auto merge of #11649 : FlaPer87/rust/pow, r=cmr
There was an old and barely used implementation of pow, which expected both parameters to be uint and required more traits to be implemented. Since a new implementation for `pow` landed, I'm proposing to remove this old impl in favor of the new one. The benchmark shows that the new implementation is faster than the one being removed: ``` test num::bench::bench_pow_function ..bench: 9429 ns/iter (+/- 2055) test num::bench::bench_pow_with_uint_function ...bench: 28476 ns/iter (+/- 2202) ```
This commit is contained in:
commit
764f2cb6f3
@ -909,7 +909,7 @@ impl<T : Iterator<char>> Parser<T> {
|
||||
}
|
||||
}
|
||||
|
||||
let exp: f64 = num::pow_with_uint(10u, exp);
|
||||
let exp: f64 = num::pow(10u as f64, exp);
|
||||
if neg_exp {
|
||||
res /= exp;
|
||||
} else {
|
||||
|
@ -993,37 +993,6 @@ pub fn from_str_radix<T: FromStrRadix>(str: &str, radix: uint) -> Option<T> {
|
||||
FromStrRadix::from_str_radix(str, radix)
|
||||
}
|
||||
|
||||
/// Calculates a power to a given radix, optimized for uint `pow` and `radix`.
|
||||
///
|
||||
/// Returns `radix^pow` as `T`.
|
||||
///
|
||||
/// Note:
|
||||
/// Also returns `1` for `0^0`, despite that technically being an
|
||||
/// undefined number. The reason for this is twofold:
|
||||
/// - If code written to use this function cares about that special case, it's
|
||||
/// probably going to catch it before making the call.
|
||||
/// - If code written to use this function doesn't care about it, it's
|
||||
/// probably assuming that `x^0` always equals `1`.
|
||||
///
|
||||
pub fn pow_with_uint<T:NumCast+One+Zero+Div<T,T>+Mul<T,T>>(radix: uint, pow: uint) -> T {
|
||||
let _0: T = Zero::zero();
|
||||
let _1: T = One::one();
|
||||
|
||||
if pow == 0u { return _1; }
|
||||
if radix == 0u { return _0; }
|
||||
let mut my_pow = pow;
|
||||
let mut total = _1;
|
||||
let mut multiplier = cast(radix).unwrap();
|
||||
while (my_pow > 0u) {
|
||||
if my_pow % 2u == 1u {
|
||||
total = total * multiplier;
|
||||
}
|
||||
my_pow = my_pow / 2u;
|
||||
multiplier = multiplier * multiplier;
|
||||
}
|
||||
total
|
||||
}
|
||||
|
||||
impl<T: Zero + 'static> Zero for @T {
|
||||
fn zero() -> @T { @Zero::zero() }
|
||||
fn is_zero(&self) -> bool { (**self).is_zero() }
|
||||
@ -1684,3 +1653,18 @@ mod tests {
|
||||
assert_pow(2u64, 50);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod bench {
|
||||
use num;
|
||||
use vec;
|
||||
use prelude::*;
|
||||
use extra::test::BenchHarness;
|
||||
|
||||
#[bench]
|
||||
fn bench_pow_function(b: &mut BenchHarness) {
|
||||
let v = vec::from_fn(1024, |n| n);
|
||||
b.iter(|| {v.iter().fold(0, |old, new| num::pow(old, *new));});
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,8 @@ use str::{StrSlice};
|
||||
use str;
|
||||
use vec::{CopyableVector, ImmutableVector, MutableVector};
|
||||
use vec::OwnedVector;
|
||||
use num::{NumCast, Zero, One, cast, pow_with_uint, Integer};
|
||||
use num;
|
||||
use num::{NumCast, Zero, One, cast, Integer};
|
||||
use num::{Round, Float, FPNaN, FPInfinite, ToPrimitive};
|
||||
|
||||
pub enum ExponentFormat {
|
||||
@ -648,10 +649,10 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Div<T,T>+
|
||||
|
||||
if exp_found {
|
||||
let c = buf[i] as char;
|
||||
let base = match (c, exponent) {
|
||||
let base: T = match (c, exponent) {
|
||||
// c is never _ so don't need to handle specially
|
||||
('e', ExpDec) | ('E', ExpDec) => 10u,
|
||||
('p', ExpBin) | ('P', ExpBin) => 2u,
|
||||
('e', ExpDec) | ('E', ExpDec) => cast(10u).unwrap(),
|
||||
('p', ExpBin) | ('P', ExpBin) => cast(2u).unwrap(),
|
||||
_ => return None // char doesn't fit given exponent format
|
||||
};
|
||||
|
||||
@ -664,9 +665,9 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Div<T,T>+
|
||||
match exp {
|
||||
Some(exp_pow) => {
|
||||
multiplier = if exp_pow < 0 {
|
||||
_1 / pow_with_uint::<T>(base, (-exp_pow.to_int().unwrap()) as uint)
|
||||
_1 / num::pow(base, (-exp_pow.to_int().unwrap()) as uint)
|
||||
} else {
|
||||
pow_with_uint::<T>(base, exp_pow.to_int().unwrap() as uint)
|
||||
num::pow(base, exp_pow.to_int().unwrap() as uint)
|
||||
}
|
||||
}
|
||||
None => return None // invalid exponent -> invalid number
|
||||
|
Loading…
x
Reference in New Issue
Block a user