From 1d8857a8423fe13d8764e5e9cb3ca34ad408ed36 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 5 Dec 2018 10:03:28 -0800 Subject: [PATCH] Expand the Roots benchmarks --- Cargo.toml | 3 + benches/bigint.rs | 24 ------- benches/roots.rs | 176 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 179 insertions(+), 24 deletions(-) create mode 100644 benches/roots.rs diff --git a/Cargo.toml b/Cargo.toml index 1115b13b..51fa9c55 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,9 @@ name = "factorial" [[bench]] name = "gcd" +[[bench]] +name = "roots" + [[bench]] harness = false name = "shootout-pidigits" diff --git a/benches/bigint.rs b/benches/bigint.rs index a043e163..2a4b87e8 100644 --- a/benches/bigint.rs +++ b/benches/bigint.rs @@ -343,27 +343,3 @@ fn modpow_even(b: &mut Bencher) { b.iter(|| base.modpow(&e, &m)); } - -#[bench] -fn roots_sqrt(b: &mut Bencher) { - let mut rng = get_rng(); - let x = rng.gen_biguint(2048); - - b.iter(|| x.sqrt()); -} - -#[bench] -fn roots_cbrt(b: &mut Bencher) { - let mut rng = get_rng(); - let x = rng.gen_biguint(2048); - - b.iter(|| x.cbrt()); -} - -#[bench] -fn roots_nth_100(b: &mut Bencher) { - let mut rng = get_rng(); - let x = rng.gen_biguint(2048); - - b.iter(|| x.nth_root(100)); -} diff --git a/benches/roots.rs b/benches/roots.rs new file mode 100644 index 00000000..51e67d9f --- /dev/null +++ b/benches/roots.rs @@ -0,0 +1,176 @@ +#![feature(test)] +#![cfg(feature = "rand")] + +extern crate num_bigint; +extern crate num_traits; +extern crate rand; +extern crate test; + +use num_bigint::{BigUint, RandBigInt}; +use num_traits::Pow; +use rand::{SeedableRng, StdRng}; +use test::Bencher; + +// The `big64` cases demonstrate the speed of cases where the value +// can be converted to a `u64` primitive for faster calculation. +// +// The `big1k` cases demonstrate those that can convert to `f64` for +// a better initial guess of the actual value. +// +// The `big2k` and `big4k` cases are too big for `f64`, and use a simpler guess. + +fn get_rng() -> StdRng { + let mut seed = [0; 32]; + for i in 1..32 { + seed[usize::from(i)] = i; + } + SeedableRng::from_seed(seed) +} + +fn check(x: &BigUint, n: u32) { + let root = x.nth_root(n); + if n == 2 { + assert_eq!(root, x.sqrt()) + } else if n == 3 { + assert_eq!(root, x.cbrt()) + } + + let lo = root.pow(n); + assert!(lo <= *x); + assert_eq!(lo.nth_root(n), root); + assert_eq!((&lo - 1u32).nth_root(n), &root - 1u32); + + let hi = (&root + 1u32).pow(n); + assert!(hi > *x); + assert_eq!(hi.nth_root(n), &root + 1u32); + assert_eq!((&hi - 1u32).nth_root(n), root); +} + +fn bench_sqrt(b: &mut Bencher, bits: usize) { + let x = get_rng().gen_biguint(bits); + eprintln!("bench_sqrt({})", x); + + check(&x, 2); + b.iter(|| x.sqrt()); +} + +#[bench] +fn big64_sqrt(b: &mut Bencher) { + bench_sqrt(b, 64); +} + +#[bench] +fn big1k_sqrt(b: &mut Bencher) { + bench_sqrt(b, 1024); +} + +#[bench] +fn big2k_sqrt(b: &mut Bencher) { + bench_sqrt(b, 2048); +} + +#[bench] +fn big4k_sqrt(b: &mut Bencher) { + bench_sqrt(b, 4096); +} + +fn bench_cbrt(b: &mut Bencher, bits: usize) { + let x = get_rng().gen_biguint(bits); + eprintln!("bench_cbrt({})", x); + + check(&x, 3); + b.iter(|| x.cbrt()); +} + +#[bench] +fn big64_cbrt(b: &mut Bencher) { + bench_cbrt(b, 64); +} + +#[bench] +fn big1k_cbrt(b: &mut Bencher) { + bench_cbrt(b, 1024); +} + +#[bench] +fn big2k_cbrt(b: &mut Bencher) { + bench_cbrt(b, 2048); +} + +#[bench] +fn big4k_cbrt(b: &mut Bencher) { + bench_cbrt(b, 4096); +} + +fn bench_nth_root(b: &mut Bencher, bits: usize, n: u32) { + let x = get_rng().gen_biguint(bits); + eprintln!("bench_{}th_root({})", n, x); + + check(&x, n); + b.iter(|| x.nth_root(n)); +} + +#[bench] +fn big64_nth_10(b: &mut Bencher) { + bench_nth_root(b, 64, 10); +} + +#[bench] +fn big1k_nth_10(b: &mut Bencher) { + bench_nth_root(b, 1024, 10); +} + +#[bench] +fn big1k_nth_100(b: &mut Bencher) { + bench_nth_root(b, 1024, 100); +} + +#[bench] +fn big1k_nth_1000(b: &mut Bencher) { + bench_nth_root(b, 1024, 1000); +} + +#[bench] +fn big1k_nth_10000(b: &mut Bencher) { + bench_nth_root(b, 1024, 10000); +} + +#[bench] +fn big2k_nth_10(b: &mut Bencher) { + bench_nth_root(b, 2048, 10); +} + +#[bench] +fn big2k_nth_100(b: &mut Bencher) { + bench_nth_root(b, 2048, 100); +} + +#[bench] +fn big2k_nth_1000(b: &mut Bencher) { + bench_nth_root(b, 2048, 1000); +} + +#[bench] +fn big2k_nth_10000(b: &mut Bencher) { + bench_nth_root(b, 2048, 10000); +} + +#[bench] +fn big4k_nth_10(b: &mut Bencher) { + bench_nth_root(b, 4096, 10); +} + +#[bench] +fn big4k_nth_100(b: &mut Bencher) { + bench_nth_root(b, 4096, 100); +} + +#[bench] +fn big4k_nth_1000(b: &mut Bencher) { + bench_nth_root(b, 4096, 1000); +} + +#[bench] +fn big4k_nth_10000(b: &mut Bencher) { + bench_nth_root(b, 4096, 10000); +}