use criterion::{
BenchmarkGroup, Criterion, Throughput, criterion_group, criterion_main, measurement::WallTime,
};
use rand_float::{badizadegan, campbell, division, pekkizen, sources::Weyl};
const SEED: u64 = 0x0123_4567_89AB_CDEF;
const FILL: usize = 1024;
fn bench_per_call(
g: &mut BenchmarkGroup<WallTime>,
name: &str,
mut f: impl FnMut(&mut Weyl) -> f64,
) {
g.bench_function(name, move |b| {
let mut rng = Weyl(SEED);
b.iter(|| f(&mut rng))
});
}
fn bench_fill(g: &mut BenchmarkGroup<WallTime>, name: &str, mut f: impl FnMut(&mut Weyl) -> f64) {
g.bench_function(name, move |b| {
let mut rng = Weyl(SEED);
let mut buf = [0.0f64; FILL];
b.iter(|| {
let mut local = Weyl(rng.0);
for x in buf.iter_mut() {
*x = f(&mut local);
}
rng.0 = local.0;
std::hint::black_box(&buf);
})
});
}
macro_rules! bench_all {
($g:expr, $one:ident) => {
$one($g, "weyl_baseline", |r| f64::from_bits(r.next_u64()));
$one($g, "division_53bits", |r| {
division::f64_53bits(|| r.next_u64())
});
$one($g, "pekkizen_64", |r| pekkizen::f64_64(|| r.next_u64()));
$one($g, "pekkizen_117", |r| pekkizen::f64_117(|| r.next_u64()));
$one($g, "pekkizen_full", |r| pekkizen::f64_full(|| r.next_u64()));
$one($g, "badizadegan_down", |r| {
badizadegan::f64_down(|| r.next_u64())
});
$one($g, "campbell_fast", |r| campbell::fast(|| r.next_u64()));
$one($g, "campbell_real", |r| campbell::real(|| r.next_u64()));
$one($g, "campbell_consttime_cmove", |r| {
campbell::consttime_cmove(|| r.next_u64())
});
$one($g, "campbell_consttime", |r| {
campbell::consttime(|| r.next_u64())
});
};
}
fn bench(c: &mut Criterion) {
let mut g = c.benchmark_group("per_call");
g.warm_up_time(std::time::Duration::from_secs(1));
g.measurement_time(std::time::Duration::from_secs(3));
bench_all!(&mut g, bench_per_call);
g.finish();
let mut g = c.benchmark_group("fill_1024");
g.warm_up_time(std::time::Duration::from_secs(1));
g.measurement_time(std::time::Duration::from_secs(3));
g.throughput(Throughput::Elements(FILL as u64));
bench_all!(&mut g, bench_fill);
g.finish();
}
criterion_group!(benches, bench);
criterion_main!(benches);