libStatGen Software
1
|
00001 /* 00002 * Copyright (C) 2010 Regents of the University of Michigan 00003 * 00004 * This program is free software: you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation, either version 3 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00016 */ 00017 00018 #ifndef __PACKEDVECTOR_H 00019 #define __PACKEDVECTOR_H 00020 00021 00022 // STL: 00023 #include <ostream> 00024 #include <sstream> 00025 #include <string> 00026 00027 #include "Generic.h" 00028 00029 00030 // 00031 // This file implements a packed vector template based on the 00032 // getter/setter code used in MemoryMapArray.h 00033 // 00034 00035 00036 template < 00037 uint32_t accessorFunc(std::vector<uint8_t> &base, uint32_t index), 00038 void setterFunc(std::vector<uint8_t> &base, uint32_t index, uint32_t value), 00039 size_t elementCount2BytesFunc(uint32_t elementCount) 00040 > 00041 class PackedVector 00042 { 00043 protected: 00044 std::vector<uint8_t> m_data; 00045 size_t m_elementCount; 00046 double m_growthRateMultiplier; 00047 double m_growthRateAdder; 00048 public: 00049 PackedVector() : 00050 m_elementCount(0), 00051 m_growthRateMultiplier(1.20), 00052 m_growthRateAdder(128) {;} 00053 00054 // accessing 00055 inline uint32_t operator[](uint32_t i) 00056 { 00057 return accessorFunc(m_data, i); 00058 } 00059 inline void set(uint32_t i, uint32_t v) 00060 { 00061 setterFunc(m_data, i, v); 00062 } 00063 00064 size_t getElementCount() const 00065 { 00066 return m_elementCount; 00067 } 00068 00069 double getUtilization() { 00070 return elementCount2BytesFunc(m_elementCount) / (double) m_data.capacity(); 00071 } 00072 00073 void reserve(uint32_t reserveElements) { 00074 m_data.reserve(elementCount2BytesFunc(reserveElements)); 00075 } 00076 00077 size_t size() {return m_elementCount;} 00078 00079 void resize(uint32_t newSize) { 00080 m_elementCount = newSize; 00081 m_data.resize(elementCount2BytesFunc(m_elementCount)); 00082 } 00083 00084 // it's a bit of a challenge to optimize this... 00085 void push_back(uint32_t value) { 00086 m_elementCount++; 00087 if(elementCount2BytesFunc(m_elementCount) >= m_data.size()) { 00088 00089 if( (elementCount2BytesFunc(m_elementCount)) > m_data.capacity()) 00090 { 00091 size_t newCapacity = (size_t) (m_data.capacity() * m_growthRateMultiplier); 00092 00093 // for small capacities, small fractional multipliers don't work, 00094 // so we check and do a linear increase in those cases: 00095 if(newCapacity == m_data.capacity()) { 00096 newCapacity = (size_t) (m_data.capacity() + m_growthRateAdder); 00097 } 00098 00099 m_data.reserve(newCapacity); 00100 } 00101 00102 } 00103 m_data.resize(elementCount2BytesFunc(m_elementCount)); 00104 set(m_elementCount-1, value); 00105 } 00106 }; 00107 00108 typedef PackedVector< 00109 PackedAccess_1Bit, 00110 PackedAssign_1Bit, 00111 Packed1BitElementCount2Bytes 00112 > PackedVectorBool_t; 00113 00114 typedef PackedVector< 00115 PackedAccess_2Bit, 00116 PackedAssign_2Bit, 00117 Packed2BitElementCount2Bytes 00118 > PackedVector2Bit_t; 00119 00120 typedef PackedVector< 00121 PackedAccess_4Bit, 00122 PackedAssign_4Bit, 00123 Packed4BitElementCount2Bytes 00124 > PackedVector4Bit_t; 00125 00126 #endif