| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448 | // Copyright 2013 The Rust Project Developers. See the COPYRIGHT// file at the top-level directory of this distribution and at// http://rust-lang.org/COPYRIGHT.//// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your// option. This file may not be copied, modified, or distributed// except according to those terms.//! Complex numbers.use std::fmt;use std::ops::{Add, Div, Mul, Neg, Sub};use {Zero, One, Num, Float};// FIXME #1284: handle complex NaN & infinity etc. This// probably doesn't map to C's _Complex correctly./// A complex number in Cartesian form.#[derive(PartialEq, Copy, Clone, Hash, RustcEncodable, RustcDecodable, Debug)]pub struct Complex<T> {    /// Real portion of the complex number    pub re: T,    /// Imaginary portion of the complex number    pub im: T}pub type Complex32 = Complex<f32>;pub type Complex64 = Complex<f64>;impl<T: Clone + Num> Complex<T> {    /// Create a new Complex    #[inline]    pub fn new(re: T, im: T) -> Complex<T> {        Complex { re: re, im: im }    }    /// Returns the square of the norm (since `T` doesn't necessarily    /// have a sqrt function), i.e. `re^2 + im^2`.    #[inline]    pub fn norm_sqr(&self) -> T {        self.re.clone() * self.re.clone() + self.im.clone() * self.im.clone()    }    /// Multiplies `self` by the scalar `t`.    #[inline]    pub fn scale(&self, t: T) -> Complex<T> {        Complex::new(self.re.clone() * t.clone(), self.im.clone() * t)    }    /// Divides `self` by the scalar `t`.    #[inline]    pub fn unscale(&self, t: T) -> Complex<T> {        Complex::new(self.re.clone() / t.clone(), self.im.clone() / t)    }}impl<T: Clone + Num + Neg<Output = T>> Complex<T> {    /// Returns the complex conjugate. i.e. `re - i im`    #[inline]    pub fn conj(&self) -> Complex<T> {        Complex::new(self.re.clone(), -self.im.clone())    }    /// Returns `1/self`    #[inline]    pub fn inv(&self) -> Complex<T> {        let norm_sqr = self.norm_sqr();        Complex::new(self.re.clone() / norm_sqr.clone(),                     -self.im.clone() / norm_sqr)    }}impl<T: Clone + Float> Complex<T> {    /// Calculate |self|    #[inline]    pub fn norm(&self) -> T {        self.re.clone().hypot(self.im.clone())    }}impl<T: Clone + Float + Num> Complex<T> {    /// Calculate the principal Arg of self.    #[inline]    pub fn arg(&self) -> T {        self.im.clone().atan2(self.re.clone())    }    /// 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) -> Complex<T> {        Complex::new(*r * theta.cos(), *r * theta.sin())    }}macro_rules! forward_val_val_binop {    (impl $imp:ident, $method:ident) => {        impl<T: Clone + Num> $imp<Complex<T>> for Complex<T> {            type Output = Complex<T>;            #[inline]            fn $method(self, other: Complex<T>) -> Complex<T> {                (&self).$method(&other)            }        }    }}macro_rules! forward_ref_val_binop {    (impl $imp:ident, $method:ident) => {        impl<'a, T: Clone + Num> $imp<Complex<T>> for &'a Complex<T> {            type Output = Complex<T>;            #[inline]            fn $method(self, other: Complex<T>) -> Complex<T> {                self.$method(&other)            }        }    }}macro_rules! forward_val_ref_binop {    (impl $imp:ident, $method:ident) => {        impl<'a, T: Clone + Num> $imp<&'a Complex<T>> for Complex<T> {            type Output = Complex<T>;            #[inline]            fn $method(self, other: &Complex<T>) -> Complex<T> {                (&self).$method(other)            }        }    }}macro_rules! forward_all_binop {    (impl $imp:ident, $method:ident) => {        forward_val_val_binop!(impl $imp, $method);        forward_ref_val_binop!(impl $imp, $method);        forward_val_ref_binop!(impl $imp, $method);    };}/* arithmetic */forward_all_binop!(impl Add, add);// (a + i b) + (c + i d) == (a + c) + i (b + d)impl<'a, 'b, T: Clone + Num> Add<&'b Complex<T>> for &'a Complex<T> {    type Output = Complex<T>;    #[inline]    fn add(self, other: &Complex<T>) -> Complex<T> {        Complex::new(self.re.clone() + other.re.clone(),                     self.im.clone() + other.im.clone())    }}forward_all_binop!(impl Sub, sub);// (a + i b) - (c + i d) == (a - c) + i (b - d)impl<'a, 'b, T: Clone + Num> Sub<&'b Complex<T>> for &'a Complex<T> {    type Output = Complex<T>;    #[inline]    fn sub(self, other: &Complex<T>) -> Complex<T> {        Complex::new(self.re.clone() - other.re.clone(),                     self.im.clone() - other.im.clone())    }}forward_all_binop!(impl Mul, mul);// (a + i b) * (c + i d) == (a*c - b*d) + i (a*d + b*c)impl<'a, 'b, T: Clone + Num> Mul<&'b Complex<T>> for &'a Complex<T> {    type Output = Complex<T>;    #[inline]    fn mul(self, other: &Complex<T>) -> Complex<T> {        Complex::new(self.re.clone() * other.re.clone() - self.im.clone() * other.im.clone(),                     self.re.clone() * other.im.clone() + self.im.clone() * other.re.clone())    }}forward_all_binop!(impl Div, div);// (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<'a, 'b, T: Clone + Num> Div<&'b Complex<T>> for &'a Complex<T> {    type Output = Complex<T>;    #[inline]    fn div(self, other: &Complex<T>) -> Complex<T> {        let norm_sqr = other.norm_sqr();        Complex::new((self.re.clone() * other.re.clone() + self.im.clone() * other.im.clone()) / norm_sqr.clone(),                     (self.im.clone() * other.re.clone() - self.re.clone() * other.im.clone()) / norm_sqr)    }}impl<T: Clone + Num + Neg<Output = T>> Neg for Complex<T> {    type Output = Complex<T>;    #[inline]    fn neg(self) -> Complex<T> { -&self }}impl<'a, T: Clone + Num + Neg<Output = T>> Neg for &'a Complex<T> {    type Output = Complex<T>;    #[inline]    fn neg(self) -> Complex<T> {        Complex::new(-self.re.clone(), -self.im.clone())    }}/* constants */impl<T: Clone + Num> Zero for Complex<T> {    #[inline]    fn zero() -> Complex<T> {        Complex::new(Zero::zero(), Zero::zero())    }    #[inline]    fn is_zero(&self) -> bool {        self.re.is_zero() && self.im.is_zero()    }}impl<T: Clone + Num> One for Complex<T> {    #[inline]    fn one() -> Complex<T> {        Complex::new(One::one(), Zero::zero())    }}/* string conversions */impl<T> fmt::Display for Complex<T> where    T: fmt::Display + Num + PartialOrd + Clone{    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {        if self.im < Zero::zero() {            write!(f, "{}-{}i", self.re, T::zero() - self.im.clone())        } else {            write!(f, "{}+{}i", self.re, self.im)        }    }}#[cfg(test)]mod test {    #![allow(non_upper_case_globals)]    use super::{Complex64, Complex};    use std::f64;    use {Zero, One, Float};    pub const _0_0i : Complex64 = Complex { re: 0.0, im: 0.0 };    pub const _1_0i : Complex64 = Complex { re: 1.0, im: 0.0 };    pub const _1_1i : Complex64 = Complex { re: 1.0, im: 1.0 };    pub const _0_1i : Complex64 = Complex { re: 0.0, im: 1.0 };    pub const _neg1_1i : Complex64 = Complex { re: -1.0, im: 1.0 };    pub const _05_05i : Complex64 = Complex { re: 0.5, im: 0.5 };    pub const all_consts : [Complex64; 5] = [_0_0i, _1_0i, _1_1i, _neg1_1i, _05_05i];    #[test]    fn test_consts() {        // check our constants are what Complex::new creates        fn test(c : Complex64, r : f64, i: f64) {            assert_eq!(c, Complex::new(r,i));        }        test(_0_0i, 0.0, 0.0);        test(_1_0i, 1.0, 0.0);        test(_1_1i, 1.0, 1.0);        test(_neg1_1i, -1.0, 1.0);        test(_05_05i, 0.5, 0.5);        assert_eq!(_0_0i, Zero::zero());        assert_eq!(_1_0i, One::one());    }    #[test]    #[cfg_attr(target_arch = "x86", ignore)]    // FIXME #7158: (maybe?) currently failing on x86.    fn test_norm() {        fn test(c: Complex64, ns: f64) {            assert_eq!(c.norm_sqr(), ns);            assert_eq!(c.norm(), ns.sqrt())        }        test(_0_0i, 0.0);        test(_1_0i, 1.0);        test(_1_1i, 2.0);        test(_neg1_1i, 2.0);        test(_05_05i, 0.5);    }    #[test]    fn test_scale_unscale() {        assert_eq!(_05_05i.scale(2.0), _1_1i);        assert_eq!(_1_1i.unscale(2.0), _05_05i);        for &c in all_consts.iter() {            assert_eq!(c.scale(2.0).unscale(2.0), c);        }    }    #[test]    fn test_conj() {        for &c in all_consts.iter() {            assert_eq!(c.conj(), Complex::new(c.re, -c.im));            assert_eq!(c.conj().conj(), c);        }    }    #[test]    fn test_inv() {        assert_eq!(_1_1i.inv(), _05_05i.conj());        assert_eq!(_1_0i.inv(), _1_0i.inv());    }    #[test]    #[should_panic]    fn test_divide_by_zero_natural() {        let n = Complex::new(2, 3);        let d = Complex::new(0, 0);        let _x = n / d;    }    #[test]    #[should_panic]    #[ignore]    fn test_inv_zero() {        // FIXME #5736: should this really fail, or just NaN?        _0_0i.inv();    }    #[test]    fn test_arg() {        fn test(c: Complex64, arg: f64) {            assert!((c.arg() - arg).abs() < 1.0e-6)        }        test(_1_0i, 0.0);        test(_1_1i, 0.25 * f64::consts::PI);        test(_neg1_1i, 0.75 * f64::consts::PI);        test(_05_05i, 0.25 * f64::consts::PI);    }    #[test]    fn test_polar_conv() {        fn test(c: Complex64) {            let (r, theta) = c.to_polar();            assert!((c - Complex::from_polar(&r, &theta)).norm() < 1e-6);        }        for &c in all_consts.iter() { test(c); }    }    mod arith {        use super::{_0_0i, _1_0i, _1_1i, _0_1i, _neg1_1i, _05_05i, all_consts};        use Zero;        #[test]        fn test_add() {            assert_eq!(_05_05i + _05_05i, _1_1i);            assert_eq!(_0_1i + _1_0i, _1_1i);            assert_eq!(_1_0i + _neg1_1i, _0_1i);            for &c in all_consts.iter() {                assert_eq!(_0_0i + c, c);                assert_eq!(c + _0_0i, c);            }        }        #[test]        fn test_sub() {            assert_eq!(_05_05i - _05_05i, _0_0i);            assert_eq!(_0_1i - _1_0i, _neg1_1i);            assert_eq!(_0_1i - _neg1_1i, _1_0i);            for &c in all_consts.iter() {                assert_eq!(c - _0_0i, c);                assert_eq!(c - c, _0_0i);            }        }        #[test]        fn test_mul() {            assert_eq!(_05_05i * _05_05i, _0_1i.unscale(2.0));            assert_eq!(_1_1i * _0_1i, _neg1_1i);            // i^2 & i^4            assert_eq!(_0_1i * _0_1i, -_1_0i);            assert_eq!(_0_1i * _0_1i * _0_1i * _0_1i, _1_0i);            for &c in all_consts.iter() {                assert_eq!(c * _1_0i, c);                assert_eq!(_1_0i * c, c);            }        }        #[test]        fn test_div() {            assert_eq!(_neg1_1i / _0_1i, _1_1i);            for &c in all_consts.iter() {                if c != Zero::zero() {                    assert_eq!(c / c, _1_0i);                }            }        }        #[test]        fn test_neg() {            assert_eq!(-_1_0i + _0_1i, _neg1_1i);            assert_eq!((-_0_1i) * _0_1i, _1_0i);            for &c in all_consts.iter() {                assert_eq!(-(-c), c);            }        }    }    #[test]    fn test_to_string() {        fn test(c : Complex64, s: String) {            assert_eq!(c.to_string(), s);        }        test(_0_0i, "0+0i".to_string());        test(_1_0i, "1+0i".to_string());        test(_0_1i, "0+1i".to_string());        test(_1_1i, "1+1i".to_string());        test(_neg1_1i, "-1+1i".to_string());        test(-_neg1_1i, "1-1i".to_string());        test(_05_05i, "0.5+0.5i".to_string());    }    #[test]    fn test_hash() {        let a = Complex::new(0i32, 0i32);        let b = Complex::new(1i32, 0i32);        let c = Complex::new(0i32, 1i32);        assert!(::hash(&a) != ::hash(&b));        assert!(::hash(&b) != ::hash(&c));        assert!(::hash(&c) != ::hash(&a));    }}
 |