libBf 0.1
|
00001 #ifndef STORE_H 00002 #define STORE_H 00003 00004 #include <cstdint> 00005 #include <stdexcept> 00006 #include <vector> 00007 #include <boost/dynamic_bitset.hpp> 00008 00009 namespace bf { 00010 00013 template <typename Derived> 00014 class store_policy 00015 { 00016 public: 00017 // TODO: decide on a reasonable interface. 00018 00019 private: 00020 // 00021 // CRTP interface 00022 // 00023 Derived& derived() 00024 { 00025 return *static_cast<Derived*>(this); 00026 } 00027 00028 const Derived& derived() const 00029 { 00030 return *static_cast<const Derived*>(this); 00031 } 00032 }; 00033 00036 template <typename Block, typename Allocator> 00037 class fixed_width : public store_policy<fixed_width<Block, Allocator>> 00038 { 00039 public: 00040 typedef Block block_type; 00041 typedef Allocator allocator_type; 00042 00043 typedef boost::dynamic_bitset<Block, Allocator> bitset; 00044 typedef typename bitset::size_type size_type; 00045 typedef std::vector<size_type> pos_vector; 00046 typedef uint64_t count_type; 00047 00048 public: 00053 fixed_width(unsigned cells, unsigned width) 00054 : bits_(cells * width) 00055 , width_(width) 00056 { 00057 if (cells == 0) 00058 throw std::invalid_argument("zero cells"); 00059 00060 if (width == 0) 00061 throw std::invalid_argument("zero width"); 00062 00063 auto max = std::numeric_limits<count_type>::digits; 00064 if (width > static_cast<decltype(width)>(max)) 00065 throw std::invalid_argument("width too large"); 00066 } 00067 00068 template <typename B, typename A> 00069 void swap(fixed_width<B, A>& store) // no throw 00070 { 00071 std::swap(bits_, store.bits_); 00072 std::swap(width_, store.width_); 00073 } 00074 00079 bool increment(size_type cell) 00080 { 00081 assert(cell < size()); 00082 00083 size_type lsb = cell * width_; 00084 for (auto i = lsb; i < lsb + width_; ++i) 00085 if (! bits_[i]) 00086 { 00087 bits_[i] = true; 00088 while (i && i > lsb) 00089 bits_[--i] = false; 00090 00091 return true; 00092 } 00093 00094 return false; 00095 } 00096 00103 bool increment(size_type cell, count_type value) 00104 { 00105 assert(cell < size()); 00106 00107 size_type lsb = cell * width_; 00108 00109 if (value >= max()) 00110 { 00111 bool r = false; 00112 for (auto i = lsb; i < lsb + width_; ++i) 00113 if (! bits_[i]) 00114 { 00115 bits_[i] = 1; 00116 if (! r) 00117 r = true; 00118 } 00119 00120 return r; 00121 } 00122 00123 bitset b(width_, value); 00124 bool carry = false; 00125 size_type i = lsb, j = 0; 00126 00127 while (i < lsb + width_) 00128 { 00129 if (bits_[i]) 00130 { 00131 if (b[j]) 00132 { 00133 bits_[i] = false; 00134 if (! carry) 00135 carry = true; 00136 } 00137 else if (carry) 00138 bits_[i] = false; 00139 } 00140 else if (b[j]) 00141 { 00142 bits_[i] = true; 00143 } 00144 else if (carry) 00145 { 00146 bits_[i] = true; 00147 carry = false; 00148 } 00149 00150 ++i; 00151 ++j; 00152 } 00153 00154 if (! carry) 00155 return true; 00156 00157 for (i = lsb; i < lsb + width_; ++i) 00158 bits_[i] = 1; 00159 00160 return false; 00161 } 00162 00167 bool decrement(size_type cell) 00168 { 00169 assert(cell < size()); 00170 00171 size_type lsb = cell * width_; 00172 for (auto i = lsb; i < lsb + width_; ++i) 00173 if (bits_[i]) 00174 { 00175 bits_[i] = false; 00176 00177 while (i && i > lsb) 00178 bits_[--i] = true; 00179 00180 return true; 00181 } 00182 00183 return false; 00184 } 00185 00190 count_type count(size_type cell) const 00191 { 00192 assert(cell < size()); 00193 00194 count_type cnt = 0, order = 1; 00195 size_type lsb = cell * width_; 00196 for (auto i = lsb; i < lsb + width_; ++i, order <<= 1) 00197 if (bits_[i]) 00198 cnt |= order; 00199 00200 return cnt; 00201 } 00202 00204 void set() 00205 { 00206 bits_.set(); 00207 } 00208 00211 void set(size_type cell) 00212 { 00213 assert(cell < size()); 00214 00215 auto lsb = cell * width_; 00216 for (auto i = lsb; i < lsb + width_; ++i) 00217 bits_[i] = true; 00218 } 00219 00223 void set(size_type cell, count_type value) 00224 { 00225 assert(cell < size()); 00226 assert(value <= max()); 00227 00228 bitset bits(width_, value); 00229 size_type i = cell * width_; 00230 for (auto bit : bits) 00231 bits_[i++] = bit; 00232 } 00233 00235 void reset() 00236 { 00237 bits_.reset(); 00238 } 00239 00242 void reset(size_type cell) 00243 { 00244 assert(cell < size()); 00245 00246 auto lsb = cell * width_; 00247 for (auto i = lsb; i < lsb + width_; ++i) 00248 bits_[i] = false; 00249 } 00250 00252 void halve() 00253 { 00254 assert(bits_.size() % 2 == 0); 00255 assert(bits_.size() > 0); 00256 00257 size_type half = bits_.size() / 2; 00258 size_type i = 0; 00259 size_type j = half; 00260 00261 while (i < half) 00262 set(i, count(i) + count(j)); 00263 00264 bits_.resize(half * width_); 00265 } 00266 00269 size_type size() const 00270 { 00271 return bits_.size() / width_; 00272 } 00273 00276 count_type max() const 00277 { 00278 return std::numeric_limits<count_type>::max() >> 00279 (std::numeric_limits<count_type>::digits - width()); 00280 } 00281 00284 bool none() const 00285 { 00286 return bits_.none(); 00287 } 00288 00291 unsigned width() const 00292 { 00293 return width_; 00294 } 00295 00299 void width(unsigned w) 00300 { 00301 assert(! "not yet tested"); 00302 00303 if (w < width_) 00304 { 00305 size_type i = 0; 00306 for (auto cell = 0; cell < bits_.size(); cell += width_) 00307 if (bits_[cell + width_]) 00308 for (auto j = 0; j < w; ++j) 00309 bits_[i++] = true; 00310 else 00311 for (auto j = 0; j < w; ++j) 00312 bits_[i++] = bits_[cell + j]; 00313 00314 bits_.resize(w * bits_.size()); 00315 } 00316 else 00317 { 00318 auto old = bits_.size(); 00319 bits_.resize(w * bits_.size()); 00320 auto i = bits_.size() / w - 1; 00321 00322 for (auto cell = old - width_ - 1; cell != 0; cell -= width_) 00323 { 00324 size_type j = 0; 00325 while (j++ < width_) 00326 bits_[i++] = bits_[cell + j]; 00327 while (j++ < w) 00328 bits_[i++] = 0; 00329 00330 i -= width_; 00331 } 00332 } 00333 00334 width_ = w; 00335 } 00336 00341 std::string to_string() const 00342 { 00343 std::string str(bits_.size(), '0'); 00344 for (size_type i = 0; i < bits_.size(); ++i) 00345 if (bits_[i]) 00346 str[i] = '1'; 00347 00348 return str; 00349 } 00350 00354 template <typename F> 00355 void each(F f) const 00356 { 00357 for (size_type cell = 0; cell < bits_.size() / width_; ++cell) 00358 f(count(cell)); 00359 } 00360 00361 private: 00362 bitset bits_; 00363 unsigned width_; 00364 }; 00365 00366 } // namespace bf 00367 00368 #endif