Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on Aug 7th, 2012  |  syntax: None  |  size: 21.98 KB  |  hits: 8  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. /*
  2.  *********************************************************************
  3.  *                                                                   *
  4.  *                           Open Bloom Filter                       *
  5.  *                                                                   *
  6.  * Author: Arash Partow - 2000                                       *
  7.  * URL: http://www.partow.net                                        *
  8.  * URL: http://www.partow.net/programming/hashfunctions/index.html   *
  9.  *                                                                   *
  10.  * Copyright notice:                                                 *
  11.  * Free use of the Open Bloom Filter Library is permitted under the  *
  12.  * guidelines and in accordance with the most current version of the *
  13.  * Common Public License.                                            *
  14.  * http://www.opensource.org/licenses/cpl1.0.php                     *
  15.  *                                                                   *
  16.  *********************************************************************
  17. */
  18.  
  19.  
  20. #ifndef INCLUDE_BLOOM_FILTER_HPP
  21. #define INCLUDE_BLOOM_FILTER_HPP
  22.  
  23. #include <cstddef>
  24. #include <algorithm>
  25. #include <cmath>
  26. #include <limits>
  27. #include <string>
  28. #include <vector>
  29.  
  30.  
  31. static const std::size_t bits_per_char = 0x08;    // 8 bits in 1 char(unsigned)
  32. static const unsigned char bit_mask[bits_per_char] = {
  33.                                                        0x01,  //00000001
  34.                                                        0x02,  //00000010
  35.                                                        0x04,  //00000100
  36.                                                        0x08,  //00001000
  37.                                                        0x10,  //00010000
  38.                                                        0x20,  //00100000
  39.                                                        0x40,  //01000000
  40.                                                        0x80   //10000000
  41.                                                      };
  42.  
  43. class bloom_parameters
  44. {
  45. public:
  46.  
  47.    bloom_parameters()
  48.    : minimum_size(1),
  49.      maximum_size(std::numeric_limits<unsigned long long int>::max()),
  50.      minimum_number_of_hashes(1),
  51.      maximum_number_of_hashes(std::numeric_limits<unsigned int>::max()),
  52.      projected_element_count(10000),
  53.      false_positive_probability(1.0 / projected_element_count),
  54.      random_seed(0xA5A5A5A55A5A5A5AULL)
  55.    {}
  56.  
  57.    virtual ~bloom_parameters()
  58.    {}
  59.  
  60.    inline bool operator!()
  61.    {
  62.       return (minimum_size > maximum_size)      ||
  63.              (minimum_number_of_hashes > maximum_number_of_hashes) ||
  64.              (minimum_number_of_hashes < 1)     ||
  65.              (0 == maximum_number_of_hashes)    ||
  66.              (0 == projected_element_count)     ||
  67.              (false_positive_probability < 0.0) ||
  68.              (std::numeric_limits<double>::infinity() == std::abs(false_positive_probability)) ||
  69.              (0 == random_seed)                 ||
  70.              (0xFFFFFFFFFFFFFFFFULL == random_seed);
  71.    }
  72.  
  73.    //Allowed min/max size of the bloom filter in bits
  74.    unsigned long long int minimum_size;
  75.    unsigned long long int maximum_size;
  76.  
  77.    //Allowed min/max number of hash functions
  78.    unsigned int minimum_number_of_hashes;
  79.    unsigned int maximum_number_of_hashes;
  80.  
  81.    //The approximate number of elements to be inserted
  82.    //into the bloom filter, should be within one order
  83.    //of magnitude. The default is 10000.
  84.    unsigned long long int projected_element_count;
  85.  
  86.    //The approximate false positive probability expected
  87.    //from the bloom filter. The default is the reciprocal
  88.    //of the projected_element_count.
  89.    double false_positive_probability;
  90.  
  91.    unsigned long long int random_seed;
  92.  
  93.    struct optimal_parameters_t
  94.    {
  95.       optimal_parameters_t()
  96.       : number_of_hashes(0),
  97.         table_size(0)
  98.       {}
  99.  
  100.       unsigned int number_of_hashes;
  101.       unsigned long long int table_size;
  102.    };
  103.  
  104.    optimal_parameters_t optimal_parameters;
  105.  
  106.    virtual bool compute_optimal_parameters()
  107.    {
  108.       /*
  109.         Note:
  110.         The following will attempt to find the number of hash functions
  111.         and minimum amount of storage bits required to construct a bloom
  112.         filter consistent with the user defined false positive probability
  113.         and estimated element insertion count.
  114.       */
  115.  
  116.       if (!(*this))
  117.          return false;
  118.  
  119.       double min_m = std::numeric_limits<double>::infinity();
  120.       double min_k = 0.0;
  121.       double curr_m = 0.0;
  122.       double k = 1.0;
  123.  
  124.       while (k < 1000.0)
  125.       {
  126.          double numerator   = (- k * projected_element_count);
  127.          double denominator = std::log(1.0 - std::pow(false_positive_probability, 1.0 / k));
  128.          curr_m = numerator / denominator;
  129.          if (curr_m < min_m)
  130.          {
  131.             min_m = curr_m;
  132.             min_k = k;
  133.          }
  134.          k += 1.0;
  135.       }
  136.  
  137.       optimal_parameters_t& optp = optimal_parameters;
  138.  
  139.       optp.number_of_hashes = static_cast<unsigned int>(min_k);
  140.       optp.table_size = static_cast<unsigned long long int>(min_m);
  141.       optp.table_size += (((optp.table_size % bits_per_char) != 0) ? (bits_per_char - (optp.table_size % bits_per_char)) : 0);
  142.  
  143.       if (optp.number_of_hashes < minimum_number_of_hashes)
  144.          optp.number_of_hashes = minimum_number_of_hashes;
  145.       else if (optp.number_of_hashes > maximum_number_of_hashes)
  146.          optp.number_of_hashes = maximum_number_of_hashes;
  147.  
  148.       if (optp.table_size < minimum_size)
  149.          optp.table_size = minimum_size;
  150.       else if (optp.table_size > maximum_size)
  151.          optp.table_size = maximum_size;
  152.  
  153.       return true;
  154.    }
  155.  
  156. };
  157.  
  158. class bloom_filter
  159. {
  160. protected:
  161.  
  162.    typedef unsigned int bloom_type;
  163.    typedef unsigned char cell_type;
  164.  
  165. public:
  166.  
  167.    bloom_filter()
  168.    : bit_table_(0),
  169.      salt_count_(0),
  170.      table_size_(0),
  171.      raw_table_size_(0),
  172.      projected_element_count_(0),
  173.      inserted_element_count_(0),
  174.      random_seed_(0),
  175.      desired_false_positive_probability_(0.0)
  176.    {}
  177.  
  178.    bloom_filter(const bloom_parameters& p)
  179.    : bit_table_(0),
  180.      projected_element_count_(p.projected_element_count),
  181.      inserted_element_count_(0),
  182.      random_seed_((p.random_seed * 0xA5A5A5A5) + 1),
  183.      desired_false_positive_probability_(p.false_positive_probability)
  184.    {
  185.       salt_count_ = p.optimal_parameters.number_of_hashes;
  186.       table_size_ = p.optimal_parameters.table_size;
  187.       generate_unique_salt();
  188.       raw_table_size_ = table_size_ / bits_per_char;
  189.       bit_table_ = new cell_type[static_cast<std::size_t>(raw_table_size_)];
  190.       std::fill_n(bit_table_,raw_table_size_,0x00);
  191.    }
  192.  
  193.    bloom_filter(const bloom_filter& filter)
  194.    {
  195.       this->operator=(filter);
  196.    }
  197.  
  198.    inline bool operator == (const bloom_filter& f) const
  199.    {
  200.       if (this != &f)
  201.       {
  202.          return
  203.             (salt_count_                         == f.salt_count_)                         &&
  204.             (table_size_                         == f.table_size_)                         &&
  205.             (raw_table_size_                     == f.raw_table_size_)                     &&
  206.             (projected_element_count_   == f.projected_element_count_)   &&
  207.             (inserted_element_count_             == f.inserted_element_count_)             &&
  208.             (random_seed_                        == f.random_seed_)                        &&
  209.             (desired_false_positive_probability_ == f.desired_false_positive_probability_) &&
  210.             (salt_                               == f.salt_)                               &&
  211.             std::equal(f.bit_table_,f.bit_table_ + raw_table_size_,bit_table_);
  212.       }
  213.       else
  214.          return true;
  215.    }
  216.  
  217.    inline bool operator != (const bloom_filter& f) const
  218.    {
  219.       return !operator==(f);
  220.    }
  221.  
  222.    inline bloom_filter& operator = (const bloom_filter& f)
  223.    {
  224.       if (this != &f)
  225.       {
  226.          salt_count_ = f.salt_count_;
  227.          table_size_ = f.table_size_;
  228.          raw_table_size_ = f.raw_table_size_;
  229.          projected_element_count_ = f.projected_element_count_;
  230.          inserted_element_count_ = f.inserted_element_count_;
  231.          random_seed_ = f.random_seed_;
  232.          desired_false_positive_probability_ = f.desired_false_positive_probability_;
  233.          delete[] bit_table_;
  234.          bit_table_ = new cell_type[static_cast<std::size_t>(raw_table_size_)];
  235.          std::copy(f.bit_table_,f.bit_table_ + raw_table_size_,bit_table_);
  236.          salt_ = f.salt_;
  237.       }
  238.       return *this;
  239.    }
  240.  
  241.    virtual ~bloom_filter()
  242.    {
  243.       delete[] bit_table_;
  244.    }
  245.  
  246.    inline bool operator!() const
  247.    {
  248.       return (0 == table_size_);
  249.    }
  250.  
  251.    inline void clear()
  252.    {
  253.       std::fill_n(bit_table_,raw_table_size_,0x00);
  254.       inserted_element_count_ = 0;
  255.    }
  256.  
  257.    inline void insert(const unsigned char* key_begin, const std::size_t& length)
  258.    {
  259.       std::size_t bit_index = 0;
  260.       std::size_t bit = 0;
  261.       for (std::size_t i = 0; i < salt_.size(); ++i)
  262.       {
  263.          compute_indices(hash_ap(key_begin,length,salt_[i]),bit_index,bit);
  264.          bit_table_[bit_index / bits_per_char] |= bit_mask[bit];
  265.       }
  266.       ++inserted_element_count_;
  267.    }
  268.  
  269.    template<typename T>
  270.    inline void insert(const T& t)
  271.    {
  272.       // Note: T must be a C++ POD type.
  273.       insert(reinterpret_cast<const unsigned char*>(&t),sizeof(T));
  274.    }
  275.  
  276.    inline void insert(const std::string& key)
  277.    {
  278.       insert(reinterpret_cast<const unsigned char*>(key.c_str()),key.size());
  279.    }
  280.  
  281.    inline void insert(const char* data, const std::size_t& length)
  282.    {
  283.       insert(reinterpret_cast<const unsigned char*>(data),length);
  284.    }
  285.  
  286.    template<typename InputIterator>
  287.    inline void insert(const InputIterator begin, const InputIterator end)
  288.    {
  289.       InputIterator itr = begin;
  290.       while (end != itr)
  291.       {
  292.          insert(*(itr++));
  293.       }
  294.    }
  295.  
  296.    inline virtual bool contains(const unsigned char* key_begin, const std::size_t length) const
  297.    {
  298.       std::size_t bit_index = 0;
  299.       std::size_t bit = 0;
  300.       for (std::size_t i = 0; i < salt_.size(); ++i)
  301.       {
  302.          compute_indices(hash_ap(key_begin,length,salt_[i]),bit_index,bit);
  303.          if ((bit_table_[bit_index / bits_per_char] & bit_mask[bit]) != bit_mask[bit])
  304.          {
  305.             return false;
  306.          }
  307.       }
  308.       return true;
  309.    }
  310.  
  311.    template<typename T>
  312.    inline bool contains(const T& t) const
  313.    {
  314.       return contains(reinterpret_cast<const unsigned char*>(&t),static_cast<std::size_t>(sizeof(T)));
  315.    }
  316.  
  317.    inline bool contains(const std::string& key) const
  318.    {
  319.       return contains(reinterpret_cast<const unsigned char*>(key.c_str()),key.size());
  320.    }
  321.  
  322.    inline bool contains(const char* data, const std::size_t& length) const
  323.    {
  324.       return contains(reinterpret_cast<const unsigned char*>(data),length);
  325.    }
  326.  
  327.    template<typename InputIterator>
  328.    inline InputIterator contains_all(const InputIterator begin, const InputIterator end) const
  329.    {
  330.       InputIterator itr = begin;
  331.       while (end != itr)
  332.       {
  333.          if (!contains(*itr))
  334.          {
  335.             return itr;
  336.          }
  337.          ++itr;
  338.       }
  339.       return end;
  340.    }
  341.  
  342.    template<typename InputIterator>
  343.    inline InputIterator contains_none(const InputIterator begin, const InputIterator end) const
  344.    {
  345.       InputIterator itr = begin;
  346.       while (end != itr)
  347.       {
  348.          if (contains(*itr))
  349.          {
  350.             return itr;
  351.          }
  352.          ++itr;
  353.       }
  354.       return end;
  355.    }
  356.  
  357.    inline virtual unsigned long long int size() const
  358.    {
  359.       return table_size_;
  360.    }
  361.  
  362.    inline std::size_t element_count() const
  363.    {
  364.       return inserted_element_count_;
  365.    }
  366.  
  367.    inline double effective_fpp() const
  368.    {
  369.       /*
  370.         Note:
  371.         The effective false positive probability is calculated using the
  372.         designated table size and hash function count in conjunction with
  373.         the current number of inserted elements - not the user defined
  374.         predicated/expected number of inserted elements.
  375.       */
  376.       return std::pow(1.0 - std::exp(-1.0 * salt_.size() * inserted_element_count_ / size()), 1.0 * salt_.size());
  377.    }
  378.  
  379.    inline bloom_filter& operator &= (const bloom_filter& f)
  380.    {
  381.       /* intersection */
  382.       if (
  383.           (salt_count_  == f.salt_count_) &&
  384.           (table_size_  == f.table_size_) &&
  385.           (random_seed_ == f.random_seed_)
  386.          )
  387.       {
  388.          for (std::size_t i = 0; i < raw_table_size_; ++i)
  389.          {
  390.             bit_table_[i] &= f.bit_table_[i];
  391.          }
  392.       }
  393.       return *this;
  394.    }
  395.  
  396.    inline bloom_filter& operator |= (const bloom_filter& f)
  397.    {
  398.       /* union */
  399.       if (
  400.           (salt_count_  == f.salt_count_) &&
  401.           (table_size_  == f.table_size_) &&
  402.           (random_seed_ == f.random_seed_)
  403.          )
  404.       {
  405.          for (std::size_t i = 0; i < raw_table_size_; ++i)
  406.          {
  407.             bit_table_[i] |= f.bit_table_[i];
  408.          }
  409.       }
  410.       return *this;
  411.    }
  412.  
  413.    inline bloom_filter& operator ^= (const bloom_filter& f)
  414.    {
  415.       /* difference */
  416.       if (
  417.           (salt_count_  == f.salt_count_) &&
  418.           (table_size_  == f.table_size_) &&
  419.           (random_seed_ == f.random_seed_)
  420.          )
  421.       {
  422.          for (std::size_t i = 0; i < raw_table_size_; ++i)
  423.          {
  424.             bit_table_[i] ^= f.bit_table_[i];
  425.          }
  426.       }
  427.       return *this;
  428.    }
  429.  
  430.    inline const cell_type* table() const
  431.    {
  432.       return bit_table_;
  433.    }
  434.  
  435.    inline std::size_t hash_count()
  436.    {
  437.       return salt_.size();
  438.    }
  439.  
  440. protected:
  441.  
  442.    inline virtual void compute_indices(const bloom_type& hash, std::size_t& bit_index, std::size_t& bit) const
  443.    {
  444.       bit_index = hash % table_size_;
  445.       bit = bit_index % bits_per_char;
  446.    }
  447.  
  448.    void generate_unique_salt()
  449.    {
  450.       /*
  451.         Note:
  452.         A distinct hash function need not be implementation-wise
  453.         distinct. In the current implementation "seeding" a common
  454.         hash function with different values seems to be adequate.
  455.       */
  456.       const unsigned int predef_salt_count = 128;
  457.       static const bloom_type predef_salt[predef_salt_count] =
  458.                                  {
  459.                                     0xAAAAAAAA, 0x55555555, 0x33333333, 0xCCCCCCCC,
  460.                                     0x66666666, 0x99999999, 0xB5B5B5B5, 0x4B4B4B4B,
  461.                                     0xAA55AA55, 0x55335533, 0x33CC33CC, 0xCC66CC66,
  462.                                     0x66996699, 0x99B599B5, 0xB54BB54B, 0x4BAA4BAA,
  463.                                     0xAA33AA33, 0x55CC55CC, 0x33663366, 0xCC99CC99,
  464.                                     0x66B566B5, 0x994B994B, 0xB5AAB5AA, 0xAAAAAA33,
  465.                                     0x555555CC, 0x33333366, 0xCCCCCC99, 0x666666B5,
  466.                                     0x9999994B, 0xB5B5B5AA, 0xFFFFFFFF, 0xFFFF0000,
  467.                                     0xB823D5EB, 0xC1191CDF, 0xF623AEB3, 0xDB58499F,
  468.                                     0xC8D42E70, 0xB173F616, 0xA91A5967, 0xDA427D63,
  469.                                     0xB1E8A2EA, 0xF6C0D155, 0x4909FEA3, 0xA68CC6A7,
  470.                                     0xC395E782, 0xA26057EB, 0x0CD5DA28, 0x467C5492,
  471.                                     0xF15E6982, 0x61C6FAD3, 0x9615E352, 0x6E9E355A,
  472.                                     0x689B563E, 0x0C9831A8, 0x6753C18B, 0xA622689B,
  473.                                     0x8CA63C47, 0x42CC2884, 0x8E89919B, 0x6EDBD7D3,
  474.                                     0x15B6796C, 0x1D6FDFE4, 0x63FF9092, 0xE7401432,
  475.                                     0xEFFE9412, 0xAEAEDF79, 0x9F245A31, 0x83C136FC,
  476.                                     0xC3DA4A8C, 0xA5112C8C, 0x5271F491, 0x9A948DAB,
  477.                                     0xCEE59A8D, 0xB5F525AB, 0x59D13217, 0x24E7C331,
  478.                                     0x697C2103, 0x84B0A460, 0x86156DA9, 0xAEF2AC68,
  479.                                     0x23243DA5, 0x3F649643, 0x5FA495A8, 0x67710DF8,
  480.                                     0x9A6C499E, 0xDCFB0227, 0x46A43433, 0x1832B07A,
  481.                                     0xC46AFF3C, 0xB9C8FFF0, 0xC9500467, 0x34431BDF,
  482.                                     0xB652432B, 0xE367F12B, 0x427F4C1B, 0x224C006E,
  483.                                     0x2E7E5A89, 0x96F99AA5, 0x0BEB452A, 0x2FD87C39,
  484.                                     0x74B2E1FB, 0x222EFD24, 0xF357F60C, 0x440FCB1E,
  485.                                     0x8BBE030F, 0x6704DC29, 0x1144D12F, 0x948B1355,
  486.                                     0x6D8FD7E9, 0x1C11A014, 0xADD1592F, 0xFB3C712E,
  487.                                     0xFC77642F, 0xF9C4CE8C, 0x31312FB9, 0x08B0DD79,
  488.                                     0x318FA6E7, 0xC040D23D, 0xC0589AA7, 0x0CA5C075,
  489.                                     0xF874B172, 0x0CF914D5, 0x784D3280, 0x4E8CFEBC,
  490.                                     0xC569F575, 0xCDB2A091, 0x2CC016B4, 0x5C5F4421
  491.                                  };
  492.  
  493.       if (salt_count_ <= predef_salt_count)
  494.       {
  495.          std::copy(predef_salt,
  496.                    predef_salt + salt_count_,
  497.                    std::back_inserter(salt_));
  498.           for (unsigned int i = 0; i < salt_.size(); ++i)
  499.           {
  500.             /*
  501.               Note:
  502.               This is done to integrate the user defined random seed,
  503.               so as to allow for the generation of unique bloom filter
  504.               instances.
  505.             */
  506.             salt_[i] = salt_[i] * salt_[(i + 3) % salt_.size()] + static_cast<bloom_type>(random_seed_);
  507.           }
  508.       }
  509.       else
  510.       {
  511.          std::copy(predef_salt,predef_salt + predef_salt_count,std::back_inserter(salt_));
  512.          srand(static_cast<unsigned int>(random_seed_));
  513.          while (salt_.size() < salt_count_)
  514.          {
  515.             bloom_type current_salt = static_cast<bloom_type>(rand()) * static_cast<bloom_type>(rand());
  516.             if (0 == current_salt) continue;
  517.             if (salt_.end() == std::find(salt_.begin(), salt_.end(), current_salt))
  518.             {
  519.                salt_.push_back(current_salt);
  520.             }
  521.          }
  522.       }
  523.    }
  524.  
  525.    inline bloom_type hash_ap(const unsigned char* begin, std::size_t remaining_length, bloom_type hash) const
  526.    {
  527.       const unsigned char* itr = begin;
  528.       unsigned int loop = 0;
  529.       while (remaining_length >= 8)
  530.       {
  531.          const unsigned int& i1 = *(reinterpret_cast<const unsigned int*>(itr)); itr += sizeof(unsigned int);
  532.          const unsigned int& i2 = *(reinterpret_cast<const unsigned int*>(itr)); itr += sizeof(unsigned int);
  533.          hash ^= (hash <<  7) ^  i1 * (hash >> 3) ^
  534.               (~((hash << 11) + (i2 ^ (hash >> 5))));
  535.          remaining_length -= 8;
  536.       }
  537.       while (remaining_length >= 4)
  538.       {
  539.          const unsigned int& i = *(reinterpret_cast<const unsigned int*>(itr));
  540.          if (loop & 0x01)
  541.             hash ^=    (hash <<  7) ^  i * (hash >> 3);
  542.          else
  543.             hash ^= (~((hash << 11) + (i ^ (hash >> 5))));
  544.          ++loop;
  545.          remaining_length -= 4;
  546.          itr += sizeof(unsigned int);
  547.       }
  548.       while (remaining_length >= 2)
  549.       {
  550.          const unsigned short& i = *(reinterpret_cast<const unsigned short*>(itr));
  551.          if (loop & 0x01)
  552.             hash ^=    (hash <<  7) ^  i * (hash >> 3);
  553.          else
  554.             hash ^= (~((hash << 11) + (i ^ (hash >> 5))));
  555.          ++loop;
  556.          remaining_length -= 2;
  557.          itr += sizeof(unsigned short);
  558.       }
  559.       if (remaining_length)
  560.       {
  561.          hash += ((*itr) ^ (hash * 0xA5A5A5A5)) + loop;
  562.       }
  563.       return hash;
  564.    }
  565.  
  566.    std::vector<bloom_type> salt_;
  567.    unsigned char*          bit_table_;
  568.    unsigned int            salt_count_;
  569.    unsigned long long int  table_size_;
  570.    unsigned long long int  raw_table_size_;
  571.    unsigned long long int  projected_element_count_;
  572.    unsigned int            inserted_element_count_;
  573.    unsigned long long int  random_seed_;
  574.    double                  desired_false_positive_probability_;
  575. };
  576.  
  577. inline bloom_filter operator & (const bloom_filter& a, const bloom_filter& b)
  578. {
  579.    bloom_filter result = a;
  580.    result &= b;
  581.    return result;
  582. }
  583.  
  584. inline bloom_filter operator | (const bloom_filter& a, const bloom_filter& b)
  585. {
  586.    bloom_filter result = a;
  587.    result |= b;
  588.    return result;
  589. }
  590.  
  591. inline bloom_filter operator ^ (const bloom_filter& a, const bloom_filter& b)
  592. {
  593.    bloom_filter result = a;
  594.    result ^= b;
  595.    return result;
  596. }
  597.  
  598. class compressible_bloom_filter : public bloom_filter
  599. {
  600. public:
  601.  
  602.    compressible_bloom_filter(const bloom_parameters& p)
  603.    : bloom_filter(p)
  604.    {
  605.       size_list.push_back(table_size_);
  606.    }
  607.  
  608.    inline virtual unsigned long long int size() const
  609.    {
  610.       return size_list.back();
  611.    }
  612.  
  613.    inline bool compress(const double& percentage)
  614.    {
  615.       if ((0.0 >= percentage) || (percentage >= 100.0))
  616.       {
  617.          return false;
  618.       }
  619.  
  620.       unsigned long long int original_table_size = size_list.back();
  621.       unsigned long long int new_table_size = static_cast<unsigned long long int>((size_list.back() * (1.0 - (percentage / 100.0))));
  622.       new_table_size -= (((new_table_size % bits_per_char) != 0) ? (new_table_size % bits_per_char) : 0);
  623.  
  624.       if ((bits_per_char > new_table_size) || (new_table_size >= original_table_size))
  625.       {
  626.          return false;
  627.       }
  628.  
  629.       desired_false_positive_probability_ = effective_fpp();
  630.       cell_type* tmp = new cell_type[static_cast<std::size_t>(new_table_size / bits_per_char)];
  631.       std::copy(bit_table_, bit_table_ + (new_table_size / bits_per_char), tmp);
  632.       cell_type* itr = bit_table_ + (new_table_size / bits_per_char);
  633.       cell_type* end = bit_table_ + (original_table_size / bits_per_char);
  634.       cell_type* itr_tmp = tmp;
  635.  
  636.       while (end != itr)
  637.       {
  638.          *(itr_tmp++) |= (*itr++);
  639.       }
  640.  
  641.       delete[] bit_table_;
  642.       bit_table_ = tmp;
  643.       size_list.push_back(new_table_size);
  644.  
  645.       return true;
  646.    }
  647.  
  648. private:
  649.  
  650.    inline virtual void compute_indices(const bloom_type& hash, std::size_t& bit_index, std::size_t& bit) const
  651.    {
  652.       bit_index = hash;
  653.       for (std::size_t i = 0; i < size_list.size(); ++i)
  654.       {
  655.          bit_index %= size_list[i];
  656.       }
  657.       bit = bit_index % bits_per_char;
  658.    }
  659.  
  660.    std::vector<unsigned long long int> size_list;
  661. };
  662.  
  663. #endif
  664.  
  665.  
  666. /*
  667.   Note 1:
  668.   If it can be guaranteed that bits_per_char will be of the form 2^n then
  669.   the following optimization can be used:
  670.  
  671.   hash_table[bit_index >> n] |= bit_mask[bit_index & (bits_per_char - 1)];
  672.  
  673.   Note 2:
  674.   For performance reasons where possible when allocating memory it should
  675.   be aligned (aligned_alloc) according to the architecture being used.
  676. */