use criterion::black_box; use criterion::criterion_group; use criterion::Criterion; const ITER: usize = 10000; const OFFSET: u64 = 0x9f1668016f482246; const MULTIPLIER: u64 = 0xf6ee9cc7a7f7d033; fn generate(i: usize) -> u64 { (i as u64).wrapping_mul(MULTIPLIER).wrapping_add(OFFSET) } fn hardware_u64_div(c: &mut Criterion) { let inputs: Vec = (0..ITER).map(generate).collect(); c.bench_function(&format!("hardware_u64_lat_{}", D), move |b| { b.iter(|| { let mut prev = 0; let div = black_box(D); for i in black_box(&inputs) { prev = (i ^ prev) / div; } black_box(prev) }) }); } fn compiled_u64_div(c: &mut Criterion) { let inputs: Vec = (0..ITER).map(generate).collect(); c.bench_function(&format!("compiled_u64_lat_by_{}", D), move |b| { b.iter(|| { let mut prev = 0; for i in black_box(&inputs) { prev = (i ^ prev) / D; } black_box(prev) }) }); } fn partial_reciprocal_sat_u64_div(c: &mut Criterion) { use reciprocal::PartialReciprocal; let d = black_box(PartialReciprocal::new(D).unwrap()); let inputs: Vec = (0..ITER).map(generate).collect(); c.bench_function(&format!("partial_sat_u64_lat_by_{}", D), move |b| { b.iter(|| { let mut prev = 0; for i in black_box(&inputs) { prev = d.apply_saturating(i ^ prev); } black_box(prev) }) }); } fn partial_reciprocal_of_u64_div(c: &mut Criterion) { use reciprocal::PartialReciprocal; let d = black_box(PartialReciprocal::new(D).unwrap()); let inputs: Vec = (0..ITER).map(generate).collect(); c.bench_function(&format!("partial_of_u64_lat_by_{}", D), move |b| { b.iter(|| { let mut prev = 0; for i in black_box(&inputs) { prev = d.apply_overflowing(i ^ prev); } black_box(prev) }) }); } fn reciprocal_full_u64_div(c: &mut Criterion) { use reciprocal::PartialReciprocal; let d = black_box(PartialReciprocal::new(D).unwrap()); let inputs: Vec = (0..ITER).map(generate).collect(); c.bench_function(&format!("reciprocal_u64_lat_by_{}", D), move |b| { b.iter(|| { let mut prev = 0; for i in black_box(&inputs) { prev = d.apply(i ^ prev); } black_box(prev) }) }); } fn strength_reduce_u64_div(c: &mut Criterion) { use strength_reduce::StrengthReducedU64; let d = black_box(StrengthReducedU64::new(D)); let inputs: Vec = (0..ITER).map(generate).collect(); c.bench_function(&format!("strength_reduce_u64_lat_by_{}", D), move |b| { b.iter(|| { let mut prev = 0; for i in black_box(&inputs) { prev = (i ^ prev) / d; } black_box(prev) }) }); } fn fast_divide_u64_div(c: &mut Criterion) { use fastdivide::DividerU64; let d = black_box(DividerU64::divide_by(D)); let inputs: Vec = (0..ITER).map(generate).collect(); c.bench_function(&format!("fast_divide_u64_lat_by_{}", D), move |b| { b.iter(|| { let mut prev = 0; for i in black_box(&inputs) { prev = d.divide(i ^ prev); } black_box(prev) }) }); } macro_rules! u64_div { ($name:ident, $div:literal) => { criterion_group!( $name, hardware_u64_div<{ $div }>, compiled_u64_div<{ $div }>, partial_reciprocal_sat_u64_div<{ $div }>, partial_reciprocal_of_u64_div<{ $div }>, reciprocal_full_u64_div<{ $div }>, strength_reduce_u64_div<{ $div }>, fast_divide_u64_div<{ $div }>, ); }; } u64_div!(u64_lat_by_2, 2); u64_div!(u64_lat_by_7, 7); u64_div!(u64_lat_by_11, 11); criterion::criterion_main!(u64_lat_by_2, u64_lat_by_7, u64_lat_by_11);