From 7e6a5940cbe9a1ff8c12566a972dc5c54c85ef5e Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Tue, 11 Jun 2013 11:03:02 +1000 Subject: [PATCH 1/2] std: convert pow, hypot, atan2, log to take arguments by reference. --- doc/tutorial-tasks.md | 4 ++-- src/libstd/num/f32.rs | 8 ++++---- src/libstd/num/f64.rs | 8 ++++---- src/libstd/num/float.rs | 16 ++++++++-------- src/libstd/num/num.rs | 8 ++++---- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/doc/tutorial-tasks.md b/doc/tutorial-tasks.md index 892908dc0a0..bf97c86b5c9 100644 --- a/doc/tutorial-tasks.md +++ b/doc/tutorial-tasks.md @@ -318,7 +318,7 @@ be distributed on the available cores. fn partial_sum(start: uint) -> f64 { let mut local_sum = 0f64; for uint::range(start*100000, (start+1)*100000) |num| { - local_sum += (num as f64 + 1.0).pow(-2.0); + local_sum += (num as f64 + 1.0).pow(&-2.0); } local_sum } @@ -355,7 +355,7 @@ a single large vector of floats. Each task needs the full vector to perform its use extra::arc::ARC; fn pnorm(nums: &~[float], p: uint) -> float { - nums.iter().fold(0.0, |a,b| a+(*b).pow(p as float) ).pow(1f / (p as float)) + nums.iter().fold(0.0, |a,b| a+(*b).pow(&(p as float)) ).pow(&(1f / (p as float))) } fn main() { diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index 62ce5ed65e1..7f981187300 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -391,7 +391,7 @@ impl Fractional for f32 { impl Algebraic for f32 { #[inline(always)] - fn pow(&self, n: f32) -> f32 { pow(*self, n) } + fn pow(&self, n: &f32) -> f32 { pow(*self, *n) } #[inline(always)] fn sqrt(&self) -> f32 { sqrt(*self) } @@ -403,7 +403,7 @@ impl Algebraic for f32 { fn cbrt(&self) -> f32 { cbrt(*self) } #[inline(always)] - fn hypot(&self, other: f32) -> f32 { hypot(*self, other) } + fn hypot(&self, other: &f32) -> f32 { hypot(*self, *other) } } impl Trigonometric for f32 { @@ -426,7 +426,7 @@ impl Trigonometric for f32 { fn atan(&self) -> f32 { atan(*self) } #[inline(always)] - fn atan2(&self, other: f32) -> f32 { atan2(*self, other) } + fn atan2(&self, other: &f32) -> f32 { atan2(*self, *other) } /// Simultaneously computes the sine and cosine of the number #[inline(always)] @@ -450,7 +450,7 @@ impl Exponential for f32 { /// Returns the logarithm of the number with respect to an arbitrary base #[inline(always)] - fn log(&self, base: f32) -> f32 { self.ln() / base.ln() } + fn log(&self, base: &f32) -> f32 { self.ln() / base.ln() } /// Returns the base 2 logarithm of the number #[inline(always)] diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index de44d861645..6303e304576 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -403,7 +403,7 @@ impl Fractional for f64 { impl Algebraic for f64 { #[inline(always)] - fn pow(&self, n: f64) -> f64 { pow(*self, n) } + fn pow(&self, n: &f64) -> f64 { pow(*self, *n) } #[inline(always)] fn sqrt(&self) -> f64 { sqrt(*self) } @@ -415,7 +415,7 @@ impl Algebraic for f64 { fn cbrt(&self) -> f64 { cbrt(*self) } #[inline(always)] - fn hypot(&self, other: f64) -> f64 { hypot(*self, other) } + fn hypot(&self, other: &f64) -> f64 { hypot(*self, *other) } } impl Trigonometric for f64 { @@ -438,7 +438,7 @@ impl Trigonometric for f64 { fn atan(&self) -> f64 { atan(*self) } #[inline(always)] - fn atan2(&self, other: f64) -> f64 { atan2(*self, other) } + fn atan2(&self, other: &f64) -> f64 { atan2(*self, *other) } /// Simultaneously computes the sine and cosine of the number #[inline(always)] @@ -462,7 +462,7 @@ impl Exponential for f64 { /// Returns the logarithm of the number with respect to an arbitrary base #[inline(always)] - fn log(&self, base: f64) -> f64 { self.ln() / base.ln() } + fn log(&self, base: &f64) -> f64 { self.ln() / base.ln() } /// Returns the base 2 logarithm of the number #[inline(always)] diff --git a/src/libstd/num/float.rs b/src/libstd/num/float.rs index a96a854e6a0..267a8890e82 100644 --- a/src/libstd/num/float.rs +++ b/src/libstd/num/float.rs @@ -475,8 +475,8 @@ impl Fractional for float { impl Algebraic for float { #[inline(always)] - fn pow(&self, n: float) -> float { - (*self as f64).pow(n as f64) as float + fn pow(&self, n: &float) -> float { + (*self as f64).pow(&(*n as f64)) as float } #[inline(always)] @@ -495,8 +495,8 @@ impl Algebraic for float { } #[inline(always)] - fn hypot(&self, other: float) -> float { - (*self as f64).hypot(other as f64) as float + fn hypot(&self, other: &float) -> float { + (*self as f64).hypot(&(*other as f64)) as float } } @@ -532,8 +532,8 @@ impl Trigonometric for float { } #[inline(always)] - fn atan2(&self, other: float) -> float { - (*self as f64).atan2(other as f64) as float + fn atan2(&self, other: &float) -> float { + (*self as f64).atan2(&(*other as f64)) as float } /// Simultaneously computes the sine and cosine of the number @@ -566,8 +566,8 @@ impl Exponential for float { /// Returns the logarithm of the number with respect to an arbitrary base #[inline(always)] - fn log(&self, base: float) -> float { - (*self as f64).log(base as f64) as float + fn log(&self, base: &float) -> float { + (*self as f64).log(&(*base as f64)) as float } /// Returns the base 2 logarithm of the number diff --git a/src/libstd/num/num.rs b/src/libstd/num/num.rs index 91631d3c9b9..a9893579721 100644 --- a/src/libstd/num/num.rs +++ b/src/libstd/num/num.rs @@ -106,11 +106,11 @@ pub trait Fractional: Num } pub trait Algebraic { - fn pow(&self, n: Self) -> Self; + fn pow(&self, n: &Self) -> Self; fn sqrt(&self) -> Self; fn rsqrt(&self) -> Self; fn cbrt(&self) -> Self; - fn hypot(&self, other: Self) -> Self; + fn hypot(&self, other: &Self) -> Self; } pub trait Trigonometric { @@ -120,7 +120,7 @@ pub trait Trigonometric { fn asin(&self) -> Self; fn acos(&self) -> Self; fn atan(&self) -> Self; - fn atan2(&self, other: Self) -> Self; + fn atan2(&self, other: &Self) -> Self; fn sin_cos(&self) -> (Self, Self); } @@ -128,7 +128,7 @@ pub trait Exponential { fn exp(&self) -> Self; fn exp2(&self) -> Self; fn ln(&self) -> Self; - fn log(&self, base: Self) -> Self; + fn log(&self, base: &Self) -> Self; fn log2(&self) -> Self; fn log10(&self) -> Self; } From 19c31b6b1afef7cad83275b2e73d27e5c44ed2a1 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Tue, 11 Jun 2013 11:37:33 +1000 Subject: [PATCH 2/2] extra: implement .norm(), and Polar conversion functions for complex numbers. Also, convert complex to use Clone, rather than Copy. Fixes #5734 and #5735. --- src/libextra/num/complex.rs | 77 ++++++++++++++++++++++++++++++------- 1 file changed, 63 insertions(+), 14 deletions(-) diff --git a/src/libextra/num/complex.rs b/src/libextra/num/complex.rs index 10bfe9409da..1bb364f3a1c 100644 --- a/src/libextra/num/complex.rs +++ b/src/libextra/num/complex.rs @@ -35,7 +35,7 @@ pub type Complex = Cmplx; pub type Complex32 = Cmplx; pub type Complex64 = Cmplx; -impl Cmplx { +impl Cmplx { /// Create a new Cmplx #[inline] pub fn new(re: T, im: T) -> Cmplx { @@ -55,7 +55,7 @@ impl Cmplx { /// Returns the complex conjugate. i.e. `re - i im` #[inline] pub fn conj(&self) -> Cmplx { - Cmplx::new(self.re, -self.im) + Cmplx::new(self.re.clone(), -self.im) } @@ -80,42 +80,71 @@ impl Cmplx { } } +#[cfg(not(stage0))] // Fixed by #4228 +impl Cmplx { + /// Calculate |self| + #[inline(always)] + pub fn norm(&self) -> T { + self.re.hypot(&self.im) + } +} + +#[cfg(not(stage0))] // Fixed by #4228 +impl Cmplx { + /// Calculate the principal Arg of self. + #[inline(always)] + pub fn arg(&self) -> T { + self.im.atan2(&self.re) + } + /// Convert to polar form (r, theta), such that `self = r * exp(i + /// * theta)` + #[inline] + pub fn to_polar(&self) -> (T, T) { + (self.norm(), self.arg()) + } + /// Convert a polar representation into a complex number. + #[inline] + pub fn from_polar(r: &T, theta: &T) -> Cmplx { + Cmplx::new(r * theta.cos(), r * theta.sin()) + } +} + /* arithmetic */ // (a + i b) + (c + i d) == (a + c) + i (b + d) -impl Add, Cmplx> for Cmplx { +impl Add, Cmplx> for Cmplx { #[inline] fn add(&self, other: &Cmplx) -> Cmplx { Cmplx::new(self.re + other.re, self.im + other.im) } } // (a + i b) - (c + i d) == (a - c) + i (b - d) -impl Sub, Cmplx> for Cmplx { +impl Sub, Cmplx> for Cmplx { #[inline] fn sub(&self, other: &Cmplx) -> Cmplx { Cmplx::new(self.re - other.re, self.im - other.im) } } // (a + i b) * (c + i d) == (a*c - b*d) + i (a*d + b*c) -impl Mul, Cmplx> for Cmplx { +impl Mul, Cmplx> for Cmplx { #[inline] fn mul(&self, other: &Cmplx) -> Cmplx { Cmplx::new(self.re*other.re - self.im*other.im, - self.re*other.im + self.im*other.re) + self.re*other.im + self.im*other.re) } } // (a + i b) / (c + i d) == [(a + i b) * (c - i d)] / (c*c + d*d) // == [(a*c + b*d) / (c*c + d*d)] + i [(b*c - a*d) / (c*c + d*d)] -impl Div, Cmplx> for Cmplx { +impl Div, Cmplx> for Cmplx { #[inline] fn div(&self, other: &Cmplx) -> Cmplx { let norm_sqr = other.norm_sqr(); Cmplx::new((self.re*other.re + self.im*other.im) / norm_sqr, - (self.im*other.re - self.re*other.im) / norm_sqr) + (self.im*other.re - self.re*other.im) / norm_sqr) } } -impl Neg> for Cmplx { +impl Neg> for Cmplx { #[inline] fn neg(&self) -> Cmplx { Cmplx::new(-self.re, -self.im) @@ -123,7 +152,7 @@ impl Neg> for Cmplx { } /* constants */ -impl Zero for Cmplx { +impl Zero for Cmplx { #[inline] fn zero() -> Cmplx { Cmplx::new(Zero::zero(), Zero::zero()) @@ -131,11 +160,11 @@ impl Zero for Cmplx { #[inline] fn is_zero(&self) -> bool { - *self == Zero::zero() + self.re.is_zero() && self.im.is_zero() } } -impl One for Cmplx { +impl One for Cmplx { #[inline] fn one() -> Cmplx { Cmplx::new(One::one(), Zero::zero()) @@ -166,7 +195,7 @@ impl ToStrRadix for Cmplx { #[cfg(test)] mod test { use super::*; - use core::num::{Zero,One}; + use core::num::{Zero,One,Real}; pub static _0_0i : Complex = Cmplx { re: 0f, im: 0f }; pub static _1_0i : Complex = Cmplx { re: 1f, im: 0f }; @@ -193,9 +222,10 @@ mod test { } #[test] - fn test_norm_sqr() { + fn test_norm() { fn test(c: Complex, ns: float) { assert_eq!(c.norm_sqr(), ns); + assert_eq!(c.norm(), ns.sqrt()) } test(_0_0i, 0f); test(_1_0i, 1f); @@ -235,6 +265,25 @@ mod test { _0_0i.inv(); } + #[test] + fn test_arg() { + fn test(c: Complex, arg: float) { + assert!(c.arg().approx_eq(&arg)) + } + test(_1_0i, 0f); + test(_1_1i, 0.25f * Real::pi()); + test(_neg1_1i, 0.75f * Real::pi()); + test(_05_05i, 0.25f * Real::pi()); + } + + #[test] + fn test_polar_conv() { + fn test(c: Complex) { + let (r, theta) = c.to_polar(); + assert!((c - Cmplx::from_polar(&r, &theta)).norm() < 1e-6); + } + for all_consts.each |&c| { test(c); } + } mod arith { use super::*;