49 #include <ndn-cxx/util/exception.hpp> 74 class bloom_parameters
80 maximum_size(std::numeric_limits<unsigned int>::max()),
81 minimum_number_of_hashes(1),
82 maximum_number_of_hashes(std::numeric_limits<unsigned int>::max()),
83 projected_element_count(200),
84 false_positive_probability(1.0 / projected_element_count),
85 random_seed(0xA5A5A5A55A5A5A5AULL)
88 inline bool operator!()
90 return (minimum_size > maximum_size) ||
91 (minimum_number_of_hashes > maximum_number_of_hashes) ||
92 (minimum_number_of_hashes < 1) ||
93 (0 == maximum_number_of_hashes) ||
94 (0 == projected_element_count) ||
95 (false_positive_probability < 0.0) ||
96 (std::numeric_limits<double>::infinity() == std::abs(false_positive_probability)) ||
98 (0xFFFFFFFFFFFFFFFFULL == random_seed);
102 unsigned int minimum_size;
103 unsigned int maximum_size;
106 unsigned int minimum_number_of_hashes;
107 unsigned int maximum_number_of_hashes;
112 unsigned int projected_element_count;
117 double false_positive_probability;
119 unsigned long long int random_seed;
121 struct optimal_parameters_t
123 optimal_parameters_t()
124 : number_of_hashes(0),
128 unsigned int number_of_hashes;
129 unsigned int table_size;
132 optimal_parameters_t optimal_parameters;
134 bool compute_optimal_parameters()
147 double min_m = std::numeric_limits<double>::infinity();
153 const double numerator = (- k * projected_element_count);
154 const double denominator = std::log(1.0 - std::pow(false_positive_probability, 1.0 / k));
156 const double curr_m = numerator / denominator;
167 optimal_parameters_t& optp = optimal_parameters;
169 optp.number_of_hashes =
static_cast<unsigned int>(min_k);
171 optp.table_size =
static_cast<unsigned int>(min_m);
175 if (optp.number_of_hashes < minimum_number_of_hashes)
176 optp.number_of_hashes = minimum_number_of_hashes;
177 else if (optp.number_of_hashes > maximum_number_of_hashes)
178 optp.number_of_hashes = maximum_number_of_hashes;
180 if (optp.table_size < minimum_size)
181 optp.table_size = minimum_size;
182 else if (optp.table_size > maximum_size)
183 optp.table_size = maximum_size;
192 : projected_element_count_(p.projected_element_count),
193 inserted_element_count_(0),
194 random_seed_((p.random_seed * 0xA5A5A5A5) + 1),
195 desired_false_positive_probability_(p.false_positive_probability)
197 salt_count_ = p.optimal_parameters.number_of_hashes;
198 table_size_ = p.optimal_parameters.table_size;
200 generate_unique_salt();
202 bit_table_.resize(table_size_ / bits_per_char, static_cast<cell_type>(0x00));
205 static bloom_parameters
207 double false_positive_probability)
210 p.projected_element_count = projected_element_count;
211 p.false_positive_probability = false_positive_probability;
213 if (!p.compute_optimal_parameters()) {
220 double false_positive_probability)
226 double false_positive_probability,
227 const ndn::name::Component& bfName)
228 :
BloomFilter(projected_element_count, false_positive_probability)
230 std::vector<cell_type> table(bfName.value_begin(), bfName.value_end());
232 NDN_THROW(
Error(
"Bloom filter cannot be decoded!"));
234 bit_table_ = std::move(table);
240 name.appendNumber(projected_element_count_);
241 name.appendNumber(static_cast<uint64_t>(desired_false_positive_probability_ * 1000));
242 name.append(bit_table_.begin(), bit_table_.end());
248 std::fill(bit_table_.begin(), bit_table_.end(),
static_cast<cell_type
>(0x00));
249 inserted_element_count_ = 0;
255 std::size_t bit_index = 0;
258 for (std::size_t i = 0; i < salt_.size(); ++i)
260 compute_indices(
murmurHash3(salt_[i], key), bit_index, bit);
265 ++inserted_element_count_;
271 std::size_t bit_index = 0;
274 for (std::size_t i = 0; i < salt_.size(); ++i)
276 compute_indices(
murmurHash3(salt_[i], key), bit_index, bit);
278 if ((bit_table_[bit_index / bits_per_char] & bit_mask[bit]) != bit_mask[bit])
288 BloomFilter::compute_indices(
const bloom_type& hash, std::size_t& bit_index, std::size_t& bit)
const 290 bit_index = hash % table_size_;
295 BloomFilter::generate_unique_salt()
303 const unsigned int predef_salt_count = 128;
305 static const bloom_type predef_salt[predef_salt_count] =
307 0xAAAAAAAA, 0x55555555, 0x33333333, 0xCCCCCCCC,
308 0x66666666, 0x99999999, 0xB5B5B5B5, 0x4B4B4B4B,
309 0xAA55AA55, 0x55335533, 0x33CC33CC, 0xCC66CC66,
310 0x66996699, 0x99B599B5, 0xB54BB54B, 0x4BAA4BAA,
311 0xAA33AA33, 0x55CC55CC, 0x33663366, 0xCC99CC99,
312 0x66B566B5, 0x994B994B, 0xB5AAB5AA, 0xAAAAAA33,
313 0x555555CC, 0x33333366, 0xCCCCCC99, 0x666666B5,
314 0x9999994B, 0xB5B5B5AA, 0xFFFFFFFF, 0xFFFF0000,
315 0xB823D5EB, 0xC1191CDF, 0xF623AEB3, 0xDB58499F,
316 0xC8D42E70, 0xB173F616, 0xA91A5967, 0xDA427D63,
317 0xB1E8A2EA, 0xF6C0D155, 0x4909FEA3, 0xA68CC6A7,
318 0xC395E782, 0xA26057EB, 0x0CD5DA28, 0x467C5492,
319 0xF15E6982, 0x61C6FAD3, 0x9615E352, 0x6E9E355A,
320 0x689B563E, 0x0C9831A8, 0x6753C18B, 0xA622689B,
321 0x8CA63C47, 0x42CC2884, 0x8E89919B, 0x6EDBD7D3,
322 0x15B6796C, 0x1D6FDFE4, 0x63FF9092, 0xE7401432,
323 0xEFFE9412, 0xAEAEDF79, 0x9F245A31, 0x83C136FC,
324 0xC3DA4A8C, 0xA5112C8C, 0x5271F491, 0x9A948DAB,
325 0xCEE59A8D, 0xB5F525AB, 0x59D13217, 0x24E7C331,
326 0x697C2103, 0x84B0A460, 0x86156DA9, 0xAEF2AC68,
327 0x23243DA5, 0x3F649643, 0x5FA495A8, 0x67710DF8,
328 0x9A6C499E, 0xDCFB0227, 0x46A43433, 0x1832B07A,
329 0xC46AFF3C, 0xB9C8FFF0, 0xC9500467, 0x34431BDF,
330 0xB652432B, 0xE367F12B, 0x427F4C1B, 0x224C006E,
331 0x2E7E5A89, 0x96F99AA5, 0x0BEB452A, 0x2FD87C39,
332 0x74B2E1FB, 0x222EFD24, 0xF357F60C, 0x440FCB1E,
333 0x8BBE030F, 0x6704DC29, 0x1144D12F, 0x948B1355,
334 0x6D8FD7E9, 0x1C11A014, 0xADD1592F, 0xFB3C712E,
335 0xFC77642F, 0xF9C4CE8C, 0x31312FB9, 0x08B0DD79,
336 0x318FA6E7, 0xC040D23D, 0xC0589AA7, 0x0CA5C075,
337 0xF874B172, 0x0CF914D5, 0x784D3280, 0x4E8CFEBC,
338 0xC569F575, 0xCDB2A091, 0x2CC016B4, 0x5C5F4421
341 if (salt_count_ <= predef_salt_count)
343 std::copy(predef_salt,
344 predef_salt + salt_count_,
345 std::back_inserter(salt_));
347 for (std::size_t i = 0; i < salt_.size(); ++i)
355 salt_[i] = salt_[i] * salt_[(i + 3) % salt_.size()] +
static_cast<bloom_type
>(random_seed_);
360 std::copy(predef_salt, predef_salt + predef_salt_count, std::back_inserter(salt_));
362 srand(static_cast<unsigned int>(random_seed_));
364 while (salt_.size() < salt_count_)
366 bloom_type current_salt =
static_cast<bloom_type
>(rand()) * static_cast<bloom_type>(rand());
368 if (0 == current_salt)
371 if (salt_.end() == std::find(salt_.begin(), salt_.end(), current_salt))
373 salt_.push_back(current_salt);
void insert(const std::string &key)
static const unsigned char bit_mask[bits_per_char]
bool contains(const std::string &key) const
static const std::size_t bits_per_char
static bloom_parameters makeParameters(unsigned int projected_element_count, double false_positive_probability)
void appendToName(ndn::Name &name) const
Append our bloom filter to the given name.
uint32_t murmurHash3(const void *key, size_t len, uint32_t seed)