From 22722ac55d0dbd26a50c9b405153beca88a44e24 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 6 Jan 2016 18:27:50 -0800 Subject: [PATCH] pow: shift exp powers of 2 before accumulating We can save a multiplication if we start the accumulation basically at the first set bit of the exponent, rather than starting at one and waiting to multiply. We only need one itself if the exponent is zero, which is easy to pre-check. Before: test pow_bench ... bench: 8,267,370 ns/iter (+/- 93,319) After: test pow_bench ... bench: 7,506,463 ns/iter (+/- 116,311) --- src/lib.rs | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 6ded371..b8c8aa7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -141,22 +141,23 @@ pub fn abs_sub(x: T, y: T) -> T { /// ``` #[inline] pub fn pow>(mut base: T, mut exp: usize) -> T { - if exp == 1 { base } - else { - let mut acc = one::(); - while exp > 0 { - if (exp & 1) == 1 { - acc = acc * base.clone(); - } + if exp == 0 { return T::one() } - // avoid overflow if we won't need it - if exp > 1 { - base = base.clone() * base; - } - exp = exp >> 1; - } - acc + while exp & 1 == 0 { + base = base.clone() * base; + exp >>= 1; } + if exp == 1 { return base } + + let mut acc = base.clone(); + while exp > 1 { + exp >>= 1; + base = base.clone() * base; + if exp & 1 == 1 { + acc = acc * base.clone(); + } + } + acc } #[cfg(test)]