haar_lib/num/
complex.rs

1//! 複素数
2use crate::impl_from;
3use crate::impl_ops;
4
5/// 複素数
6#[derive(Clone, Copy, Default, Debug, PartialEq)]
7pub struct Complex {
8    /// 実部
9    pub re: f64,
10    /// 虚部
11    pub im: f64,
12}
13
14impl Complex {
15    /// 直交座標系の複素数$a + bi$を返す。
16    pub fn new(a: f64, b: f64) -> Self {
17        Self { re: a, im: b }
18    }
19
20    /// 絶対値$|z| = \sqrt{a^2 + b^2}$を返す。
21    pub fn abs(self) -> f64 {
22        (self.re * self.re + self.im * self.im).sqrt()
23    }
24
25    /// 偏角$\arg z \in (-\pi, \pi]$を返す。
26    pub fn arg(self) -> f64 {
27        self.im.atan2(self.re)
28    }
29
30    /// 複素共役$\bar{z} = a - bi$を返す。
31    pub fn conjugate(self) -> Self {
32        Self {
33            re: self.re,
34            im: -self.im,
35        }
36    }
37
38    /// 極座標系の複素数$re^{ia}$を返す。
39    pub fn polar(r: f64, a: f64) -> Self {
40        Self {
41            re: r * a.cos(),
42            im: r * a.sin(),
43        }
44    }
45}
46
47impl_ops!(Add for Complex, |a: Self, b: Self| Self::new(a.re + b.re, a.im + b.im));
48impl_ops!(Sub for Complex, |a: Self, b: Self| Self::new(a.re - b.re, a.im - b.im));
49impl_ops!(Mul for Complex, |a: Self, b: Self| Self::new(
50    a.re * b.re - a.im * b.im,
51    a.re * b.im + a.im * b.re
52));
53impl_ops!(Div for Complex, |a: Self, b: Self| Self::new(
54    (a.re * b.re + a.im * b.im) / (b.re * b.re + b.im * b.im),
55    (a.im * b.re - a.re * b.im) / (b.re * b.re + b.im * b.im)
56));
57impl_ops!(Neg for Complex, |a: Self| Self::new(-a.re, -a.im));
58
59impl_ops!(AddAssign for Complex, |a: &mut Self, b: Self| *a = *a + b);
60impl_ops!(SubAssign for Complex, |a: &mut Self, b: Self| *a = *a - b);
61impl_ops!(MulAssign for Complex, |a: &mut Self, b: Self| *a = *a * b);
62impl_ops!(DivAssign for Complex, |a: &mut Self, b: Self| *a = *a / b);
63
64impl_from!((f64, f64) => Complex, |(a, b)| Self::new(a, b));
65impl_from!(Complex => (f64, f64), |Complex { re, im }| (re, im));
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70    use std::f64::consts::PI;
71
72    #[test]
73    fn test() {
74        assert_eq!(
75            Complex::new(1.0, 1.0) + Complex::new(3.0, -2.5),
76            Complex::new(4.0, -1.5)
77        );
78
79        assert_eq!(
80            Complex::new(1.0, 1.0) - Complex::new(3.0, -2.5),
81            Complex::new(-2.0, 3.5)
82        );
83
84        assert_eq!(
85            Complex::new(1.0, 1.0) * Complex::new(3.0, -2.5),
86            Complex::new(5.5, 0.5)
87        );
88
89        assert_eq!(
90            Complex::polar(2.0, PI / 4.0) * Complex::polar(4.0, PI / 8.0),
91            Complex::polar(8.0, PI * 3.0 / 8.0)
92        );
93    }
94}