libBf 0.1

bloom_filter_a2.h

00001 #ifndef BLOOM_FILTER_A2_H
00002 #define BLOOM_FILTER_A2_H
00003 
00004 #include "bloom_filter.h"
00005 #include "core.h"
00006 #include "detail/basic.h"
00007 #include "detail/spectral.h"
00008 
00009 namespace bf {
00010 
00012 template <typename Core = core<>>
00013 class a2 : public bloom_filter<a2<Core>>
00014 {
00015 public:
00016     typedef Core core_type;
00017 
00018 public:
00022     static double k(double f)
00023     {
00024         return std::floor(- (std::log(1 - std::sqrt(1 - f)) / std::log(2)));
00025     }
00026 
00034     static double capacity(unsigned k, unsigned m)
00035     {
00036         return std::floor(m / (2 * k) * std::log(2));
00037     }
00038 
00046     a2(core_type&& core, size_t capacity = 0)
00047       : items_(0)
00048       , capacity_(capacity)
00049       , core1_(core)
00050       , core2_(core1_)
00051     {
00052         if (core1_.store.size() != core2_.store.size())
00053             throw std::invalid_argument("different store sizes");
00054 
00055         if (core1_.store.width() != 1)
00056             throw std::invalid_argument("width of store 1 too large");
00057 
00058         if (core2_.store.width() != 1)
00059             throw std::invalid_argument("width of store 2 too large");
00060 
00061         if (! capacity_)
00062         {
00063             capacity_ = a2<Core>::capacity(core1_.hash.k(), 
00064                     core1_.store.size());
00065             if (! capacity_)
00066                 capacity_ = 1;  // TODO: Find a good default value.
00067         }
00068     }
00069 
00070     template <typename T>
00071     void add(const T& x)
00072     {
00073         auto pos = core1_.positions(x);
00074         if (detail::spectral::minimum(pos, core1_.store))
00075             return;
00076 
00077         for (auto i : pos)
00078             core1_.store.increment(i);
00079 
00080         if (++items_ <= capacity_)
00081             return;
00082 
00083         core2_.store.reset();
00084         core1_.swap(core2_);
00085         for (auto i : pos)
00086             core1_.store.increment(i);
00087 
00088         items_ = 1;
00089     }
00090 
00091     template <typename T>
00092     void remove(const T& x) = delete;
00093 
00094     template <typename T>
00095     unsigned count(const T& x) const
00096     {
00097         auto pos = core1_.positions(x);
00098         auto cnt = detail::spectral::minimum(pos, core1_.store);
00099         if (cnt)
00100             return cnt;
00101 
00102         pos = core2_.positions(x);
00103         return detail::spectral::minimum(pos, core2_.store);
00104     }
00105 
00108     const core_type& core1() const
00109     {
00110         return core1_;
00111     }
00112 
00115     const core_type& core2() const
00116     {
00117         return core2_;
00118     }
00119 
00121     void clear()
00122     {
00123         core1_.store.reset();
00124         core2_.store.reset();
00125     }
00126 
00127     std::string to_string() const
00128     {
00129         std::string str = core1_.store.to_string();
00130         str.push_back('\n');
00131         str += core2_.store.to_string();
00132 
00133         return str;
00134     }
00135 
00136 private:
00137     std::size_t items_;     
00138     std::size_t capacity_;  
00139     core_type core1_;
00140     core_type core2_;
00141 };
00142 
00143 template <
00144     typename Elem
00145  ,  typename Traits
00146  ,  typename Core
00147 >
00148 std::basic_ostream<Elem, Traits>& operator<<(
00149         std::basic_ostream<Elem, Traits>& os, const bf::a2<Core>& b)
00150 {
00151     os << b.to_string();
00152     return os;
00153 }
00154 
00155 } // namespace bf
00156 
00157 #endif
 All Classes Functions Variables