use bitpolar::{TurboCode, TurboQuantizer};
fn main() {
let dim = 128usize;
let q = TurboQuantizer::new(dim, 4, 32, 42).expect("failed to create quantizer");
println!(
"TurboQuantizer: dim={} bits={} projections={}",
q.dim(),
q.bits(),
q.projections()
);
let db: Vec<TurboCode> = (0..1000_usize)
.map(|i| {
let v: Vec<f32> =
(0..dim).map(|j| ((i * dim + j) as f32 * 0.01).sin()).collect();
q.encode(&v).expect("encode failed")
})
.collect();
println!("Encoded {} vectors.", db.len());
let stats = q.batch_stats(&db);
println!(
"Compression: {:.2}x ratio, {:.2} bits/value ({} -> {} bytes total)",
stats.compression_ratio,
stats.bits_per_value,
stats.original_bytes,
stats.compressed_bytes,
);
let query: Vec<f32> = (0..dim).map(|j| (j as f32 * 0.02).cos()).collect();
let mut scored: Vec<(usize, f32)> = db
.iter()
.enumerate()
.map(|(i, code)| {
let score = q.inner_product_estimate(code, &query).unwrap_or(f32::MIN);
(i, score)
})
.collect();
scored.sort_unstable_by(|(_, a), (_, b)| b.partial_cmp(a).unwrap());
println!("\nTop-5 results by estimated inner product:");
println!("{:<8} {}", "Index", "Score");
println!("{}", "-".repeat(20));
for (rank, (idx, score)) in scored.iter().take(5).enumerate() {
println!("#{:<7} idx={:<6} score={:.4}", rank + 1, idx, score);
}
let (top_idx, top_score) = scored[0];
let reconstructed = q.decode(&db[top_idx]);
println!(
"\nDecoded top result (index={}, score={:.4}), first 4 dims: {:?}",
top_idx,
top_score,
&reconstructed[..4]
);
}