2015-05-19 16:22:06 +00:00
|
|
|
#![feature(test)]
|
|
|
|
|
|
|
|
extern crate test;
|
|
|
|
extern crate num;
|
2015-11-20 10:05:36 +00:00
|
|
|
extern crate rand;
|
2015-05-19 16:22:06 +00:00
|
|
|
|
|
|
|
use std::mem::replace;
|
|
|
|
use test::Bencher;
|
2015-12-16 05:31:05 +00:00
|
|
|
use num::{BigInt, BigUint, Zero, One, FromPrimitive};
|
2015-11-20 10:05:36 +00:00
|
|
|
use num::bigint::RandBigInt;
|
|
|
|
use rand::{SeedableRng, StdRng};
|
|
|
|
|
2015-12-16 05:31:05 +00:00
|
|
|
fn get_rng() -> StdRng {
|
2015-11-20 10:05:36 +00:00
|
|
|
let seed: &[_] = &[1, 2, 3, 4];
|
2015-12-16 05:31:05 +00:00
|
|
|
SeedableRng::from_seed(seed)
|
|
|
|
}
|
2015-11-20 10:05:36 +00:00
|
|
|
|
2015-12-16 05:31:05 +00:00
|
|
|
fn multiply_bench(b: &mut Bencher, xbits: usize, ybits: usize) {
|
|
|
|
let mut rng = get_rng();
|
2015-11-20 10:05:36 +00:00
|
|
|
let x = rng.gen_bigint(xbits);
|
|
|
|
let y = rng.gen_bigint(ybits);
|
|
|
|
|
|
|
|
b.iter(|| &x * &y);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn divide_bench(b: &mut Bencher, xbits: usize, ybits: usize) {
|
2015-12-16 05:31:05 +00:00
|
|
|
let mut rng = get_rng();
|
2015-11-20 10:05:36 +00:00
|
|
|
let x = rng.gen_bigint(xbits);
|
|
|
|
let y = rng.gen_bigint(ybits);
|
|
|
|
|
|
|
|
b.iter(|| &x / &y);
|
|
|
|
}
|
2015-05-19 16:22:06 +00:00
|
|
|
|
|
|
|
fn factorial(n: usize) -> BigUint {
|
|
|
|
let mut f: BigUint = One::one();
|
|
|
|
for i in 1..(n+1) {
|
|
|
|
let bu: BigUint = FromPrimitive::from_usize(i).unwrap();
|
|
|
|
f = f * bu;
|
|
|
|
}
|
|
|
|
f
|
|
|
|
}
|
|
|
|
|
bigint: allow `Sub` to work in-place on the RHS
A new Fibonacci benchmark demonstrates the improvement by using both
addition and subtraction in each iteration of the loop, like #200.
Before:
test fib2_100 ... bench: 4,558 ns/iter (+/- 3,357)
test fib2_1000 ... bench: 62,575 ns/iter (+/- 5,200)
test fib2_10000 ... bench: 2,898,425 ns/iter (+/- 207,973)
After:
test fib2_100 ... bench: 1,973 ns/iter (+/- 102)
test fib2_1000 ... bench: 41,203 ns/iter (+/- 947)
test fib2_10000 ... bench: 2,544,272 ns/iter (+/- 45,183)
2016-07-09 00:34:12 +00:00
|
|
|
/// Compute Fibonacci numbers
|
2015-05-19 16:22:06 +00:00
|
|
|
fn fib(n: usize) -> BigUint {
|
|
|
|
let mut f0: BigUint = Zero::zero();
|
|
|
|
let mut f1: BigUint = One::one();
|
|
|
|
for _ in 0..n {
|
|
|
|
let f2 = f0 + &f1;
|
|
|
|
f0 = replace(&mut f1, f2);
|
|
|
|
}
|
|
|
|
f0
|
|
|
|
}
|
|
|
|
|
bigint: allow `Sub` to work in-place on the RHS
A new Fibonacci benchmark demonstrates the improvement by using both
addition and subtraction in each iteration of the loop, like #200.
Before:
test fib2_100 ... bench: 4,558 ns/iter (+/- 3,357)
test fib2_1000 ... bench: 62,575 ns/iter (+/- 5,200)
test fib2_10000 ... bench: 2,898,425 ns/iter (+/- 207,973)
After:
test fib2_100 ... bench: 1,973 ns/iter (+/- 102)
test fib2_1000 ... bench: 41,203 ns/iter (+/- 947)
test fib2_10000 ... bench: 2,544,272 ns/iter (+/- 45,183)
2016-07-09 00:34:12 +00:00
|
|
|
/// Compute Fibonacci numbers with two ops per iteration
|
|
|
|
/// (add and subtract, like issue #200)
|
|
|
|
fn fib2(n: usize) -> BigUint {
|
|
|
|
let mut f0: BigUint = Zero::zero();
|
|
|
|
let mut f1: BigUint = One::one();
|
|
|
|
for _ in 0..n {
|
|
|
|
f1 = f1 + &f0;
|
|
|
|
f0 = &f1 - f0;
|
|
|
|
}
|
|
|
|
f0
|
|
|
|
}
|
|
|
|
|
2015-11-20 10:05:36 +00:00
|
|
|
#[bench]
|
|
|
|
fn multiply_0(b: &mut Bencher) {
|
|
|
|
multiply_bench(b, 1 << 8, 1 << 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn multiply_1(b: &mut Bencher) {
|
|
|
|
multiply_bench(b, 1 << 8, 1 << 16);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn multiply_2(b: &mut Bencher) {
|
|
|
|
multiply_bench(b, 1 << 16, 1 << 16);
|
|
|
|
}
|
|
|
|
|
2017-08-03 16:30:09 +00:00
|
|
|
#[bench]
|
|
|
|
fn multiply_3(b: &mut Bencher) {
|
|
|
|
multiply_bench(b, 1 << 16, 1 << 17);
|
|
|
|
}
|
|
|
|
|
2015-11-20 10:05:36 +00:00
|
|
|
#[bench]
|
|
|
|
fn divide_0(b: &mut Bencher) {
|
|
|
|
divide_bench(b, 1 << 8, 1 << 6);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn divide_1(b: &mut Bencher) {
|
|
|
|
divide_bench(b, 1 << 12, 1 << 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn divide_2(b: &mut Bencher) {
|
|
|
|
divide_bench(b, 1 << 16, 1 << 12);
|
|
|
|
}
|
|
|
|
|
2015-05-19 16:22:06 +00:00
|
|
|
#[bench]
|
|
|
|
fn factorial_100(b: &mut Bencher) {
|
2015-12-16 05:31:05 +00:00
|
|
|
b.iter(|| factorial(100));
|
2015-05-19 16:22:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn fib_100(b: &mut Bencher) {
|
2015-12-16 05:31:05 +00:00
|
|
|
b.iter(|| fib(100));
|
2015-05-19 16:22:06 +00:00
|
|
|
}
|
|
|
|
|
2016-06-30 01:19:47 +00:00
|
|
|
#[bench]
|
|
|
|
fn fib_1000(b: &mut Bencher) {
|
|
|
|
b.iter(|| fib(1000));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn fib_10000(b: &mut Bencher) {
|
|
|
|
b.iter(|| fib(10000));
|
|
|
|
}
|
|
|
|
|
bigint: allow `Sub` to work in-place on the RHS
A new Fibonacci benchmark demonstrates the improvement by using both
addition and subtraction in each iteration of the loop, like #200.
Before:
test fib2_100 ... bench: 4,558 ns/iter (+/- 3,357)
test fib2_1000 ... bench: 62,575 ns/iter (+/- 5,200)
test fib2_10000 ... bench: 2,898,425 ns/iter (+/- 207,973)
After:
test fib2_100 ... bench: 1,973 ns/iter (+/- 102)
test fib2_1000 ... bench: 41,203 ns/iter (+/- 947)
test fib2_10000 ... bench: 2,544,272 ns/iter (+/- 45,183)
2016-07-09 00:34:12 +00:00
|
|
|
#[bench]
|
|
|
|
fn fib2_100(b: &mut Bencher) {
|
|
|
|
b.iter(|| fib2(100));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn fib2_1000(b: &mut Bencher) {
|
|
|
|
b.iter(|| fib2(1000));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn fib2_10000(b: &mut Bencher) {
|
|
|
|
b.iter(|| fib2(10000));
|
|
|
|
}
|
|
|
|
|
2015-05-19 16:22:06 +00:00
|
|
|
#[bench]
|
2015-12-16 05:31:05 +00:00
|
|
|
fn fac_to_string(b: &mut Bencher) {
|
2015-05-19 16:22:06 +00:00
|
|
|
let fac = factorial(100);
|
2015-12-16 05:31:05 +00:00
|
|
|
b.iter(|| fac.to_string());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn fib_to_string(b: &mut Bencher) {
|
2015-05-19 16:22:06 +00:00
|
|
|
let fib = fib(100);
|
2015-12-16 05:31:05 +00:00
|
|
|
b.iter(|| fib.to_string());
|
|
|
|
}
|
|
|
|
|
|
|
|
fn to_str_radix_bench(b: &mut Bencher, radix: u32) {
|
|
|
|
let mut rng = get_rng();
|
|
|
|
let x = rng.gen_bigint(1009);
|
|
|
|
b.iter(|| x.to_str_radix(radix));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn to_str_radix_02(b: &mut Bencher) {
|
|
|
|
to_str_radix_bench(b, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn to_str_radix_08(b: &mut Bencher) {
|
|
|
|
to_str_radix_bench(b, 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn to_str_radix_10(b: &mut Bencher) {
|
|
|
|
to_str_radix_bench(b, 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn to_str_radix_16(b: &mut Bencher) {
|
|
|
|
to_str_radix_bench(b, 16);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn to_str_radix_36(b: &mut Bencher) {
|
|
|
|
to_str_radix_bench(b, 36);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn from_str_radix_bench(b: &mut Bencher, radix: u32) {
|
|
|
|
use num::Num;
|
|
|
|
let mut rng = get_rng();
|
|
|
|
let x = rng.gen_bigint(1009);
|
|
|
|
let s = x.to_str_radix(radix);
|
|
|
|
assert_eq!(x, BigInt::from_str_radix(&s, radix).unwrap());
|
|
|
|
b.iter(|| BigInt::from_str_radix(&s, radix));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn from_str_radix_02(b: &mut Bencher) {
|
|
|
|
from_str_radix_bench(b, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn from_str_radix_08(b: &mut Bencher) {
|
|
|
|
from_str_radix_bench(b, 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn from_str_radix_10(b: &mut Bencher) {
|
|
|
|
from_str_radix_bench(b, 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn from_str_radix_16(b: &mut Bencher) {
|
|
|
|
from_str_radix_bench(b, 16);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn from_str_radix_36(b: &mut Bencher) {
|
|
|
|
from_str_radix_bench(b, 36);
|
2015-05-19 16:22:06 +00:00
|
|
|
}
|
|
|
|
|
2016-01-28 06:53:10 +00:00
|
|
|
#[bench]
|
|
|
|
fn shl(b: &mut Bencher) {
|
|
|
|
let n = BigUint::one() << 1000;
|
|
|
|
b.iter(|| {
|
|
|
|
let mut m = n.clone();
|
|
|
|
for i in 0..50 {
|
|
|
|
m = m << i;
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-05-19 16:22:06 +00:00
|
|
|
#[bench]
|
|
|
|
fn shr(b: &mut Bencher) {
|
2016-01-28 06:53:10 +00:00
|
|
|
let n = BigUint::one() << 2000;
|
2015-05-19 16:22:06 +00:00
|
|
|
b.iter(|| {
|
|
|
|
let mut m = n.clone();
|
2016-01-28 06:53:10 +00:00
|
|
|
for i in 0..50 {
|
|
|
|
m = m >> i;
|
2015-05-19 16:22:06 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2015-12-17 06:32:00 +00:00
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn hash(b: &mut Bencher) {
|
|
|
|
use std::collections::HashSet;
|
|
|
|
let mut rng = get_rng();
|
|
|
|
let v: Vec<BigInt> = (1000..2000).map(|bits| rng.gen_bigint(bits)).collect();
|
|
|
|
b.iter(|| {
|
|
|
|
let h: HashSet<&BigInt> = v.iter().collect();
|
|
|
|
assert_eq!(h.len(), v.len());
|
|
|
|
});
|
|
|
|
}
|
2016-01-06 17:02:21 +00:00
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn pow_bench(b: &mut Bencher) {
|
|
|
|
b.iter(|| {
|
2016-01-07 02:18:32 +00:00
|
|
|
let upper = 100_usize;
|
2016-01-06 17:02:21 +00:00
|
|
|
for i in 2..upper + 1 {
|
|
|
|
for j in 2..upper + 1 {
|
|
|
|
let i_big = BigUint::from_usize(i).unwrap();
|
|
|
|
num::pow(i_big, j);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|