libBf 0.1
|
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