rft/
complex.rs

1use num::{self, Zero, One};
2use Precision;
3
4/// Trait representing complex numbers.
5pub trait Complex: Zero + One + Clone {
6	/// Gets the real part.
7	fn real(&self) -> Precision;
8
9	/// Gets the imaginary part.
10	fn imag(&self) -> Precision;
11
12	/// Returns a `num::Complex` so it can be used internally.
13	#[inline]
14	fn to_num(&self) -> num::Complex<Precision> {
15		num::Complex::new(self.real(), self.imag())
16	}
17}
18
19/// Trait representing mutable complex numbers.
20pub trait ComplexMut: Complex {
21	/// Sets the real part.
22	fn set_real(&mut self, value: Precision);
23
24	/// Sets the imaginary part.
25	fn set_imag(&mut self, value: Precision);
26
27	/// Sets the real and imaginary part from another `Complex`.
28	#[inline]
29	fn set<C: Complex>(&mut self, value: &C) {
30		self.set_real(value.real());
31		self.set_imag(value.imag());
32	}
33
34	/// Multiplies in-place with another `Complex`.
35	#[inline]
36	fn mul<C: Complex>(&mut self, value: &C) {
37		let real = self.real();
38		let imag = self.imag();
39
40		self.set_real(real * value.real() - imag * value.imag());
41		self.set_imag(real * value.imag() + imag * value.real());
42	}
43
44	/// Scales in-place.
45	#[inline]
46	fn scale(&mut self, value: Precision) {
47		let real = self.real();
48		let imag = self.imag();
49
50		self.set_real(real * value);
51		self.set_imag(imag * value);
52	}
53
54	/// Divides in-place with another `Complex`.
55	#[inline]
56	fn div<C: Complex>(&mut self, value: &C) {
57		let real = self.real();
58		let imag = self.imag();
59		let sqr  = self.real() * self.real() + self.imag() * self.imag();
60
61		self.set_real((real * value.real() + imag * value.imag()) / sqr);
62		self.set_imag((imag * value.real() - real * value.imag()) / sqr);
63	}
64
65	/// Unscales in-place.
66	#[inline]
67	fn unscale(&mut self, value: Precision) {
68		let real = self.real();
69		let imag = self.imag();
70
71		self.set_real(real / value);
72		self.set_imag(imag / value);
73	}
74}
75
76impl Complex for num::Complex<f32> {
77	#[inline(always)]
78	fn real(&self) -> Precision {
79		self.re as Precision
80	}
81
82	#[inline(always)]
83	fn imag(&self) -> Precision {
84		self.im as Precision
85	}
86}
87
88impl Complex for num::Complex<f64> {
89	#[inline(always)]
90	fn real(&self) -> Precision {
91		self.re as Precision
92	}
93
94	#[inline(always)]
95	fn imag(&self) -> Precision {
96		self.im as Precision
97	}
98}
99
100impl ComplexMut for num::Complex<f32> {
101	#[inline(always)]
102	fn set_real(&mut self, value: Precision) {
103		self.re = value as f32;
104	}
105
106	#[inline(always)]
107	fn set_imag(&mut self, value: Precision) {
108		self.im = value as f32;
109	}
110}
111
112impl ComplexMut for num::Complex<f64> {
113	#[inline(always)]
114	fn set_real(&mut self, value: Precision) {
115		self.re = value as f64;
116	}
117
118	#[inline(always)]
119	fn set_imag(&mut self, value: Precision) {
120		self.im = value as f64;
121	}
122}
123
124#[cfg(test)]
125mod tests {
126	use super::Complex;
127	use std::{u8, i16, i32};
128
129	macro_rules! assert_approx_eq {
130		($a:expr, $r:expr, $i:expr, $p:expr) => (
131			assert_eq!(format!("{:.1$}", $a.real(), $p), format!("{:.1$}", $r, $p));
132			assert_eq!(format!("{:.1$}", $a.imag(), $p), format!("{:.1$}", $i, $p));
133		)
134	}
135
136	#[test]
137	fn u8() {
138		assert_approx_eq!(u8::MAX,  1.00, 0.00, 2);
139		assert_approx_eq!(u8::MIN, -0.99, 0.00, 2);
140	}
141
142	#[test]
143	fn i16() {
144		assert_approx_eq!(i16::MAX,  1.00, 0.00, 2);
145		assert_approx_eq!(i16::MIN, -1.00, 0.00, 2);
146	}
147
148	#[test]
149	fn i32() {
150		assert_approx_eq!(i32::MAX,  1.00, 0.00, 2);
151		assert_approx_eq!(i32::MIN, -1.00, 0.00, 2);
152	}
153}