use criterion::{criterion_group, criterion_main, Criterion};
use std::hint::black_box;
use writerslogic_warm::core::intersection::sparse_intersection_count;
const UNIVERSE: u32 = 262_144;
const NA: usize = 64;
struct Rng(u64);
impl Rng {
fn next(&mut self) -> u64 {
self.0 = self.0.wrapping_add(0x9E37_79B9_7F4A_7C15);
let mut z = self.0;
z = (z ^ (z >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9);
z = (z ^ (z >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB);
z ^ (z >> 31)
}
fn idx(&mut self) -> u32 {
(self.next() % UNIVERSE as u64) as u32
}
}
fn make_pair(nb: usize, overlap_pct: usize, seed: u64) -> (Vec<u32>, Vec<u32>) {
let mut rng = Rng(seed);
let mut a = std::collections::BTreeSet::new();
while a.len() < NA {
a.insert(rng.idx());
}
let a: Vec<u32> = a.into_iter().collect();
let shared = NA * overlap_pct / 100;
let mut b = std::collections::BTreeSet::new();
let mut pool = a.clone();
for k in 0..shared {
let r = k + (rng.next() as usize) % (pool.len() - k);
pool.swap(k, r);
b.insert(pool[k]);
}
while b.len() < nb {
let v = rng.idx();
if a.binary_search(&v).is_err() {
b.insert(v);
}
}
(a, b.into_iter().collect())
}
fn bench(c: &mut Criterion) {
for &nb in &[64usize, 256, 1024, 4096, 16384] {
for &ov in &[0usize, 10, 50, 100] {
let (a, b) = make_pair(nb, ov, (nb * 1000 + ov) as u64);
let mut g = c.benchmark_group(format!("b{nb}_ov{ov}"));
g.bench_function("sparse_intersection_count", |bn| {
bn.iter(|| sparse_intersection_count(black_box(&a), black_box(&b)))
});
g.finish();
}
}
}
criterion_group!(benches, bench);
criterion_main!(benches);