libStatGen Software  1
PackedVector.h
1 /*
2  * Copyright (C) 2010 Regents of the University of Michigan
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef __PACKEDVECTOR_H
19 #define __PACKEDVECTOR_H
20 
21 
22 // STL:
23 #include <ostream>
24 #include <sstream>
25 #include <string>
26 
27 #include "Generic.h"
28 
29 
30 //
31 // This file implements a packed vector template based on the
32 // getter/setter code used in MemoryMapArray.h
33 //
34 
35 
36 template <
37 uint32_t accessorFunc(std::vector<uint8_t> &base, uint32_t index),
38 void setterFunc(std::vector<uint8_t> &base, uint32_t index, uint32_t value),
39 size_t elementCount2BytesFunc(uint32_t elementCount)
40 >
42 {
43 protected:
44  std::vector<uint8_t> m_data;
45  size_t m_elementCount;
46  double m_growthRateMultiplier;
47  double m_growthRateAdder;
48 public:
49  PackedVector() :
50  m_elementCount(0),
51  m_growthRateMultiplier(1.20),
52  m_growthRateAdder(128) {;}
53 
54  // accessing
55  inline uint32_t operator[](uint32_t i)
56  {
57  return accessorFunc(m_data, i);
58  }
59  inline void set(uint32_t i, uint32_t v)
60  {
61  setterFunc(m_data, i, v);
62  }
63 
64  size_t getElementCount() const
65  {
66  return m_elementCount;
67  }
68 
69  double getUtilization() {
70  return elementCount2BytesFunc(m_elementCount) / (double) m_data.capacity();
71  }
72 
73  void reserve(uint32_t reserveElements) {
74  m_data.reserve(elementCount2BytesFunc(reserveElements));
75  }
76 
77  size_t size() {return m_elementCount;}
78 
79  void resize(uint32_t newSize) {
80  m_elementCount = newSize;
81  m_data.resize(elementCount2BytesFunc(m_elementCount));
82  }
83 
84  // it's a bit of a challenge to optimize this...
85  void push_back(uint32_t value) {
86  m_elementCount++;
87  if(elementCount2BytesFunc(m_elementCount) >= m_data.size()) {
88 
89  if( (elementCount2BytesFunc(m_elementCount)) > m_data.capacity())
90  {
91  size_t newCapacity = (size_t) (m_data.capacity() * m_growthRateMultiplier);
92 
93  // for small capacities, small fractional multipliers don't work,
94  // so we check and do a linear increase in those cases:
95  if(newCapacity == m_data.capacity()) {
96  newCapacity = (size_t) (m_data.capacity() + m_growthRateAdder);
97  }
98 
99  m_data.reserve(newCapacity);
100  }
101 
102  }
103  m_data.resize(elementCount2BytesFunc(m_elementCount));
104  set(m_elementCount-1, value);
105  }
106 };
107 
108 typedef PackedVector<
109 PackedAccess_1Bit,
110 PackedAssign_1Bit,
111 Packed1BitElementCount2Bytes
113 
114 typedef PackedVector<
115 PackedAccess_2Bit,
116 PackedAssign_2Bit,
117 Packed2BitElementCount2Bytes
119 
120 typedef PackedVector<
121 PackedAccess_4Bit,
122 PackedAssign_4Bit,
123 Packed4BitElementCount2Bytes
125 
126 #endif