Implement arithmetic with real for complex

This commit is contained in:
Ivan Ukhov 2015-10-20 09:39:44 +02:00
parent d9b72a3366
commit b57e4a4db4
1 changed files with 132 additions and 3 deletions

View File

@ -289,6 +289,20 @@ impl<T: Clone + Float> Complex<T> {
} }
} }
impl<T: Clone + Num> From<T> for Complex<T> {
#[inline]
fn from(re: T) -> Complex<T> {
Complex { re: re, im: T::zero() }
}
}
impl<'a, T: Clone + Num> From<&'a T> for Complex<T> {
#[inline]
fn from(re: &T) -> Complex<T> {
From::from(re.clone())
}
}
macro_rules! forward_val_val_binop { macro_rules! forward_val_val_binop {
(impl $imp:ident, $method:ident) => { (impl $imp:ident, $method:ident) => {
impl<T: Clone + Num> $imp<Complex<T>> for Complex<T> { impl<T: Clone + Num> $imp<Complex<T>> for Complex<T> {
@ -407,6 +421,93 @@ impl<'a, T: Clone + Num + Neg<Output = T>> Neg for &'a Complex<T> {
} }
} }
macro_rules! real_arithmetic {
(@forward $imp:ident::$method:ident for $($real:ident),*) => (
impl<'a, T: Clone + Num> $imp<&'a T> for Complex<T> {
type Output = Complex<T>;
#[inline]
fn $method(self, other: &T) -> Complex<T> {
self.$method(other.clone())
}
}
impl<'a, T: Clone + Num> $imp<T> for &'a Complex<T> {
type Output = Complex<T>;
#[inline]
fn $method(self, other: T) -> Complex<T> {
self.clone().$method(other)
}
}
impl<'a, 'b, T: Clone + Num> $imp<&'a T> for &'b Complex<T> {
type Output = Complex<T>;
#[inline]
fn $method(self, other: &T) -> Complex<T> {
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<Complex<$real>> 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<T: Clone + Num> $imp<T> for Complex<T> {
type Output = Complex<T>;
#[inline]
fn $method(self, other: T) -> Complex<T> {
self.$method(Complex::from(other))
}
}
$(
impl $imp<Complex<$real>> 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 */ /* constants */
impl<T: Clone + Num> Zero for Complex<T> { impl<T: Clone + Num> Zero for Complex<T> {
#[inline] #[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 super::{_0_0i, _1_0i, _1_1i, _0_1i, _neg1_1i, _05_05i, all_consts};
use Zero; use Zero;
@ -880,6 +981,7 @@ mod test {
assert_eq!(_1_0i * c, c); assert_eq!(_1_0i * c, c);
} }
} }
#[test] #[test]
fn test_div() { fn test_div() {
assert_eq!(_neg1_1i / _0_1i, _1_1i); assert_eq!(_neg1_1i / _0_1i, _1_1i);
@ -889,6 +991,7 @@ mod test {
} }
} }
} }
#[test] #[test]
fn test_neg() { fn test_neg() {
assert_eq!(-_1_0i + _0_1i, _neg1_1i); 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] #[test]
fn test_to_string() { fn test_to_string() {
fn test(c : Complex64, s: String) { fn test(c : Complex64, s: String) {
@ -915,8 +1046,6 @@ mod test {
#[test] #[test]
fn test_hash() { fn test_hash() {
let a = Complex::new(0i32, 0i32); let a = Complex::new(0i32, 0i32);
let b = Complex::new(1i32, 0i32); let b = Complex::new(1i32, 0i32);
let c = Complex::new(0i32, 1i32); let c = Complex::new(0i32, 1i32);