use std::time::Instant; use criterion::{black_box, criterion_group, criterion_main, Criterion}; use fixnum::{ops::*, FixedPoint}; #[cfg(feature = "i64")] type F64p9 = FixedPoint; #[cfg(feature = "i128")] type F128p18 = FixedPoint; macro_rules! define_bench { ($fp:tt) => { #[allow(non_snake_case)] fn $fp(c: &mut Criterion) { let mut group = c.benchmark_group(stringify!($fp)); group.bench_function("cadd (~1e4)", |b| { let lhs = black_box($fp::try_from(12345i32).unwrap()); let rhs = black_box($fp::try_from(54321i32).unwrap()); b.iter(move || lhs.cadd(rhs)) }); let mut rmul = |mode| { group.bench_function(format!("rmul (~1e4, {:?})", mode), |b| { let lhs = black_box( $fp::try_from(12345i32) .unwrap() .cadd($fp::from_bits(1)) .unwrap(), ); let rhs = black_box($fp::from_decimal(5, -1).unwrap()); b.iter(move || lhs.rmul(rhs, mode)) }); }; rmul(RoundMode::Floor); rmul(RoundMode::Ceil); rmul(RoundMode::Nearest); let mut rdiv = |mode| { group.bench_function(format!("rdiv (~1e5/~1e4, {:?})", mode), |b| { let lhs = black_box($fp::try_from(987656i32).unwrap()); let rhs = black_box($fp::try_from(54321i32).unwrap()); b.iter(move || lhs.rdiv(rhs, mode)) }); }; rdiv(RoundMode::Floor); rdiv(RoundMode::Ceil); rdiv(RoundMode::Nearest); let mut rsqrt = |mode| { group.bench_function(format!("rsqrt (~1e4, {:?})", mode), |b| { let x: $fp = black_box(22347.try_into().unwrap()); b.iter(move || x.rsqrt(mode)) }); }; rsqrt(RoundMode::Floor); rsqrt(RoundMode::Ceil); rsqrt(RoundMode::Nearest); let mut rsqrt_max = |mode| { group.bench_function(format!("rsqrt (MAX, {:?})", mode), |b| { let x = black_box($fp::MAX); b.iter(move || x.rsqrt(mode)) }); }; rsqrt_max(RoundMode::Floor); rsqrt_max(RoundMode::Ceil); rsqrt_max(RoundMode::Nearest); let mut rsqrt_adaptive = |mode| { group.bench_function(format!("rsqrt (adaptive, {:?})", mode), |b| { b.iter_custom(|iters| { let mut num = $fp::ZERO; let step = $fp::MAX .rdiv(*$fp::from_bits(iters as _).as_bits(), RoundMode::Floor) .unwrap(); let started_time = Instant::now(); for _ in 0..iters { num = num.cadd(step).unwrap(); let _ = black_box(num.rsqrt(mode)); } started_time.elapsed() }) }); }; rsqrt_adaptive(RoundMode::Floor); rsqrt_adaptive(RoundMode::Ceil); rsqrt_adaptive(RoundMode::Nearest); group.bench_function("next_power_of_ten", |b| { let mut value = 0; b.iter(move || { value += 1; $fp::from_bits(value).next_power_of_ten() }) }); group.bench_function("try_from(f64) (MIN_POSITIVE)", |b| { let value = black_box(f64::MIN_POSITIVE); b.iter(move || $fp::try_from(value)) }); group.bench_function("try_from(f64) (MAX)", |b| { let value = black_box(f64::MAX); b.iter(move || $fp::try_from(value)) }); group.bench_function("try_from(f64) (~1e-12)", |b| { let value = black_box(3.141592653589793e-12); b.iter(move || $fp::try_from(value)) }); group.bench_function("try_from(f64) (~0.1)", |b| { let value = black_box(0.3141592653589793); b.iter(move || $fp::try_from(value)) }); group.bench_function("try_from(f64) (~1e6)", |b| { let value = black_box(3.141592653589793e6); b.iter(move || $fp::try_from(value)) }); group.bench_function("from_decimal(12345, -3)", |b| { let decimal = black_box((12345, -3)); b.iter(move || $fp::from_decimal(decimal.0, decimal.1)) }); group.bench_function("to_decimal(0) (12.345)", |b| { let value = black_box($fp::from_decimal(12345, -3).unwrap()); b.iter(move || value.to_decimal(0)) }); group.bench_function("to_decimal(i32::MAX) (12.345)", |b| { let value = black_box($fp::from_decimal(12345, -3).unwrap()); b.iter(move || value.to_decimal(i32::MAX)) }); group.finish(); } }; } #[cfg(feature = "i64")] define_bench!(F64p9); #[cfg(feature = "i128")] define_bench!(F128p18); #[cfg(all(feature = "i64", feature = "i128"))] criterion_group!(benches, F64p9, F128p18); #[cfg(not(feature = "i128"))] criterion_group!(benches, F64p9); #[cfg(not(feature = "i64"))] criterion_group!(benches, F128p18); criterion_main!(benches);