Skip to content

Commit 7dc187a

Browse files
pnkfelixalexcrichton
authored andcommittedFeb 13, 2014
Remove a source of O(n^2) running time in bigints.
::num::bigint, Remove a source of O(n^2) running time in `fn shr_bits`. I'll cut to the chase: On my laptop, this brings the running time on `pidigits 2000` (from src/test/bench/shootout-pidigits.rs) from this: ``` % time ./pidigits 2000 > /dev/null real 0m7.695s user 0m7.690s sys 0m0.005s ``` to this: ``` % time ./pidigits 2000 > /dev/null real 0m0.322s user 0m0.318s sys 0m0.004s ``` The previous code was building up a vector by repeatedly making a fresh copy for each element that was unshifted onto the front, yielding quadratic running time. This fixes that by building up the vector in reverse order (pushing elements onto the end) and then reversing it. (Another option would be to build up a zero-initialized vector of the desired length and then installing all of the shifted result elements into their target index, but this was easier to hack up quickly, and yields the desired asymptotic improvement. I have been thinking of adding a `vec::from_fn_rev` to handle this case, maybe I will try that this weekend.)
1 parent 606c23a commit 7dc187a

File tree

1 file changed

+14
-2
lines changed

1 file changed

+14
-2
lines changed
 

‎src/libnum/bigint.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -784,11 +784,12 @@ impl BigUint {
784784
if n_bits == 0 || self.data.is_empty() { return (*self).clone(); }
785785

786786
let mut borrow = 0;
787-
let mut shifted = ~[];
787+
let mut shifted_rev = vec::with_capacity(self.data.len());
788788
for elem in self.data.rev_iter() {
789-
shifted = ~[(*elem >> n_bits) | borrow] + shifted;
789+
shifted_rev.push((*elem >> n_bits) | borrow);
790790
borrow = *elem << (BigDigit::bits - n_bits);
791791
}
792+
let shifted = { shifted_rev.reverse(); shifted_rev };
792793
return BigUint::new(shifted);
793794
}
794795

@@ -2637,4 +2638,15 @@ mod bench {
26372638
fib.to_str();
26382639
});
26392640
}
2641+
2642+
#[bench]
2643+
fn shr(bh: &mut BenchHarness) {
2644+
let n = { let one : BigUint = One::one(); one << 1000 };
2645+
bh.iter(|| {
2646+
let mut m = n.clone();
2647+
for _ in range(0, 10) {
2648+
m = m >> 1;
2649+
}
2650+
})
2651+
}
26402652
}

0 commit comments

Comments
 (0)
Please sign in to comment.