summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Worthe <justin.worthe@gmail.com>2016-11-26 22:56:37 +0200
committerJustin Worthe <justin.worthe@gmail.com>2016-11-26 22:56:37 +0200
commite4a79af68b2542bec5cd30237869cef0fc911f77 (patch)
tree99d8ef2ef5a3530566732adccd2abf1ee13fbcb3
parent253500a2088718957831dbec5922aa53e2fe113e (diff)
Adding constructors from polar coordinates
-rw-r--r--src/complex.rs68
-rw-r--r--src/lib.rs1
-rw-r--r--src/num_traits.rs80
3 files changed, 146 insertions, 3 deletions
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<T> {
@@ -6,12 +7,27 @@ pub struct Complex<T> {
imag: T
}
-impl<T: Clone> Complex<T> {
- fn new(real: T, imag: T) -> Complex<T> {
+impl<T> Complex<T> {
+ pub fn new(real: T, imag: T) -> Complex<T> {
Complex{real: real, imag: imag}
}
}
+impl<T> Complex<T> where T: Trig<T> + Mul<Output=T> + Copy {
+ pub fn from_polar(r: T, theta: T) -> Complex<T> {
+ let real = r*theta.cos();
+ let imag = r*theta.sin();
+ Complex::new(real, imag)
+ }
+}
+impl<T> Complex<T> where T: Trig<T> + Pow<T> + Add<Output=T> + 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<T> Add for Complex<T> where T: Add<Output=T> + Copy {
type Output = Complex<T>;
@@ -22,14 +38,60 @@ impl<T> Add for Complex<T> where T: Add<Output=T> + Copy {
}
}
+impl<T> Sub for Complex<T> where T: Sub<Output=T> + Copy {
+ type Output = Complex<T>;
+
+ 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<T> {
+ 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<f32> 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<f64> 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<T> {
+ fn powi(self, n: i32) -> Self;
+ fn powf(self, n: T) -> Self;
+ fn sqrt(self) -> Self;
+}
+
+impl Pow<f32> 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<f64> 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()
+ }
+}