pow: avoid unnecessary overflows
The code was performing an extra squaring of the base, which might trigger an arithmetic overflow that doesn't matter to the result. Now this squaring is only attempted when enough exp remains to need it. A new doctest tries pow(6u8, 3), where an extra square would exceed 256.
This commit is contained in:
parent
fbd7d81b44
commit
043a5b2918
|
@ -121,7 +121,8 @@ pub fn abs_sub<T: Signed>(x: T, y: T) -> T {
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use num;
|
/// use num;
|
||||||
///
|
///
|
||||||
/// assert_eq!(num::pow(2i, 4), 16);
|
/// assert_eq!(num::pow(2i8, 4), 16);
|
||||||
|
/// assert_eq!(num::pow(6u8, 3), 216);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn pow<T: Clone + One + Mul<T, Output = T>>(mut base: T, mut exp: usize) -> T {
|
pub fn pow<T: Clone + One + Mul<T, Output = T>>(mut base: T, mut exp: usize) -> T {
|
||||||
|
@ -132,7 +133,11 @@ pub fn pow<T: Clone + One + Mul<T, Output = T>>(mut base: T, mut exp: usize) ->
|
||||||
if (exp & 1) == 1 {
|
if (exp & 1) == 1 {
|
||||||
acc = acc * base.clone();
|
acc = acc * base.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// avoid overflow if we won't need it
|
||||||
|
if exp > 1 {
|
||||||
base = base.clone() * base;
|
base = base.clone() * base;
|
||||||
|
}
|
||||||
exp = exp >> 1;
|
exp = exp >> 1;
|
||||||
}
|
}
|
||||||
acc
|
acc
|
||||||
|
|
Loading…
Reference in New Issue