Skip to content

Implements a pow method for Integers #11503

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 18, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions doc/guide-tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ be distributed on the available cores.
fn partial_sum(start: uint) -> f64 {
let mut local_sum = 0f64;
for num in range(start*100000, (start+1)*100000) {
local_sum += (num as f64 + 1.0).pow(&-2.0);
local_sum += (num as f64 + 1.0).powf(&-2.0);
}
local_sum
}
Expand Down Expand Up @@ -326,7 +326,7 @@ a single large vector of floats. Each task needs the full vector to perform its
use extra::arc::Arc;

fn pnorm(nums: &~[f64], p: uint) -> f64 {
nums.iter().fold(0.0, |a,b| a+(*b).pow(&(p as f64)) ).pow(&(1.0 / (p as f64)))
nums.iter().fold(0.0, |a,b| a+(*b).powf(&(p as f64)) ).powf(&(1.0 / (p as f64)))
}

fn main() {
Expand Down
12 changes: 6 additions & 6 deletions src/libextra/num/rational.rs
Original file line number Diff line number Diff line change
Expand Up @@ -653,19 +653,19 @@ mod test {

// f32
test(3.14159265359f32, ("13176795", "4194304"));
test(2f32.pow(&100.), ("1267650600228229401496703205376", "1"));
test(-2f32.pow(&100.), ("-1267650600228229401496703205376", "1"));
test(1.0 / 2f32.pow(&100.), ("1", "1267650600228229401496703205376"));
test(2f32.powf(&100.), ("1267650600228229401496703205376", "1"));
test(-2f32.powf(&100.), ("-1267650600228229401496703205376", "1"));
test(1.0 / 2f32.powf(&100.), ("1", "1267650600228229401496703205376"));
test(684729.48391f32, ("1369459", "2"));
test(-8573.5918555f32, ("-4389679", "512"));

// f64
test(3.14159265359f64, ("3537118876014453", "1125899906842624"));
test(2f64.pow(&100.), ("1267650600228229401496703205376", "1"));
test(-2f64.pow(&100.), ("-1267650600228229401496703205376", "1"));
test(2f64.powf(&100.), ("1267650600228229401496703205376", "1"));
test(-2f64.powf(&100.), ("-1267650600228229401496703205376", "1"));
test(684729.48391f64, ("367611342500051", "536870912"));
test(-8573.5918555, ("-4713381968463931", "549755813888"));
test(1.0 / 2f64.pow(&100.), ("1", "1267650600228229401496703205376"));
test(1.0 / 2f64.powf(&100.), ("1", "1267650600228229401496703205376"));
}

#[test]
Expand Down
4 changes: 2 additions & 2 deletions src/libextra/stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,8 +349,8 @@ pub fn write_boxplot(w: &mut io::Writer, s: &Summary, width_hint: uint) {
let (q1,q2,q3) = s.quartiles;

// the .abs() handles the case where numbers are negative
let lomag = (10.0_f64).pow(&(s.min.abs().log10().floor()));
let himag = (10.0_f64).pow(&(s.max.abs().log10().floor()));
let lomag = (10.0_f64).powf(&(s.min.abs().log10().floor()));
let himag = (10.0_f64).powf(&(s.max.abs().log10().floor()));

// need to consider when the limit is zero
let lo = if lomag == 0.0 {
Expand Down
4 changes: 2 additions & 2 deletions src/libstd/num/f32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ impl Real for f32 {
fn recip(&self) -> f32 { 1.0 / *self }

#[inline]
fn pow(&self, n: &f32) -> f32 { pow(*self, *n) }
fn powf(&self, n: &f32) -> f32 { pow(*self, *n) }

#[inline]
fn sqrt(&self) -> f32 { sqrt(*self) }
Expand Down Expand Up @@ -1265,7 +1265,7 @@ mod tests {
fn test_integer_decode() {
assert_eq!(3.14159265359f32.integer_decode(), (13176795u64, -22i16, 1i8));
assert_eq!((-8573.5918555f32).integer_decode(), (8779358u64, -10i16, -1i8));
assert_eq!(2f32.pow(&100.0).integer_decode(), (8388608u64, 77i16, 1i8));
assert_eq!(2f32.powf(&100.0).integer_decode(), (8388608u64, 77i16, 1i8));
assert_eq!(0f32.integer_decode(), (0u64, -150i16, 1i8));
assert_eq!((-0f32).integer_decode(), (0u64, -150i16, -1i8));
assert_eq!(INFINITY.integer_decode(), (8388608u64, 105i16, 1i8));
Expand Down
4 changes: 2 additions & 2 deletions src/libstd/num/f64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ impl Real for f64 {
fn recip(&self) -> f64 { 1.0 / *self }

#[inline]
fn pow(&self, n: &f64) -> f64 { pow(*self, *n) }
fn powf(&self, n: &f64) -> f64 { pow(*self, *n) }

#[inline]
fn sqrt(&self) -> f64 { sqrt(*self) }
Expand Down Expand Up @@ -1269,7 +1269,7 @@ mod tests {
fn test_integer_decode() {
assert_eq!(3.14159265359f64.integer_decode(), (7074237752028906u64, -51i16, 1i8));
assert_eq!((-8573.5918555f64).integer_decode(), (4713381968463931u64, -39i16, -1i8));
assert_eq!(2f64.pow(&100.0).integer_decode(), (4503599627370496u64, 48i16, 1i8));
assert_eq!(2f64.powf(&100.0).integer_decode(), (4503599627370496u64, 48i16, 1i8));
assert_eq!(0f64.integer_decode(), (0u64, -1075i16, 1i8));
assert_eq!((-0f64).integer_decode(), (0u64, -1075i16, -1i8));
assert_eq!(INFINITY.integer_decode(), (4503599627370496u64, 972i16, 1i8));
Expand Down
32 changes: 0 additions & 32 deletions src/libstd/num/int.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,38 +121,6 @@ impl CheckedMul for int {
}
}

/// Returns `base` raised to the power of `exponent`
pub fn pow(base: int, exponent: uint) -> int {
if exponent == 0u {
//Not mathemtically true if ~[base == 0]
return 1;
}
if base == 0 { return 0; }
let mut my_pow = exponent;
let mut acc = 1;
let mut multiplier = base;
while(my_pow > 0u) {
if my_pow % 2u == 1u {
acc *= multiplier;
}
my_pow /= 2u;
multiplier *= multiplier;
}
return acc;
}

#[test]
fn test_pow() {
assert!((pow(0, 0u) == 1));
assert!((pow(0, 1u) == 0));
assert!((pow(0, 2u) == 0));
assert!((pow(-1, 0u) == 1));
assert!((pow(1, 0u) == 1));
assert!((pow(-3, 2u) == 9));
assert!((pow(-3, 3u) == -27));
assert!((pow(4, 9u) == 262144));
}

#[test]
fn test_overflows() {
assert!((::int::max_value > 0));
Expand Down
68 changes: 64 additions & 4 deletions src/libstd/num/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,9 @@ pub trait Real: Signed
fn recip(&self) -> Self;

// Algebraic functions

/// Raise a number to a power.
fn pow(&self, n: &Self) -> Self;
fn powf(&self, n: &Self) -> Self;

/// Take the square root of a number.
fn sqrt(&self) -> Self;
/// Take the reciprocal (inverse) square root of a number, `1/sqrt(x)`.
Expand Down Expand Up @@ -263,17 +263,61 @@ pub trait Real: Signed
fn to_radians(&self) -> Self;
}

/// Raises a value to the power of exp, using
/// exponentiation by squaring.
///
/// # Example
///
/// ```rust
/// use std::num;
///
/// let sixteen = num::pow(2, 4u);
/// assert_eq!(sixteen, 16);
/// ```
#[inline]
pub fn pow<T: Clone+One+Mul<T, T>>(num: T, exp: uint) -> T {
let one: uint = One::one();
let num_one: T = One::one();

if exp.is_zero() { return num_one; }
if exp == one { return num.clone(); }

let mut i: uint = exp;
let mut v: T;
let mut r: T = num_one;

// This if is to avoid cloning self.
if (i & one) == one {
r = r * num;
i = i - one;
}

i = i >> one;
v = num * num;

while !i.is_zero() {
if (i & one) == one {
r = r * v;
i = i - one;
}
i = i >> one;
v = v * v;
}

r
}

/// Raise a number to a power.
///
/// # Example
///
/// ```rust
/// use std::num;
///
/// let sixteen: f64 = num::pow(2.0, 4.0);
/// let sixteen: f64 = num::powf(2.0, 4.0);
/// assert_eq!(sixteen, 16.0);
/// ```
#[inline(always)] pub fn pow<T: Real>(value: T, n: T) -> T { value.pow(&n) }
#[inline(always)] pub fn powf<T: Real>(value: T, n: T) -> T { value.powf(&n) }
/// Take the square root of a number.
#[inline(always)] pub fn sqrt<T: Real>(value: T) -> T { value.sqrt() }
/// Take the reciprocal (inverse) square root of a number, `1/sqrt(x)`.
Expand Down Expand Up @@ -1074,6 +1118,7 @@ pub fn test_num<T:Num + NumCast>(ten: T, two: T) {
mod tests {
use prelude::*;
use super::*;
use num;
use i8;
use i16;
use i32;
Expand Down Expand Up @@ -1634,4 +1679,19 @@ mod tests {
assert_eq!(from_f32(5f32), Some(Value { x: 5 }));
assert_eq!(from_f64(5f64), Some(Value { x: 5 }));
}

#[test]
fn test_pow() {
fn assert_pow<T: Eq+Clone+One+Mul<T, T>>(num: T, exp: uint) -> () {
assert_eq!(num::pow(num.clone(), exp),
range(1u, exp).fold(num.clone(), |acc, _| acc * num));
}

assert_eq!(num::pow(3, 0), 1);
assert_eq!(num::pow(5, 1), 5);
assert_pow(-4, 2);
assert_pow(8, 3);
assert_pow(8, 5);
assert_pow(2u64, 50);
}
}
2 changes: 1 addition & 1 deletion src/libstd/rand/distributions/gamma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ impl IndependentSample<f64> for GammaSmallShape {
fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
let Open01(u) = rng.gen::<Open01<f64>>();

self.large_shape.ind_sample(rng) * num::pow(u, self.inv_shape)
self.large_shape.ind_sample(rng) * num::powf(u, self.inv_shape)
}
}
impl IndependentSample<f64> for GammaLargeShape {
Expand Down
4 changes: 2 additions & 2 deletions src/libstd/sync/mpmc_bounded_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@

use clone::Clone;
use kinds::Send;
use num::{Real, Round};
use option::{Option, Some, None};
use sync::arc::UnsafeArc;
use sync::atomics::{AtomicUint,Relaxed,Release,Acquire};
use uint;
use vec;

struct Node<T> {
Expand Down Expand Up @@ -64,7 +64,7 @@ impl<T: Send> State<T> {
2u
} else {
// use next power of 2 as capacity
2f64.pow(&((capacity as f64).log2().ceil())) as uint
uint::next_power_of_two(capacity)
}
} else {
capacity
Expand Down
2 changes: 1 addition & 1 deletion src/test/bench/shootout-binarytrees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ fn main() {
let long_lived_tree = bottom_up_tree(&long_lived_arena, 0, max_depth);

let mut messages = range_step(min_depth, max_depth + 1, 2).map(|depth| {
use std::int::pow;
use std::num::pow;
let iterations = pow(2, (max_depth - depth + min_depth) as uint);
do Future::spawn {
let mut chk = 0;
Expand Down