From e4a79af68b2542bec5cd30237869cef0fc911f77 Mon Sep 17 00:00:00 2001 From: Justin Worthe Date: Sat, 26 Nov 2016 22:56:37 +0200 Subject: Adding constructors from polar coordinates --- src/complex.rs | 68 +++++++++++++++++++++++++++++++++++++++++++--- src/lib.rs | 1 + src/num_traits.rs | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 src/num_traits.rs (limited to 'src') diff --git a/src/complex.rs b/src/complex.rs index 0919564..1a8bc20 100644 --- a/src/complex.rs +++ b/src/complex.rs @@ -1,4 +1,5 @@ -use std::ops::Add; +use std::ops::{Add, Sub, Mul}; +use ::num_traits::{Trig, Pow}; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct Complex { @@ -6,12 +7,27 @@ pub struct Complex { imag: T } -impl Complex { - fn new(real: T, imag: T) -> Complex { +impl Complex { + pub fn new(real: T, imag: T) -> Complex { Complex{real: real, imag: imag} } } +impl Complex where T: Trig + Mul + Copy { + pub fn from_polar(r: T, theta: T) -> Complex { + let real = r*theta.cos(); + let imag = r*theta.sin(); + Complex::new(real, imag) + } +} +impl Complex where T: Trig + Pow + Add + Copy { + pub fn to_polar(self) -> (T, T) { + let r = (self.real.powi(2) + self.imag.powi(2)).sqrt(); + let theta = self.imag.atan2(self.real); + (r, theta) + } +} + impl Add for Complex where T: Add + Copy { type Output = Complex; @@ -22,14 +38,60 @@ impl Add for Complex where T: Add + Copy { } } +impl Sub for Complex where T: Sub + Copy { + type Output = Complex; + + fn sub(self, other: Self) -> Self { + let real = self.real - other.real; + let imag = self.imag - other.imag; + Complex::new(real, imag) + } +} + #[cfg(test)] mod tests { use super::*; + use std::f32; + #[test] fn addition() { let a = Complex::new(1, 5); let b = Complex::new(-3, 2); assert_eq!(a+b, Complex::new(-2, 7)); } + + #[test] + fn subtraction() { + let a = Complex::new(1, 5); + let b = Complex::new(-3, 2); + assert_eq!(a-b, Complex::new(4, 3)); + } + + + #[test] + fn from_polar() { + let right = Complex::from_polar(1.0 as f32, 0.0 as f32); + assert!((right.real-1.0).abs() < f32::EPSILON); + assert!((right.imag-0.0).abs() < f32::EPSILON); + + let up = Complex::from_polar(1.0 as f32, f32::consts::PI/2.0); + assert!((up.real-0.0).abs() < f32::EPSILON/2.0); + assert!((up.imag-1.0).abs() < f32::EPSILON/2.0); + + let left = Complex::from_polar(1.0 as f32, f32::consts::PI); + assert!((left.real+1.0).abs() < f32::EPSILON); + assert!((left.imag-0.0).abs() < f32::EPSILON); + + let down = Complex::from_polar(1.0 as f32, f32::consts::PI*3.0/2.0); + assert!((down.real-0.0).abs() < f32::EPSILON); + assert!((down.imag+1.0).abs() < f32::EPSILON); + + //not sure why the error here is more than epsilon. My guess + // is that it's the 2.0*PI, meaning that the value for PI has + // twice the normal error. + let rev = Complex::from_polar(1.0 as f32, f32::consts::PI*2.0); + assert!((rev.real-1.0).abs() < f32::EPSILON*2.0); + assert!((rev.imag-0.0).abs() < f32::EPSILON*2.0); + } } diff --git a/src/lib.rs b/src/lib.rs index 3987f3d..818890f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1 +1,2 @@ pub mod complex; +pub mod num_traits; diff --git a/src/num_traits.rs b/src/num_traits.rs new file mode 100644 index 0000000..3e18a4b --- /dev/null +++ b/src/num_traits.rs @@ -0,0 +1,80 @@ +pub trait Trig { + fn sin(self) -> Self; + fn cos(self) -> Self; + fn tan(self) -> Self; + + fn asin(self) -> Self; + fn acos(self) -> Self; + fn atan2(self, other: Self) -> Self; +} + +impl Trig for f32 { + fn sin(self) -> Self { + self.sin() + } + fn cos(self) -> Self { + self.cos() + } + fn tan(self) -> Self { + self.tan() + } + fn asin(self) -> Self { + self.asin() + } + fn acos(self) -> Self { + self.acos() + } + fn atan2(self, other: Self) -> Self { + self.atan2(other) + } +} +impl Trig for f64 { + fn sin(self) -> Self { + self.sin() + } + fn cos(self) -> Self { + self.cos() + } + fn tan(self) -> Self { + self.tan() + } + fn asin(self) -> Self { + self.asin() + } + fn acos(self) -> Self { + self.acos() + } + fn atan2(self, other: Self) -> Self { + self.atan2(other) + } +} + + +pub trait Pow { + fn powi(self, n: i32) -> Self; + fn powf(self, n: T) -> Self; + fn sqrt(self) -> Self; +} + +impl Pow for f32 { + fn powi(self, n: i32) -> Self { + self.powi(n) + } + fn powf(self, n: Self) -> Self { + self.powf(n) + } + fn sqrt(self) -> Self { + self.sqrt() + } +} +impl Pow for f64 { + fn powi(self, n: i32) -> Self { + self.powi(n) + } + fn powf(self, n: Self) -> Self { + self.powf(n) + } + fn sqrt(self) -> Self { + self.sqrt() + } +} -- cgit v1.2.3