From b57e4a4db4a38f7d237b2f899410fd00d80a2c5a Mon Sep 17 00:00:00 2001 From: Ivan Ukhov Date: Tue, 20 Oct 2015 09:39:44 +0200 Subject: [PATCH] Implement arithmetic with real for complex --- src/complex.rs | 135 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 132 insertions(+), 3 deletions(-) diff --git a/src/complex.rs b/src/complex.rs index 1173816..299342d 100644 --- a/src/complex.rs +++ b/src/complex.rs @@ -289,6 +289,20 @@ impl Complex { } } +impl From for Complex { + #[inline] + fn from(re: T) -> Complex { + Complex { re: re, im: T::zero() } + } +} + +impl<'a, T: Clone + Num> From<&'a T> for Complex { + #[inline] + fn from(re: &T) -> Complex { + From::from(re.clone()) + } +} + macro_rules! forward_val_val_binop { (impl $imp:ident, $method:ident) => { impl $imp> for Complex { @@ -407,6 +421,93 @@ impl<'a, T: Clone + Num + Neg> Neg for &'a Complex { } } +macro_rules! real_arithmetic { + (@forward $imp:ident::$method:ident for $($real:ident),*) => ( + impl<'a, T: Clone + Num> $imp<&'a T> for Complex { + type Output = Complex; + + #[inline] + fn $method(self, other: &T) -> Complex { + self.$method(other.clone()) + } + } + impl<'a, T: Clone + Num> $imp for &'a Complex { + type Output = Complex; + + #[inline] + fn $method(self, other: T) -> Complex { + self.clone().$method(other) + } + } + impl<'a, 'b, T: Clone + Num> $imp<&'a T> for &'b Complex { + type Output = Complex; + + #[inline] + fn $method(self, other: &T) -> Complex { + self.clone().$method(other.clone()) + } + } + $( + impl<'a> $imp<&'a Complex<$real>> for $real { + type Output = Complex<$real>; + + #[inline] + fn $method(self, other: &Complex<$real>) -> Complex<$real> { + self.$method(other.clone()) + } + } + impl<'a> $imp> for &'a $real { + type Output = Complex<$real>; + + #[inline] + fn $method(self, other: Complex<$real>) -> Complex<$real> { + self.clone().$method(other) + } + } + impl<'a, 'b> $imp<&'a Complex<$real>> for &'b $real { + type Output = Complex<$real>; + + #[inline] + fn $method(self, other: &Complex<$real>) -> Complex<$real> { + self.clone().$method(other.clone()) + } + } + )* + ); + (@implement $imp:ident::$method:ident for $($real:ident),*) => ( + impl $imp for Complex { + type Output = Complex; + + #[inline] + fn $method(self, other: T) -> Complex { + self.$method(Complex::from(other)) + } + } + $( + impl $imp> for $real { + type Output = Complex<$real>; + + #[inline] + fn $method(self, other: Complex<$real>) -> Complex<$real> { + Complex::from(self).$method(other) + } + } + )* + ); + ($($real:ident),*) => ( + real_arithmetic!(@forward Add::add for $($real),*); + real_arithmetic!(@forward Sub::sub for $($real),*); + real_arithmetic!(@forward Mul::mul for $($real),*); + real_arithmetic!(@forward Div::div for $($real),*); + real_arithmetic!(@implement Add::add for $($real),*); + real_arithmetic!(@implement Sub::sub for $($real),*); + real_arithmetic!(@implement Mul::mul for $($real),*); + real_arithmetic!(@implement Div::div for $($real),*); + ); +} + +real_arithmetic!(usize, u8, u16, u32, u64, isize, i8, i16, i32, i64, f32, f64); + /* constants */ impl Zero for Complex { #[inline] @@ -838,7 +939,7 @@ mod test { } } - mod arith { + mod complex_arithmetic { use super::{_0_0i, _1_0i, _1_1i, _0_1i, _neg1_1i, _05_05i, all_consts}; use Zero; @@ -880,6 +981,7 @@ mod test { assert_eq!(_1_0i * c, c); } } + #[test] fn test_div() { assert_eq!(_neg1_1i / _0_1i, _1_1i); @@ -889,6 +991,7 @@ mod test { } } } + #[test] fn test_neg() { assert_eq!(-_1_0i + _0_1i, _neg1_1i); @@ -899,6 +1002,34 @@ mod test { } } + mod real_arithmetic { + use super::super::Complex; + + #[test] + fn test_add() { + assert_eq!(Complex::new(4.0, 2.0) + 0.5, Complex::new(4.5, 2.0)); + assert_eq!(0.5 + Complex::new(4.0, 2.0), Complex::new(4.5, 2.0)); + } + + #[test] + fn test_sub() { + assert_eq!(Complex::new(4.0, 2.0) - 0.5, Complex::new(3.5, 2.0)); + assert_eq!(0.5 - Complex::new(4.0, 2.0), Complex::new(-3.5, -2.0)); + } + + #[test] + fn test_mul() { + assert_eq!(Complex::new(4.0, 2.0) * 0.5, Complex::new(2.0, 1.0)); + assert_eq!(0.5 * Complex::new(4.0, 2.0), Complex::new(2.0, 1.0)); + } + + #[test] + fn test_div() { + assert_eq!(Complex::new(4.0, 2.0) / 0.5, Complex::new(8.0, 4.0)); + assert_eq!(0.5 / Complex::new(4.0, 2.0), Complex::new(0.1, -0.05)); + } + } + #[test] fn test_to_string() { fn test(c : Complex64, s: String) { @@ -915,8 +1046,6 @@ mod test { #[test] fn test_hash() { - - let a = Complex::new(0i32, 0i32); let b = Complex::new(1i32, 0i32); let c = Complex::new(0i32, 1i32);