mod common;
use criterion::{Criterion, black_box, criterion_group, criterion_main};
use num_bigint::BigInt;
use common::{bench_id, bench_id_named, epsilon, precision_bits, verbose};
use computable::{Binary, Computable, pi, pi_bounds_at_precision};
fn bench_pi_refinement(c: &mut Criterion) {
let mut group = c.benchmark_group("pi/refinement");
group.sample_size(10);
for &bits in precision_bits() {
let eps = epsilon(bits);
if verbose() {
let bounds = pi()
.refine_to_default(eps)
.expect("pi refinement should succeed");
eprintln!("[pi/refinement/{bits}] width: {}", bounds.width());
}
group.bench_with_input(bench_id(bits), &eps, |b, eps| {
b.iter(|| {
black_box(
pi().refine_to_default(*eps)
.expect("pi refinement should succeed"),
)
})
});
}
group.finish();
}
fn bench_pi_bounds_at_precision(c: &mut Criterion) {
let mut group = c.benchmark_group("pi/bounds_at_precision");
group.sample_size(10);
for &bits in precision_bits() {
if verbose() {
let (lower, upper) = pi_bounds_at_precision(bits);
eprintln!(
"[pi/bounds_at_precision/{bits}] width: {}",
upper.sub(&lower)
);
}
group.bench_with_input(bench_id(bits), &bits, |b, &bits| {
b.iter(|| black_box(pi_bounds_at_precision(bits)))
});
}
group.finish();
}
fn bench_pi_arithmetic(c: &mut Criterion) {
let mut group = c.benchmark_group("pi/arithmetic");
group.sample_size(10);
for &bits in precision_bits() {
let eps = epsilon(bits);
group.bench_with_input(bench_id_named("2pi", bits), &eps, |b, eps| {
b.iter(|| {
let two = Computable::constant(Binary::new(BigInt::from(2), BigInt::from(0)));
black_box(
(two * pi())
.refine_to_default(*eps)
.expect("2pi should succeed"),
)
})
});
group.bench_with_input(bench_id_named("pi_half", bits), &eps, |b, eps| {
b.iter(|| {
let half = Computable::constant(Binary::new(BigInt::from(1), BigInt::from(-1)));
black_box(
(half * pi())
.refine_to_default(*eps)
.expect("pi/2 should succeed"),
)
})
});
group.bench_with_input(bench_id_named("pi_sq", bits), &eps, |b, eps| {
b.iter(|| {
black_box(
(pi() * pi())
.refine_to_default(*eps)
.expect("pi^2 should succeed"),
)
})
});
group.bench_with_input(bench_id_named("inv_pi", bits), &eps, |b, eps| {
b.iter(|| {
black_box(
pi().inv()
.refine_to_default(*eps)
.expect("1/pi should succeed"),
)
})
});
}
group.finish();
}
fn bench_sin_pi(c: &mut Criterion) {
let mut group = c.benchmark_group("pi/sin_multiples");
group.sample_size(10);
for &bits in precision_bits() {
let eps = epsilon(bits);
for &multiplier in &[1u64, 2, 10, 100] {
group.bench_with_input(
bench_id_named(format!("mul_{multiplier}"), bits),
&eps,
|b, eps| {
b.iter(|| {
let n_pi = if multiplier == 1 {
pi()
} else {
Computable::constant(Binary::new(
BigInt::from(multiplier),
BigInt::from(0),
)) * pi()
};
black_box(
n_pi.sin()
.refine_to_default(*eps)
.expect("sin(n*pi) should succeed"),
)
})
},
);
}
}
group.finish();
}
criterion_group!(
benches,
bench_pi_refinement,
bench_pi_bounds_at_precision,
bench_pi_arithmetic,
bench_sin_pi,
);
criterion_main!(benches);