Skip to content
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

Implement .norm() and to/from_polar() for complex numbers. #7050

Closed
wants to merge 2 commits into from
Closed
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/tutorial-tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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() {
Expand Down
77 changes: 63 additions & 14 deletions src/libextra/num/complex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub type Complex = Cmplx<float>;
pub type Complex32 = Cmplx<f32>;
pub type Complex64 = Cmplx<f64>;

impl<T: Copy + Num> Cmplx<T> {
impl<T: Clone + Num> Cmplx<T> {
/// Create a new Cmplx
#[inline]
pub fn new(re: T, im: T) -> Cmplx<T> {
Expand All @@ -55,7 +55,7 @@ impl<T: Copy + Num> Cmplx<T> {
/// Returns the complex conjugate. i.e. `re - i im`
#[inline]
pub fn conj(&self) -> Cmplx<T> {
Cmplx::new(self.re, -self.im)
Cmplx::new(self.re.clone(), -self.im)
}


Expand All @@ -80,62 +80,91 @@ impl<T: Copy + Num> Cmplx<T> {
}
}

#[cfg(not(stage0))] // Fixed by #4228
impl<T: Clone + Algebraic + Num> Cmplx<T> {
/// Calculate |self|
#[inline(always)]
pub fn norm(&self) -> T {
self.re.hypot(&self.im)
}
}

#[cfg(not(stage0))] // Fixed by #4228
impl<T: Clone + Trigonometric + Algebraic + Num> Cmplx<T> {
/// 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<T> {
Cmplx::new(r * theta.cos(), r * theta.sin())
}
}

/* arithmetic */
// (a + i b) + (c + i d) == (a + c) + i (b + d)
impl<T: Copy + Num> Add<Cmplx<T>, Cmplx<T>> for Cmplx<T> {
impl<T: Clone + Num> Add<Cmplx<T>, Cmplx<T>> for Cmplx<T> {
#[inline]
fn add(&self, other: &Cmplx<T>) -> Cmplx<T> {
Cmplx::new(self.re + other.re, self.im + other.im)
}
}
// (a + i b) - (c + i d) == (a - c) + i (b - d)
impl<T: Copy + Num> Sub<Cmplx<T>, Cmplx<T>> for Cmplx<T> {
impl<T: Clone + Num> Sub<Cmplx<T>, Cmplx<T>> for Cmplx<T> {
#[inline]
fn sub(&self, other: &Cmplx<T>) -> Cmplx<T> {
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<T: Copy + Num> Mul<Cmplx<T>, Cmplx<T>> for Cmplx<T> {
impl<T: Clone + Num> Mul<Cmplx<T>, Cmplx<T>> for Cmplx<T> {
#[inline]
fn mul(&self, other: &Cmplx<T>) -> Cmplx<T> {
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<T: Copy + Num> Div<Cmplx<T>, Cmplx<T>> for Cmplx<T> {
impl<T: Clone + Num> Div<Cmplx<T>, Cmplx<T>> for Cmplx<T> {
#[inline]
fn div(&self, other: &Cmplx<T>) -> Cmplx<T> {
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<T: Copy + Num> Neg<Cmplx<T>> for Cmplx<T> {
impl<T: Clone + Num> Neg<Cmplx<T>> for Cmplx<T> {
#[inline]
fn neg(&self) -> Cmplx<T> {
Cmplx::new(-self.re, -self.im)
}
}

/* constants */
impl<T: Copy + Num> Zero for Cmplx<T> {
impl<T: Clone + Num> Zero for Cmplx<T> {
#[inline]
fn zero() -> Cmplx<T> {
Cmplx::new(Zero::zero(), Zero::zero())
}

#[inline]
fn is_zero(&self) -> bool {
*self == Zero::zero()
self.re.is_zero() && self.im.is_zero()
}
}

impl<T: Copy + Num> One for Cmplx<T> {
impl<T: Clone + Num> One for Cmplx<T> {
#[inline]
fn one() -> Cmplx<T> {
Cmplx::new(One::one(), Zero::zero())
Expand Down Expand Up @@ -166,7 +195,7 @@ impl<T: ToStrRadix + Num + Ord> ToStrRadix for Cmplx<T> {
#[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 };
Expand All @@ -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);
Expand Down Expand Up @@ -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::*;
Expand Down
8 changes: 4 additions & 4 deletions src/libstd/num/f32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) }
Expand All @@ -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 {
Expand All @@ -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)]
Expand All @@ -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)]
Expand Down
8 changes: 4 additions & 4 deletions src/libstd/num/f64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) }
Expand All @@ -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 {
Expand All @@ -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)]
Expand All @@ -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)]
Expand Down
16 changes: 8 additions & 8 deletions src/libstd/num/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand All @@ -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
}
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions src/libstd/num/num.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -120,15 +120,15 @@ 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);
}

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;
}
Expand Down