libBf 0.1

store.h

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
 All Classes Functions Variables