extern crate rand;
extern crate hashers;
use hashers::{builtin, fnv, fx_hash, jenkins, null, oz};
mod samples;
fn chi2(sample: &[Vec<u8>], hfcn: fn(&[u8]) -> u64, mask_size: u32) -> f64 {
let n_buckets = 2usize.pow(mask_size);
let mask: u64 = n_buckets as u64 - 1;
let mut buckets: Vec<usize> = vec![0; n_buckets];
sample
.iter()
.map(|s| (hfcn(s) & mask) as usize)
.for_each(|s| buckets[s] += 1);
let expected: f64 = (sample.len() as f64) / (n_buckets as f64);
let chi2: f64 = buckets
.iter()
.map(|&c| (c as f64) - expected)
.map(|r| (r * r) / expected)
.sum();
(chi2 - (n_buckets as f64)) / (n_buckets as f64).sqrt()
}
fn do_hashes(samples: &[Vec<u8>]) {
println!("default: {}", chi2(&samples, builtin::default, 7));
println!("djb2: {}", chi2(&samples, oz::djb2, 7));
println!("lookup3: {}", chi2(&samples, jenkins::lookup3, 7));
println!("loselose: {}", chi2(&samples, oz::loselose, 7));
println!("null: {}", chi2(&samples, null::null, 7));
println!("OAAT: {}", chi2(&samples, jenkins::oaat, 7));
println!("Pass: {}", chi2(&samples, null::passthrough, 7));
println!("sdbm: {}", chi2(&samples, oz::sdbm, 7));
println!("fnv1a 32: {}", chi2(&samples, fnv::fnv1a32, 7));
println!("fnv1a 64 {}", chi2(&samples, fnv::fnv1a64, 7));
println!("fxhash: {}", chi2(&samples, fx_hash::fxhash, 7));
println!("fxhash32: {}", chi2(&samples, fx_hash::fxhash32, 7));
println!("fxhash64: {}", chi2(&samples, fx_hash::fxhash64, 7));
println!("spooky: {}", chi2(&samples, jenkins::spooky_hash::spooky, 7));
}
fn main() {
println!("Uniform distribution");
let s1 = samples::random_samples(&mut samples::uniform(), 1000, 6);
do_hashes(&s1);
println!("\nAlphanumeric distribution");
let s2 = samples::alphanumeric_samples(1000, 6);
do_hashes(&s2);
println!("\nGenerated identifiers");
let s3 = samples::generated_samples(1000, 6);
do_hashes(&s3);
println!("\nDictionary words");
let s4 = samples::word_samples();
do_hashes(&s4);
}