abels_complex/
rectangular.rs

1use crate::polar::*;
2use core::fmt;
3use core::ops::*;
4use core::write;
5#[cfg(feature = "libm")]
6use num_traits::real::Real;
7
8/// Creates a complex number in rectangular form.
9#[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    // #[test]
641    // fn format_display() {
642    //     for n in random_samples::<i32>() {
643    //         let x = n as f32 * 0.01;
644    //
645    //         let z: Complex = x.into();
646    //         assert_eq!(format!("{}", z), format!("{}", x));
647    //         assert_eq!(format!("{:+}", z), format!("{:+}", x));
648    //
649    //         let z = complex(0.0, x);
650    //         assert_eq!(format!("{}", z), format!("{}i", x));
651    //         assert_eq!(format!("{:+}", z), format!("{:+}i", x));
652    //     }
653    //     assert_eq!(format!("{}", Complex::ZERO), "0");
654    //     assert_eq!(format!("{}", Complex::ONE), "1");
655    //     assert_eq!(format!("{}", Complex::NEG_ONE), "-1");
656    //     assert_eq!(format!("{}", Complex::I), "i");
657    //     assert_eq!(format!("{}", Complex::NEG_I), "-i");
658    //
659    //     assert_eq!(format!("{:+}", Complex::ZERO), "+0");
660    //     assert_eq!(format!("{:+}", -Complex::ZERO), "-0");
661    //     assert_eq!(format!("{:+}", Complex::ONE), "+1");
662    //     assert_eq!(format!("{}", 2.0 * Complex::I), "2i");
663    //     assert_eq!(format!("{}", 2.0 * Complex::NEG_I), "-2i");
664    //
665    //     assert_eq!(format!("{:+}", Complex::I), "+i");
666    //     assert_eq!(format!("{:+}", 2.0 * Complex::I), "+2i");
667    //
668    //     assert_eq!(format!("{}", complex(1.0, 1.0)), "1+i");
669    //     assert_eq!(format!("{}", complex(-1.0, 1.0)), "-1+i");
670    //     assert_eq!(format!("{}", complex(-1.0, -1.0)), "-1-i");
671    //     assert_eq!(format!("{}", complex(1.0, -1.0)), "1-i");
672    //
673    //     assert_eq!(format!("{}", complex(2.0, 2.0)), "2+2i");
674    //     assert_eq!(format!("{}", complex(-2.0, 2.0)), "-2+2i");
675    //     assert_eq!(format!("{}", complex(-2.0, -2.0)), "-2-2i");
676    //     assert_eq!(format!("{}", complex(2.0, -2.0)), "2-2i");
677    //
678    //     assert_eq!(format!("{}", complex(1.234, 1.234)), "1.234+1.234i");
679    //     assert_eq!(format!("{:.2}", complex(1.234, 1.234)), "1.23+1.23i");
680    //     assert_eq!(format!("{:+}", complex(1.234, 1.234)), "+1.234+1.234i");
681    //     assert_eq!(format!("{:+.2}", complex(1.234, 1.234)), "+1.23+1.23i");
682    // }
683}