Skip to content

Commit

Permalink
Auto merge of #133 - koverstreet:master, r=cuviper
Browse files Browse the repository at this point in the history
[RFC] Some performance improvements

I added add and subtract methods that take an operand by value, instead of by reference, so they can work in place instead of always allocating new BigInts for the result.

I'd like to hear if anyone knows a better way of doing this, though - with the various wrappers/forwardings doing this for all the operations is going to be a mess and add a ton of boilerplate. I haven't even tried to do a complete job of it yet.

I'm starting to think the sanest thing to do would be to only have in place implements of most of the operations - and have the wrappers clone() if necessary. That way, the only extra work we're doing is a memcpy(), which is a hell of a lot faster than a heap allocation.
  • Loading branch information
homu committed Dec 11, 2015
2 parents a228385 + fa372e2 commit f2ea30d
Show file tree
Hide file tree
Showing 3 changed files with 553 additions and 222 deletions.
53 changes: 53 additions & 0 deletions benches/bigint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,33 @@

extern crate test;
extern crate num;
extern crate rand;

use std::mem::replace;
use test::Bencher;
use num::{BigUint, Zero, One, FromPrimitive};
use num::bigint::RandBigInt;
use rand::{SeedableRng, StdRng};

fn multiply_bench(b: &mut Bencher, xbits: usize, ybits: usize) {
let seed: &[_] = &[1, 2, 3, 4];
let mut rng: StdRng = SeedableRng::from_seed(seed);

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) {
let seed: &[_] = &[1, 2, 3, 4];
let mut rng: StdRng = SeedableRng::from_seed(seed);

let x = rng.gen_bigint(xbits);
let y = rng.gen_bigint(ybits);

b.iter(|| &x / &y);
}

fn factorial(n: usize) -> BigUint {
let mut f: BigUint = One::one();
Expand All @@ -26,6 +49,36 @@ fn fib(n: usize) -> BigUint {
f0
}

#[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);
}

#[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);
}

#[bench]
fn factorial_100(b: &mut Bencher) {
b.iter(|| {
Expand Down
4 changes: 2 additions & 2 deletions benches/shootout-pidigits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ fn pidigits(n: isize, out: &mut io::Write) -> io::Result<()> {
let mut k = 0;
let mut context = Context::new();

for i in (1..(n+1)) {
for i in 1..(n+1) {
let mut d;
loop {
k += 1;
Expand All @@ -110,7 +110,7 @@ fn pidigits(n: isize, out: &mut io::Write) -> io::Result<()> {

let m = n % 10;
if m != 0 {
for _ in (m..10) { try!(write!(out, " ")); }
for _ in m..10 { try!(write!(out, " ")); }
try!(write!(out, "\t:{}\n", n));
}
Ok(())
Expand Down
Loading

0 comments on commit f2ea30d

Please sign in to comment.