use crate::basicqht::*;
use crate::filter::Filter;
pub use rand::rngs::StdRng;
pub use rand::{FromEntropy, Rng};
pub use std::collections::hash_map::DefaultHasher;
pub use std::hash::{Hash, Hasher};
pub use rust_dense_bitset::DenseBitSetExtended;
const FINGERPRINT_SIZE_LIMIT: usize = 8;
pub struct QQuotientHashTableD {
n_cells: usize,
n_buckets: usize,
fingerprint_size: usize,
pow_fingerprint_size: u64,
qht: DenseBitSetExtended,
}
impl QQuotientHashTableD {
pub fn new(memory_size: usize, n_buckets: usize, fingerprint_size: usize) -> Self {
if fingerprint_size > FINGERPRINT_SIZE_LIMIT {
panic!("[qQHTcd Filter] Incorrect parameters, fingerprint_size cannot exceed 8.");
} else if fingerprint_size == 0 {
panic!("[QHTc Filter] Incorrect parameters, fingerprint_size cannot be zero.");
}
if n_buckets == 0 {
panic!("[QHTc Filter] Incorrect parameters, n_buckets cannot be zero.");
}
let pow_fingerprint_size = 2u64.pow(fingerprint_size as u32);
let n_cells = memory_size / (n_buckets * fingerprint_size);
let qht = DenseBitSetExtended::with_capacity(n_cells * n_buckets * fingerprint_size);
if n_cells == 0 {
panic!("[QHT Filter] Incorrect parameters, memory size should be at least n_buckets * fingerprint_size");
}
Self {
n_cells,
n_buckets,
fingerprint_size,
pow_fingerprint_size,
qht,
}
}
fn insert_fingerprint_in_last_bucket(&mut self, address: usize, fingerprint: Fingerprint) {
for prev in 0..(self.n_buckets - 1) {
let idx = prev + 1;
let fg = self.get_fingerprint_from_bucket(address, idx);
self.insert_fingerprint_in_bucket(address, prev, fg);
}
let last_bucket = self.n_buckets - 1;
self.insert_fingerprint_in_bucket(address, last_bucket, fingerprint)
}
}
impl_basicqht!(QQuotientHashTableD);
impl Filter for QQuotientHashTableD {
fn lookup(&self, e: impl Hash) -> bool {
let fingerprint = self.get_fingerprint(&e);
let address = (get_hash(&e, 1, 0) as usize) % self.n_cells;
self.in_cell(address, fingerprint)
}
fn insert(&mut self, e: impl Hash) -> bool {
let fingerprint = self.get_fingerprint(&e);
let address = (get_hash(&e, 1, 0) as usize) % self.n_cells;
let detected = self.in_cell(address, fingerprint);
self.insert_fingerprint_in_last_bucket(address, fingerprint);
detected
}
}