1use super::{Complex, Float};
4use core::iter::{Product, Sum};
5use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
6
7impl<T: Float> Complex<T> {
8 #[inline]
9 fn plus(a: Self, b: Self) -> Self {
10 Complex::new(a.re + b.re, a.im + b.im)
11 }
12
13 #[inline]
14 fn plus_real(a: Self, b: T) -> Self {
15 Complex::new(a.re + b, a.im)
16 }
17
18 #[inline]
19 fn real_plus(a: T, b: Self) -> Self {
20 Complex::new(a + b.re, b.im)
21 }
22
23 #[inline]
24 fn minus(a: Self, b: Self) -> Self {
25 Complex::new(a.re - b.re, a.im - b.im)
26 }
27
28 #[inline]
29 fn minus_real(a: Self, b: T) -> Self {
30 Complex::new(a.re - b, a.im)
31 }
32
33 #[inline]
34 fn real_minus(a: T, b: Self) -> Self {
35 Complex::new(a - b.re, -b.im)
36 }
37
38 #[inline]
39 fn times(a: Self, b: Self) -> Self {
40 Complex::new(a.re * b.re - a.im * b.im, a.re * b.im + a.im * b.re)
41 }
42
43 #[inline]
44 fn times_real(a: Self, b: T) -> Self {
45 Complex::new(a.re * b, a.im * b)
46 }
47
48 #[inline]
49 fn real_times(a: T, b: Self) -> Self {
50 Complex::new(a * b.re, a * b.im)
51 }
52
53 #[inline]
72 fn over(a: Self, b: Self) -> Self {
73 let zero = T::ZERO;
74 let (aa, ab, ba, bb) = (a.re.abs(), a.im.abs(), b.re.abs(), b.im.abs());
75 let limit = T::MAX * T::HALF;
76 let tiny = T::MIN_POSITIVE * T::from_f64(4.0) / T::EPSILON;
77 let big = (aa >= limit) | (ab >= limit) | (ba >= limit) | (bb >= limit);
78 let small = ((aa <= tiny) & (ab <= tiny)) | ((ba <= tiny) & (bb <= tiny));
79 let s = if big {
80 T::HALF
81 } else if small {
82 T::from_f64(8.0) / (T::EPSILON * T::EPSILON)
83 } else {
84 T::ONE
85 };
86 let (ar, ai, br, bi) = (a.re * s, a.im * s, b.re * s, b.im * s);
87 let swap = br.abs() < bi.abs();
88 let (p, q) = if swap { (bi, br) } else { (br, bi) };
89 let (x, y) = if swap { (ai, ar) } else { (ar, ai) };
90 let r = if p == zero { zero } else { q / p };
91 let d = p + q * r;
92 let (yr, xr) = if r.abs() < T::MIN_POSITIVE && q != zero && p != zero {
93 ((y * q) / p, (x * q) / p)
94 } else {
95 (y * r, x * r)
96 };
97 let im = (y - xr) / d;
98 Complex::new((x + yr) / d, if swap { -im } else { im })
99 }
100
101 #[inline]
102 fn over_real(a: Self, b: T) -> Self {
103 Complex::new(a.re / b, a.im / b)
104 }
105
106 #[inline]
107 fn real_over(a: T, b: Self) -> Self {
108 Complex::over(Complex::from(a), b)
109 }
110}
111
112macro_rules! operators {
115 ($op:ident, $method:ident, $assign:ident, $assign_method:ident, $both:ident, $real:ident) => {
116 impl<T: Float> $op for Complex<T> {
117 type Output = Self;
118 #[inline]
119 fn $method(self, rhs: Self) -> Self {
120 Complex::$both(self, rhs)
121 }
122 }
123 impl<T: Float> $op<&Complex<T>> for Complex<T> {
124 type Output = Self;
125 #[inline]
126 fn $method(self, rhs: &Self) -> Self {
127 Complex::$both(self, *rhs)
128 }
129 }
130 impl<T: Float> $op<Complex<T>> for &Complex<T> {
131 type Output = Complex<T>;
132 #[inline]
133 fn $method(self, rhs: Complex<T>) -> Complex<T> {
134 Complex::$both(*self, rhs)
135 }
136 }
137 impl<T: Float> $op<&Complex<T>> for &Complex<T> {
138 type Output = Complex<T>;
139 #[inline]
140 fn $method(self, rhs: &Complex<T>) -> Complex<T> {
141 Complex::$both(*self, *rhs)
142 }
143 }
144 impl<T: Float> $op<T> for Complex<T> {
145 type Output = Self;
146 #[inline]
147 fn $method(self, rhs: T) -> Self {
148 Complex::$real(self, rhs)
149 }
150 }
151 impl<T: Float> $op<&T> for Complex<T> {
152 type Output = Self;
153 #[inline]
154 fn $method(self, rhs: &T) -> Self {
155 Complex::$real(self, *rhs)
156 }
157 }
158 impl<T: Float> $op<T> for &Complex<T> {
159 type Output = Complex<T>;
160 #[inline]
161 fn $method(self, rhs: T) -> Complex<T> {
162 Complex::$real(*self, rhs)
163 }
164 }
165 impl<T: Float> $op<&T> for &Complex<T> {
166 type Output = Complex<T>;
167 #[inline]
168 fn $method(self, rhs: &T) -> Complex<T> {
169 Complex::$real(*self, *rhs)
170 }
171 }
172 impl<T: Float> $assign for Complex<T> {
173 #[inline]
174 fn $assign_method(&mut self, rhs: Self) {
175 *self = Complex::$both(*self, rhs);
176 }
177 }
178 impl<T: Float> $assign<&Complex<T>> for Complex<T> {
179 #[inline]
180 fn $assign_method(&mut self, rhs: &Self) {
181 *self = Complex::$both(*self, *rhs);
182 }
183 }
184 impl<T: Float> $assign<T> for Complex<T> {
185 #[inline]
186 fn $assign_method(&mut self, rhs: T) {
187 *self = Complex::$real(*self, rhs);
188 }
189 }
190 impl<T: Float> $assign<&T> for Complex<T> {
191 #[inline]
192 fn $assign_method(&mut self, rhs: &T) {
193 *self = Complex::$real(*self, *rhs);
194 }
195 }
196 };
197}
198
199operators!(Add, add, AddAssign, add_assign, plus, plus_real);
200operators!(Sub, sub, SubAssign, sub_assign, minus, minus_real);
201operators!(Mul, mul, MulAssign, mul_assign, times, times_real);
202operators!(Div, div, DivAssign, div_assign, over, over_real);
203
204macro_rules! left {
207 ($t:ident, $op:ident, $method:ident, $left:ident) => {
208 impl $op<Complex<$t>> for $t {
209 type Output = Complex<$t>;
210 #[inline]
211 fn $method(self, rhs: Complex<$t>) -> Complex<$t> {
212 Complex::$left(self, rhs)
213 }
214 }
215 impl $op<&Complex<$t>> for $t {
216 type Output = Complex<$t>;
217 #[inline]
218 fn $method(self, rhs: &Complex<$t>) -> Complex<$t> {
219 Complex::$left(self, *rhs)
220 }
221 }
222 impl $op<Complex<$t>> for &$t {
223 type Output = Complex<$t>;
224 #[inline]
225 fn $method(self, rhs: Complex<$t>) -> Complex<$t> {
226 Complex::$left(*self, rhs)
227 }
228 }
229 impl $op<&Complex<$t>> for &$t {
230 type Output = Complex<$t>;
231 #[inline]
232 fn $method(self, rhs: &Complex<$t>) -> Complex<$t> {
233 Complex::$left(*self, *rhs)
234 }
235 }
236 };
237}
238
239macro_rules! lefts {
240 ($t:ident) => {
241 left!($t, Add, add, real_plus);
242 left!($t, Sub, sub, real_minus);
243 left!($t, Mul, mul, real_times);
244 left!($t, Div, div, real_over);
245 };
246}
247
248lefts!(f32);
249lefts!(f64);
250
251impl<T: Float> Neg for Complex<T> {
252 type Output = Self;
253 #[inline]
254 fn neg(self) -> Self {
255 Complex::new(-self.re, -self.im)
256 }
257}
258
259impl<T: Float> Neg for &Complex<T> {
260 type Output = Complex<T>;
261 #[inline]
262 fn neg(self) -> Complex<T> {
263 -*self
264 }
265}
266
267impl<T: Float> Sum for Complex<T> {
268 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
269 iter.fold(Self::ZERO, |s, z| s + z)
270 }
271}
272
273impl<'a, T: Float> Sum<&'a Complex<T>> for Complex<T> {
274 fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
275 iter.fold(Self::ZERO, |s, z| s + z)
276 }
277}
278
279impl<T: Float> Product for Complex<T> {
280 fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
281 iter.fold(Self::ONE, |p, z| p * z)
282 }
283}
284
285impl<'a, T: Float> Product<&'a Complex<T>> for Complex<T> {
286 fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
287 iter.fold(Self::ONE, |p, z| p * z)
288 }
289}