Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ impl<T: ToBytes> HyperLogLog<T, BuildHasherDefault<DefaultHasher>> {
}

impl<T: ToBytes, S: BuildHasher + Default + Clone> HyperLogLog<T, S> {

/// Creates a new `HyperLogLog` with `p` bits.
/// Panics if `p < 4` or if `p` is too large to shift safely.
pub fn with_hasher(p: u32, hasher_builder: S) -> Self {
Expand All @@ -103,6 +104,7 @@ impl<T: ToBytes, S: BuildHasher + Default + Clone> HyperLogLog<T, S> {
// which means max leading zeros is 64 but the smallest data type rust handles is u8
let buckets = vec![0u8; m];


HyperLogLog { p, m, buckets, hasher_builder, _marker: PhantomData }
}

Expand Down Expand Up @@ -175,4 +177,20 @@ impl<T: ToBytes, S: BuildHasher + Default + Clone> HyperLogLog<T, S> {

return Ok(())
}

pub fn reset(&mut self) {
self.buckets.fill(0);
}

pub fn get_buckets(&self) -> Vec<u8> {
self.buckets.clone()
}

pub fn get_p(&self) -> u32 {
self.p.clone()
}

pub fn get_m(&self) -> usize {
self.m.clone()
}
}
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ fn main() {
println!("Time to insert: {:.2?}", insertion_end);
println!("Time to calculate cardinality: {:.2?}", duration_cardinality);

hll.reset();
let serialized = serde_json::to_string(&hll).unwrap();
println!("{}", serialized);
let desserialized: HyperLogLog<i64> = serde_json::from_str(&serialized).unwrap();
Expand Down
74 changes: 74 additions & 0 deletions tests/reset_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use hyperloglog::HyperLogLog;

#[test]
fn test_reset_clears_buckets() {
let mut hll = HyperLogLog::<u32>::new(10);

// Insert some elements
hll.insert(1);
hll.insert(2);


let are_buckets_filled: bool = hll.get_buckets().iter().any(|x| *x > 0u8);

// Ensure buckets are not in the default state before reset
assert!(are_buckets_filled == true);

// Call reset
hll.reset();

let are_buckets_filled: bool = hll.get_buckets().iter().any(|x| *x > 0);

assert!(are_buckets_filled == false);

}

#[test]
fn test_reset_does_not_affect_other_fields() {
let mut hll = HyperLogLog::<u32>::new(10);

let original_p = hll.get_p();
let original_m = hll.get_m();

// Call reset
hll.reset();

let new_p = hll.get_p();
let new_m = hll.get_m();

assert!(original_p == new_p, "original p: {}, not equal to p after reset: {}", original_p, new_p);
assert!(original_m == new_m, "original m: {}, not equal to m after reset: {}", original_m, new_m);
}

#[test]
fn test_reset_after_inserting_elements() {
let mut hll = HyperLogLog::<u32>::new(10);

// Insert elements into the HyperLogLog
hll.insert(1);
hll.insert(2);

// Ensure the cardinality estimate is non-zero
let cardinality_before_reset = hll.calculate_cardinality();
assert!(cardinality_before_reset > 0);

// Call reset
hll.reset();

// Ensure the cardinality estimate is zero after reset
let cardinality_after_reset = hll.calculate_cardinality();
assert_eq!(cardinality_after_reset, 0);
}

#[test]
fn test_reset_multiple_times() {
let mut hll = HyperLogLog::<u32>::new(10);

// Call reset multiple times
hll.reset();
hll.reset();
hll.reset();

// Ensure buckets are still zero after multiple resets
assert_eq!(hll.get_buckets()[0], 0);
}