1use num::{self, Zero, One};
2use Precision;
3
4pub trait Complex: Zero + One + Clone {
6 fn real(&self) -> Precision;
8
9 fn imag(&self) -> Precision;
11
12 #[inline]
14 fn to_num(&self) -> num::Complex<Precision> {
15 num::Complex::new(self.real(), self.imag())
16 }
17}
18
19pub trait ComplexMut: Complex {
21 fn set_real(&mut self, value: Precision);
23
24 fn set_imag(&mut self, value: Precision);
26
27 #[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 #[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 #[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 #[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 #[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}