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