1use crate::polar::*;
2use core::fmt;
3use core::ops::*;
4use core::write;
5#[cfg(feature = "libm")]
6use num_traits::real::Real;
7
8#[inline(always)]
10#[must_use]
11pub const fn complex(re: f32, im: f32) -> Complex {
12 Complex::new(re, im)
13}
14
15#[derive(Clone, Copy, PartialEq, Debug)]
16#[repr(C)]
17pub struct Complex {
18 pub re: f32,
19 pub im: f32,
20}
21
22impl Complex {
23 pub const ZERO: Self = complex(0.0, 0.0);
24 pub const ONE: Self = complex(1.0, 0.0);
25 pub const NEG_ONE: Self = complex(-1.0, 0.0);
26 pub const I: Self = complex(0.0, 1.0);
27 pub const NEG_I: Self = complex(0.0, -1.0);
28
29 pub const fn new(re: f32, im: f32) -> Self {
30 Self { re, im }
31 }
32
33 pub const fn conjugate(self) -> Self {
34 complex(self.re, -self.im)
35 }
36
37 pub fn abs(self) -> f32 {
38 self.abs_sq().sqrt()
39 }
40
41 pub fn abs_sq(self) -> f32 {
42 self.re * self.re + self.im * self.im
43 }
44
45 pub fn arg(self) -> f32 {
46 self.im.atan2(self.re)
47 }
48
49 pub fn recip(self) -> Self {
50 self.conjugate() / self.abs_sq()
51 }
52
53 pub fn sqrt(self) -> Self {
54 let abs = self.abs();
55 complex(
56 (0.5 * (abs + self.re)).sqrt(),
57 (0.5 * (abs - self.re)).sqrt().copysign(self.im),
58 )
59 }
60
61 pub fn to_polar(self) -> ComplexPolar {
62 complex_polar(self.abs(), self.arg())
63 }
64
65 pub fn exp(self) -> ComplexPolar {
66 complex_polar(self.re.exp(), self.im)
67 }
68
69 pub fn log(self) -> Self {
70 self.to_polar().log()
71 }
72
73 pub fn powi(self, n: i32) -> ComplexPolar {
74 self.to_polar().powi(n)
75 }
76
77 pub fn powf(self, x: f32) -> ComplexPolar {
78 self.to_polar().powf(x)
79 }
80
81 pub fn distance(self, other: Self) -> f32 {
82 (self - other).abs()
83 }
84
85 pub fn distance_squared(self, other: Self) -> f32 {
86 (self - other).abs_sq()
87 }
88}
89
90impl Add for Complex {
91 type Output = Self;
92 fn add(mut self, other: Self) -> Self::Output {
93 self += other;
94 self
95 }
96}
97
98impl Add<f32> for Complex {
99 type Output = Self;
100 fn add(mut self, re: f32) -> Self::Output {
101 self += re;
102 self
103 }
104}
105
106impl Add<Complex> for f32 {
107 type Output = Complex;
108 fn add(self, mut z: Complex) -> Self::Output {
109 z += self;
110 z
111 }
112}
113
114impl AddAssign for Complex {
115 fn add_assign(&mut self, other: Self) {
116 self.re += other.re;
117 self.im += other.im;
118 }
119}
120
121impl AddAssign<f32> for Complex {
122 fn add_assign(&mut self, re: f32) {
123 self.re += re;
124 }
125}
126
127impl Sub for Complex {
128 type Output = Self;
129 fn sub(mut self, other: Self) -> Self::Output {
130 self -= other;
131 self
132 }
133}
134
135impl Sub<f32> for Complex {
136 type Output = Self;
137 fn sub(mut self, re: f32) -> Self::Output {
138 self -= re;
139 self
140 }
141}
142
143impl Sub<Complex> for f32 {
144 type Output = Complex;
145 fn sub(self, z: Complex) -> Self::Output {
146 complex(self - z.re, -z.im)
147 }
148}
149
150impl SubAssign for Complex {
151 fn sub_assign(&mut self, other: Self) {
152 self.re -= other.re;
153 self.im -= other.im;
154 }
155}
156
157impl SubAssign<f32> for Complex {
158 fn sub_assign(&mut self, re: f32) {
159 self.re -= re;
160 }
161}
162
163impl Mul for Complex {
164 type Output = Self;
165 fn mul(mut self, other: Self) -> Self::Output {
166 self *= other;
167 self
168 }
169}
170
171impl Mul<f32> for Complex {
172 type Output = Self;
173 fn mul(mut self, re: f32) -> Self::Output {
174 self *= re;
175 self
176 }
177}
178
179impl Mul<Complex> for f32 {
180 type Output = Complex;
181 fn mul(self, mut other: Complex) -> Self::Output {
182 other *= self;
183 other
184 }
185}
186
187impl MulAssign for Complex {
188 fn mul_assign(&mut self, other: Self) {
189 let re = self.re * other.re - self.im * other.im;
190 self.im = self.re * other.im + self.im * other.re;
191 self.re = re;
192 }
193}
194
195impl MulAssign<f32> for Complex {
196 fn mul_assign(&mut self, re: f32) {
197 self.re *= re;
198 self.im *= re;
199 }
200}
201
202impl Div for Complex {
203 type Output = Self;
204 fn div(self, other: Self) -> Self::Output {
205 self * other.conjugate() / other.abs_sq()
206 }
207}
208
209impl Div<f32> for Complex {
210 type Output = Self;
211 fn div(mut self, re: f32) -> Self::Output {
212 self /= re;
213 self
214 }
215}
216
217impl Div<Complex> for f32 {
218 type Output = Complex;
219 fn div(self, other: Complex) -> Self::Output {
220 self * other.conjugate() / other.abs_sq()
221 }
222}
223
224impl DivAssign for Complex {
225 fn div_assign(&mut self, other: Self) {
226 *self = *self / other;
227 }
228}
229
230impl DivAssign<f32> for Complex {
231 fn div_assign(&mut self, re: f32) {
232 self.re /= re;
233 self.im /= re;
234 }
235}
236
237impl Neg for Complex {
238 type Output = Self;
239 fn neg(self) -> Self::Output {
240 complex(-self.re, -self.im)
241 }
242}
243
244impl fmt::Display for Complex {
245 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
246 fn fmt_x(f: &mut fmt::Formatter, x: f32, sign_plus: bool) -> fmt::Result {
247 match (f.precision(), sign_plus) {
248 (None, false) => write!(f, "{}", x),
249 (None, true) => write!(f, "{:+}", x),
250 (Some(p), false) => write!(f, "{:.*}", p, x),
251 (Some(p), true) => write!(f, "{:+.*}", p, x),
252 }
253 }
254 match (self.re, self.im, f.sign_plus()) {
255 (re, 0.0, sp) => fmt_x(f, re, sp),
256 (0.0, 1.0, false) => write!(f, "i"),
257 (0.0, 1.0, true) => write!(f, "+i"),
258 (0.0, -1.0, _) => write!(f, "-i"),
259 (0.0, im, sp) => {
260 fmt_x(f, im, sp)?;
261 write!(f, "i")
262 }
263 (re, 1.0, sp) => {
264 fmt_x(f, re, sp)?;
265 write!(f, "+i")
266 }
267 (re, -1.0, sp) => {
268 fmt_x(f, re, sp)?;
269 write!(f, "-i")
270 }
271 (re, im, sp) => {
272 fmt_x(f, re, sp)?;
273 fmt_x(f, im, true)?;
274 write!(f, "i")
275 }
276 }
277 }
278}
279
280#[cfg(feature = "rand")]
281impl rand::distr::Distribution<Complex> for rand::distr::StandardUniform {
282 fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> Complex {
283 rng.sample::<ComplexPolar, _>(self).to_rectangular()
284 }
285}
286
287#[cfg(feature = "approx")]
288use approx::{AbsDiffEq, RelativeEq, UlpsEq};
289
290#[cfg(feature = "approx")]
291impl AbsDiffEq for Complex {
292 type Epsilon = <f32 as AbsDiffEq>::Epsilon;
293 fn default_epsilon() -> Self::Epsilon {
294 f32::default_epsilon()
295 }
296 fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
297 f32::abs_diff_eq(&self.re, &other.re, epsilon)
298 && f32::abs_diff_eq(&self.im, &other.im, epsilon)
299 }
300}
301
302#[cfg(feature = "approx")]
303impl RelativeEq for Complex {
304 fn default_max_relative() -> Self::Epsilon {
305 f32::default_max_relative()
306 }
307 fn relative_eq(
308 &self,
309 other: &Self,
310 epsilon: Self::Epsilon,
311 max_relative: Self::Epsilon,
312 ) -> bool {
313 f32::relative_eq(&self.re, &other.re, epsilon, max_relative)
314 && f32::relative_eq(&self.im, &other.im, epsilon, max_relative)
315 }
316}
317
318#[cfg(feature = "approx")]
319impl UlpsEq for Complex {
320 fn default_max_ulps() -> u32 {
321 f32::default_max_ulps()
322 }
323 fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
324 f32::ulps_eq(&self.re, &other.re, epsilon, max_ulps)
325 && f32::ulps_eq(&self.im, &other.im, epsilon, max_ulps)
326 }
327}
328
329impl From<f32> for Complex {
330 fn from(value: f32) -> Self {
331 complex(value, 0.0)
332 }
333}
334
335#[cfg(feature = "glam")]
336impl From<glam::Vec2> for Complex {
337 fn from(v: glam::Vec2) -> Self {
338 complex(v.x, v.y)
339 }
340}
341
342#[cfg(feature = "glam")]
343impl From<Complex> for glam::Vec2 {
344 fn from(z: Complex) -> Self {
345 glam::vec2(z.re, z.im)
346 }
347}
348
349#[cfg(test)]
350mod tests {
351 use super::*;
352 use approx::*;
353 use core::f32::consts::{E, FRAC_PI_2, PI, SQRT_2};
354 use core::iter::Iterator;
355 use rand::{
356 distr::{Distribution, StandardUniform},
357 rngs::StdRng,
358 Rng, SeedableRng,
359 };
360
361 const NUM_SAMPLES: usize = 100;
362
363 fn random_samples<T>() -> impl Iterator<Item = T>
364 where
365 StandardUniform: Distribution<T>,
366 {
367 StdRng::seed_from_u64(21)
368 .sample_iter(StandardUniform)
369 .take(NUM_SAMPLES)
370 }
371
372 #[test]
373 fn addition() {
374 for z0 in random_samples::<Complex>() {
375 for z1 in random_samples::<Complex>() {
376 let z = z0 + z1;
377 assert_eq!(z.re, z0.re + z1.re);
378 assert_eq!(z.im, z0.im + z1.im);
379
380 let z = z0 + z1.re;
381 assert_eq!(z.re, z0.re + z1.re);
382 assert_eq!(z.im, z0.im);
383
384 let z = z0.re + z1;
385 assert_eq!(z.re, z0.re + z1.re);
386 assert_eq!(z.im, z1.im);
387
388 let mut z = z0;
389 z += z1;
390 assert_eq!(z, z0 + z1);
391
392 let mut z = z0;
393 z += z1.re;
394 assert_eq!(z, z0 + z1.re);
395 }
396 assert_eq!(z0 + Complex::ZERO, z0);
397 }
398 }
399
400 #[test]
401 fn subtraction() {
402 for z0 in random_samples::<Complex>() {
403 for z1 in random_samples::<Complex>() {
404 let z = z0 - z1;
405 assert_eq!(z.re, z0.re - z1.re);
406 assert_eq!(z.im, z0.im - z1.im);
407
408 let z = z0 - z1.re;
409 assert_eq!(z.re, z0.re - z1.re);
410 assert_eq!(z.im, z0.im);
411
412 let z = z0.re - z1;
413 assert_eq!(z.re, z0.re - z1.re);
414 assert_eq!(z.im, -z1.im);
415
416 let mut z = z0;
417 z -= z1;
418 assert_eq!(z, z0 - z1);
419
420 let mut z = z0;
421 z -= z1.re;
422 assert_eq!(z, z0 - z1.re);
423 }
424 assert_eq!(z0 - z0, Complex::ZERO);
425 assert_eq!(z0 - Complex::ZERO, z0);
426 }
427 }
428
429 #[test]
430 fn multiplication() {
431 for z0 in random_samples::<Complex>() {
432 for z1 in random_samples::<Complex>() {
433 let z = z0 * z1;
434 assert_ulps_eq!(z.abs(), z0.abs() * z1.abs());
435 assert_ulps_eq!(
436 z.arg().sin(),
437 (z0.arg() + z1.arg()).sin(),
438 epsilon = 4.0 * f32::EPSILON
439 );
440
441 let z = z0 * z1.re;
442 assert_eq!(z.re, z0.re * z1.re);
443 assert_eq!(z.im, z0.im * z1.re);
444
445 let z = z0.re * z1;
446 assert_eq!(z.re, z0.re * z1.re);
447 assert_eq!(z.im, z0.re * z1.im);
448
449 let mut z = z0;
450 z *= z1;
451 assert_eq!(z, z0 * z1);
452
453 let mut z = z0;
454 z *= z1.re;
455 assert_eq!(z, z0 * z1.re);
456 }
457 assert_eq!(z0 * Complex::ONE, z0);
458 assert_eq!(z0 * Complex::ZERO, Complex::ZERO);
459 assert_eq!(z0 * 0.0, Complex::ZERO);
460 }
461 }
462
463 #[test]
464 fn division() {
465 for z0 in random_samples::<Complex>() {
466 for z1 in random_samples::<Complex>() {
467 let z = z0 / z1;
468 assert_relative_eq!(
469 z.abs(),
470 z0.abs() / z1.abs(),
471 max_relative = 3.0 * f32::EPSILON
472 );
473 assert_ulps_eq!(
474 z.arg().sin(),
475 (z0.arg() - z1.arg()).sin(),
476 epsilon = 4.0 * f32::EPSILON
477 );
478
479 let z = z0 / z1.re;
480 assert_eq!(z.re, z0.re / z1.re);
481 assert_eq!(z.im, z0.im / z1.re);
482
483 let z = z0.re / z1;
484 assert_ulps_eq!(z.abs(), z0.re.abs() / z1.abs());
485 assert_ulps_eq!(
486 z.arg().sin(),
487 (-z0.re.signum() * z1.arg()).sin(),
488 epsilon = 2.0 * f32::EPSILON
489 );
490
491 let mut z = z0;
492 z /= z1;
493 assert_eq!(z, z0 / z1);
494
495 let mut z = z0;
496 z /= z1.re;
497 assert_eq!(z, z0 / z1.re);
498 }
499 assert_eq!(z0 / z0, Complex::ONE);
500 assert_eq!(Complex::ZERO / z0, Complex::ZERO);
501 }
502 }
503
504 #[test]
505 fn negation() {
506 for z in random_samples::<Complex>() {
507 assert_eq!(-z, complex(-z.re, -z.im));
508 }
509 assert_eq!(-Complex::ONE, Complex::NEG_ONE);
510 assert_eq!(-Complex::I, Complex::NEG_I);
511 assert_eq!(-Complex::NEG_ONE, Complex::ONE);
512 assert_eq!(-Complex::NEG_I, Complex::I);
513 }
514
515 #[test]
516 fn reciprocal() {
517 for z in random_samples::<Complex>() {
518 assert_eq!(z.recip(), 1.0 / z);
519 assert_ulps_eq!(z * z.recip(), Complex::ONE);
520 }
521 assert_eq!(Complex::ONE.recip(), Complex::ONE);
522 assert_eq!(Complex::I.recip(), Complex::NEG_I);
523 assert_eq!(Complex::NEG_ONE.recip(), Complex::NEG_ONE);
524 assert_eq!(Complex::NEG_I.recip(), Complex::I);
525 }
526
527 #[test]
528 fn sqrt() {
529 for z in random_samples::<Complex>() {
530 assert_ulps_eq!(z.sqrt().abs(), z.abs().sqrt());
531 assert_ulps_eq!(
532 z.sqrt().arg(),
533 z.arg() / 2.0,
534 epsilon = 1400.0 * f32::EPSILON
535 );
536 }
537 assert_eq!(Complex::ONE.sqrt(), Complex::ONE);
538 assert_eq!(Complex::NEG_ONE.sqrt(), Complex::I);
539 assert_eq!(complex(0.0, 2.0).sqrt(), complex(1.0, 1.0));
540 assert_eq!(complex(0.0, -2.0).sqrt(), complex(1.0, -1.0));
541 }
542
543 #[test]
544 fn abs() {
545 for z in random_samples::<Complex>() {
546 assert_ulps_eq!(z.abs_sq(), z.abs() * z.abs());
547 assert_eq!(z.abs_sq(), z.re * z.re + z.im * z.im);
548 }
549 assert_eq!(Complex::ONE.abs(), 1.0);
550 assert_eq!(Complex::I.abs(), 1.0);
551 assert_eq!(Complex::NEG_ONE.abs(), 1.0);
552 assert_eq!(Complex::NEG_I.abs(), 1.0);
553 assert_eq!(complex(1.0, 1.0).abs(), SQRT_2);
554 assert_eq!(complex(-1.0, 1.0).abs(), SQRT_2);
555 assert_eq!(complex(-1.0, -1.0).abs(), SQRT_2);
556 assert_eq!(complex(1.0, -1.0).abs(), SQRT_2);
557 }
558
559 #[test]
560 fn conjugate() {
561 for z in random_samples::<Complex>() {
562 assert_eq!(z.conjugate().re, z.re);
563 assert_eq!(z.conjugate().im, -z.im);
564 assert_eq!(z.conjugate().conjugate(), z);
565 }
566 assert_eq!(Complex::ONE.conjugate(), Complex::ONE);
567 assert_eq!(Complex::I.conjugate(), Complex::NEG_I);
568 assert_eq!(Complex::NEG_ONE.conjugate(), Complex::NEG_ONE);
569 assert_eq!(Complex::NEG_I.conjugate(), Complex::I);
570 }
571
572 #[test]
573 fn arg() {
574 assert_eq!(Complex::ONE.arg(), 0.0);
575 assert_eq!(Complex::I.arg(), FRAC_PI_2);
576 assert_eq!(Complex::NEG_ONE.arg(), PI);
577 assert_eq!(Complex::NEG_I.arg(), -FRAC_PI_2);
578 }
579
580 #[test]
581 fn exp() {
582 for z in random_samples::<Complex>() {
583 assert_eq!(z.exp().abs, z.re.exp());
584 assert_eq!(z.exp().arg, z.im);
585 assert_ulps_eq!(z.exp().log(), z);
586 }
587 assert_eq!(Complex::ONE.exp(), complex_polar(E, 0.0));
588 assert_eq!(Complex::I.exp(), complex_polar(1.0, 1.0));
589 assert_eq!(Complex::NEG_ONE.exp(), complex_polar(E.recip(), 0.0));
590 assert_eq!(Complex::NEG_I.exp(), complex_polar(1.0, -1.0));
591 }
592
593 #[test]
594 fn log() {
595 for z in random_samples::<Complex>() {
596 assert_eq!(z.log().re, z.abs().ln());
597 assert_eq!(z.log().im, z.arg());
598 assert_ulps_eq!(z.log().exp(), z.to_polar());
599 }
600 assert_eq!(Complex::ONE.log(), Complex::ZERO);
601 assert_eq!(Complex::I.log(), Complex::I * FRAC_PI_2);
602 assert_eq!(Complex::NEG_ONE.log(), Complex::I * PI);
603 assert_eq!(Complex::NEG_I.log(), Complex::I * -FRAC_PI_2);
604 }
605
606 #[test]
607 fn powi() {
608 for z in random_samples::<Complex>() {
609 assert_eq!(z.powi(0), ComplexPolar::ONE);
610 assert_eq!(z.powi(1), z.to_polar());
611 for n in random_samples::<i32>() {
612 assert_eq!(z.powi(n).abs, z.abs().powi(n));
613 assert_eq!(z.powi(n).arg, z.arg() * n as f32);
614 }
615 }
616 for n in random_samples::<i32>() {
617 assert_eq!(Complex::ZERO.powi(n.abs()), ComplexPolar::ZERO);
618 assert_eq!(Complex::ONE.powi(n), ComplexPolar::ONE);
619 }
620 }
621
622 #[test]
623 fn powf() {
624 for z in random_samples::<Complex>() {
625 assert_eq!(z.powf(0.0), ComplexPolar::ONE);
626 assert_eq!(z.powf(1.0), z.to_polar());
627 for n in random_samples::<i32>() {
628 let x = n as f32 * 0.01;
629 assert_eq!(z.powf(x).abs, z.abs().powf(x));
630 assert_eq!(z.powf(x).arg, z.arg() * x);
631 }
632 }
633 for n in random_samples::<i32>() {
634 let x = n as f32 * 0.01;
635 assert_eq!(Complex::ZERO.powf(x.abs()), ComplexPolar::ZERO);
636 assert_eq!(Complex::ONE.powf(x), ComplexPolar::ONE);
637 }
638 }
639
640 }