/* This file is part of Jellyfish.
Jellyfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Jellyfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jellyfish. If not, see .
*/
#ifndef __JELLYFISH_BLOOM_COMMON_HPP__
#define __JELLYFISH_BLOOM_COMMON_HPP__
#include
#include
#include
namespace jellyfish {
template
struct hash_pair { };
template >
class bloom_base {
protected:
struct prefetch_info {
size_t boff;
unsigned char* pos;
};
// The number of bits in the structure, previously known as m_, is
// know stored as d_.d()
const jflib::divisor64 d_;
const unsigned long k_;
unsigned char * const data_;
HashPair hash_fns_;
public:
typedef Key key_type;
bloom_base(size_t m, unsigned long k, unsigned char* ptr, const HashPair& fns = HashPair()) :
d_(m), k_(k), data_(ptr), hash_fns_(fns)
{ }
bloom_base(const bloom_base& rhs) = delete;
bloom_base(bloom_base&& rhs) :
d_(rhs.d_), k_(rhs.k_), data_(rhs.data_), hash_fns_(std::move(rhs.hash_fns_))
{ }
void write_bits(std::ostream& out) {
out.write((char*)data_, static_cast(this)->nb_bytes());
}
// Number of hash functions
unsigned long k() const { return k_; }
// Size of bit vector
size_t m() const { return d_.d(); }
const HashPair& hash_functions() const { return hash_fns_; }
static const double LOG2;
static const double LOG2_SQ;
static size_t opt_m(const double fp, const size_t n) {
return n * (size_t)lrint(-log(fp) / LOG2_SQ);
}
static unsigned long opt_k(const double fp) {
return lrint(-log(fp) / LOG2);
}
// Insert key k. Returns previous value of k
unsigned int insert(const Key &k) {
uint64_t hashes[2];
hash_fns_(k, hashes);
return static_cast(this)->insert__(hashes);
}
unsigned int check(const Key &k) const {
uint64_t hashes[2];
hash_fns_(k, hashes);
return static_cast(this)->check__(hashes);
}
// Limited std::map interface compatibility
class element_proxy {
Derived& bc_;
const Key& k_;
public:
element_proxy(Derived& bc, const Key& k) : bc_(bc), k_(k) { }
unsigned int operator++() {
unsigned int res = bc_.insert(k_);
return res == 0 ? 1 : 2;
}
unsigned int operator++(int) { return bc_.insert(k_); }
unsigned int operator*() const { return bc_.check(k_); }
operator unsigned int() const { return bc_.check(k_); }
};
class const_element_proxy {
const Derived& bc_;
const Key& k_;
public:
const_element_proxy(const Derived& bc, const Key& k) : bc_(bc), k_(k) { }
unsigned int operator*() const { return bc_.check(k_); }
operator unsigned int() const { return bc_.check(k_); }
};
element_proxy operator[](const Key& k) { return element_proxy(*static_cast(this), k); }
const_element_proxy operator[](const Key& k) const { return const_element_proxy(*static_cast(this), k); }
};
template
const double bloom_base::LOG2 = 0.6931471805599453;
template
const double bloom_base::LOG2_SQ = 0.4804530139182014;
}
#endif /* __JELLYFISH_BLOOM_COMMON_HPP__ */