const NUM_EXACT: usize = 25;
const EULER_MASCHERONI: f64 = 0.577_215_664_901_532_9;
const EXACT_HARMONIC: [f64; NUM_EXACT] = [
0.0, 1.0, 1.5, 11.0 / 6.0, 25.0 / 12.0, 137.0 / 60.0, 49.0 / 20.0, 363.0 / 140.0, 761.0 / 280.0, 7129.0 / 2520.0, 7381.0 / 2520.0, 83711.0 / 27720.0, 86021.0 / 27720.0, 1145993.0 / 360360.0, 1171733.0 / 360360.0, 1195757.0 / 360360.0, 2436559.0 / 720720.0, 42142223.0 / 12252240.0, 14274301.0 / 4084080.0, 275295799.0 / 77597520.0, 55835135.0 / 15519504.0, 18858053.0 / 5173168.0, 19093197.0 / 5173168.0, 444316699.0 / 118982864.0, 1347822955.0 / 356948592.0, ];
fn harmonic_number(n: usize) -> f64 {
if n < NUM_EXACT {
return EXACT_HARMONIC[n];
}
let x = n as f64;
let inv_sq = 1.0 / (x * x);
let mut sum = x.ln() + EULER_MASCHERONI + (1.0 / (2.0 * x));
let mut pow = inv_sq; sum -= pow * (1.0 / 12.0);
pow *= inv_sq; sum += pow * (1.0 / 120.0);
pow *= inv_sq; sum -= pow * (1.0 / 252.0);
pow *= inv_sq; sum += pow * (1.0 / 240.0);
sum
}
pub fn bitmap_estimate(bit_vector_length: u32, num_bits_set: u32) -> f64 {
let k = bit_vector_length;
let num_set = num_bits_set;
let h_k = harmonic_number(k as usize);
let h_diff = harmonic_number((k - num_set) as usize);
(k as f64) * (h_k - h_diff)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_exact_harmonic_numbers() {
assert!((harmonic_number(1) - 1.0).abs() < 1e-10);
assert!((harmonic_number(2) - 1.5).abs() < 1e-10);
assert!((harmonic_number(3) - 11.0 / 6.0).abs() < 1e-10);
let expected = 1.0
+ 1.0 / 2.0
+ 1.0 / 3.0
+ 1.0 / 4.0
+ 1.0 / 5.0
+ 1.0 / 6.0
+ 1.0 / 7.0
+ 1.0 / 8.0
+ 1.0 / 9.0
+ 1.0 / 10.0;
assert!((harmonic_number(10) - expected).abs() < 1e-10);
}
#[test]
fn test_asymptotic_harmonic() {
let n = 1000usize;
let h_n = harmonic_number(n);
let approx = (n as f64).ln() + EULER_MASCHERONI + 1.0 / (2.0 * n as f64);
assert!((h_n - approx).abs() / h_n < 0.001);
}
#[test]
fn test_bitmap_estimate_empty() {
let est = bitmap_estimate(1024, 0);
assert!(est.abs() < 1e-6);
}
#[test]
fn test_bitmap_estimate_full() {
let k = 1024;
let est = bitmap_estimate(k, k);
assert!(est > k as f64);
let expected = k as f64 * harmonic_number(k as usize);
assert!((est - expected).abs() < 1e-6);
}
#[test]
fn test_bitmap_estimate_half() {
let k = 1024;
let est = bitmap_estimate(k, k / 2);
assert!(est > 0.0);
assert!(est < k as f64 * harmonic_number(k as usize));
}
}