abels_complex/complex/
rectangular.rs

1use core::ops::*;
2pub type Complex32 = Complex<f32>;
3pub type Complex64 = Complex<f64>;
4use crate::traits::Number;
5
6use super::ComplexPolar as Polar;
7
8/// Creates a complex number in rectangular form.
9#[inline(always)]
10#[must_use]
11pub const fn complex<FT>(re: FT, im: FT) -> Complex<FT> {
12    Complex::new(re, im)
13}
14
15/// A complex number in rectangular form.
16#[derive(Clone, Copy, PartialEq, Debug, Default)]
17#[repr(C)]
18pub struct Complex<FT> {
19    pub re: FT,
20    pub im: FT,
21}
22impl<FT> Complex<FT> {
23    /// Creates a complex number.
24    pub const fn new(re: FT, im: FT) -> Self {
25        Self { re, im }
26    }
27}
28
29impl<FT: Number> Complex<FT> {
30    pub const ZERO: Self = Self::new(FT::ZERO, FT::ZERO);
31    pub const ONE: Self = Self::new(FT::ONE, FT::ZERO);
32    pub const I: Self = Self::new(FT::ZERO, FT::ONE);
33
34    /// Computes the conjugate.
35    pub fn conjugate(self) -> Self {
36        Self::new(self.re, -self.im)
37    }
38
39    /// Computes the absolute value.
40    pub fn abs(self) -> FT {
41        self.abs_sq().sqrt()
42    }
43
44    /// Computes the squared absolute value.
45    ///
46    /// This is faster than `abs()` as it avoids a square root operation.
47    pub fn abs_sq(self) -> FT {
48        self.re * self.re + self.im * self.im
49    }
50
51    /// Computes the argument in the range `(-π, +π]`.
52    pub fn arg(self) -> FT {
53        self.im.atan2(self.re)
54    }
55
56    /// Computes the reciprocal.
57    pub fn recip(self) -> Self {
58        self.conjugate() / self.abs_sq()
59    }
60
61    /// Convert to polar form.
62    pub fn to_polar(self) -> Polar<FT> {
63        Polar::new(self.abs(), self.arg())
64    }
65
66    /// Computes `e^self` where `e` is the base of the natural logarithm.
67    pub fn exp(self) -> Polar<FT> {
68        Polar::new(self.re.exp(), self.im)
69    }
70
71    /// Computes the principle natural logarithm.
72    pub fn ln(self) -> Self {
73        self.to_polar().ln()
74    }
75
76    /// Computes the principle logarithm in base 2.
77    pub fn log2(self) -> Self {
78        self.ln() / FT::LN_2()
79    }
80
81    /// Computes the principle logarithm in base 10.
82    pub fn log10(self) -> Self {
83        self.ln() / FT::LN_10()
84    }
85
86    /// Raises `self` to an integer power.
87    pub fn powi(self, n: i32) -> Polar<FT> {
88        self.to_polar().powi(n)
89    }
90
91    /// Raises `self` to a floating point power.
92    pub fn powf(self, x: FT) -> Polar<FT> {
93        self.to_polar().powf(x)
94    }
95
96    /// Computes the principle square root.
97    pub fn sqrt(self) -> Self {
98        let two = FT::ONE + FT::ONE;
99        let abs = self.abs();
100        Self::new(
101            ((abs + self.re) / two).sqrt(),
102            ((abs - self.re) / two).sqrt().copysign(self.im),
103        )
104    }
105
106    /// Computes the euclidian distance between two points.
107    pub fn distance(self, other: Self) -> FT {
108        (self - other).abs()
109    }
110
111    /// Computes the squared euclidian distance between two points.
112    pub fn distance_squared(self, other: Self) -> FT {
113        (self - other).abs_sq()
114    }
115
116    /// Computes the linear interpolation between two points based on the value `t`.
117    pub fn lerp(self, other: Self, t: FT) -> Self {
118        self + (other - self) * t
119    }
120}
121
122impl<FT: Number> Add for Complex<FT> {
123    type Output = Self;
124    fn add(self, other: Self) -> Self::Output {
125        Complex::new(self.re + other.re, self.im + other.im)
126    }
127}
128
129impl<FT: Number> Add<FT> for Complex<FT> {
130    type Output = Self;
131    fn add(self, re: FT) -> Self::Output {
132        Complex::new(self.re + re, self.im)
133    }
134}
135
136impl<FT: Number> AddAssign for Complex<FT> {
137    fn add_assign(&mut self, other: Self) {
138        self.re += other.re;
139        self.im += other.im;
140    }
141}
142
143impl<FT: Number> AddAssign<FT> for Complex<FT> {
144    fn add_assign(&mut self, re: FT) {
145        self.re += re;
146    }
147}
148
149impl<FT: Number> Sub for Complex<FT> {
150    type Output = Self;
151    fn sub(self, other: Self) -> Self::Output {
152        Complex::new(self.re - other.re, self.im - other.im)
153    }
154}
155
156impl<FT: Number> Sub<FT> for Complex<FT> {
157    type Output = Self;
158    fn sub(self, re: FT) -> Self::Output {
159        Complex::new(self.re - re, self.im)
160    }
161}
162
163impl<FT: Number> SubAssign for Complex<FT> {
164    fn sub_assign(&mut self, other: Self) {
165        self.re -= other.re;
166        self.im -= other.im;
167    }
168}
169
170impl<FT: Number> SubAssign<FT> for Complex<FT> {
171    fn sub_assign(&mut self, re: FT) {
172        self.re -= re;
173    }
174}
175
176impl<FT: Number> Mul for Complex<FT> {
177    type Output = Self;
178    fn mul(mut self, other: Self) -> Self {
179        self *= other;
180        self
181    }
182}
183
184impl<FT: Number> Mul<FT> for Complex<FT> {
185    type Output = Self;
186    fn mul(self, re: FT) -> Self {
187        Complex::new(self.re * re, self.im * re)
188    }
189}
190
191impl<FT: Number> MulAssign for Complex<FT> {
192    fn mul_assign(&mut self, other: Self) {
193        let re = self.re * other.re - self.im * other.im;
194        self.im = self.re * other.im + self.im * other.re;
195        self.re = re;
196    }
197}
198
199impl<FT: Number> MulAssign<FT> for Complex<FT> {
200    fn mul_assign(&mut self, re: FT) {
201        self.re *= re;
202        self.im *= re;
203    }
204}
205
206impl<FT: Number> Div for Complex<FT> {
207    type Output = Self;
208    fn div(self, other: Self) -> Self::Output {
209        self * other.recip()
210    }
211}
212
213impl<FT: Number> Div<FT> for Complex<FT> {
214    type Output = Self;
215    fn div(self, re: FT) -> Self::Output {
216        Complex::new(self.re / re, self.im / re)
217    }
218}
219
220impl<FT: Number> DivAssign for Complex<FT> {
221    fn div_assign(&mut self, other: Self) {
222        *self = *self / other;
223    }
224}
225
226impl<FT: Number> DivAssign<FT> for Complex<FT> {
227    fn div_assign(&mut self, re: FT) {
228        self.re /= re;
229        self.im /= re;
230    }
231}
232
233impl<FT: Number> Neg for Complex<FT> {
234    type Output = Self;
235    fn neg(self) -> Self::Output {
236        Self::new(-self.re, -self.im)
237    }
238}
239
240impl<FT: Number> From<FT> for Complex<FT> {
241    fn from(value: FT) -> Self {
242        Self::new(value, FT::ZERO)
243    }
244}
245
246#[cfg(feature = "approx")]
247use approx::{AbsDiffEq, RelativeEq, UlpsEq};
248
249#[cfg(feature = "approx")]
250impl<FT: AbsDiffEq + Copy> AbsDiffEq for Complex<FT>
251where
252    <FT as AbsDiffEq>::Epsilon: Copy,
253{
254    type Epsilon = <FT as AbsDiffEq>::Epsilon;
255    fn default_epsilon() -> Self::Epsilon {
256        FT::default_epsilon()
257    }
258    fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
259        FT::abs_diff_eq(&self.re, &other.re, epsilon)
260            && FT::abs_diff_eq(&self.im, &other.im, epsilon)
261    }
262}
263
264#[cfg(feature = "approx")]
265impl<FT: RelativeEq + Copy> RelativeEq for Complex<FT>
266where
267    <FT as AbsDiffEq>::Epsilon: Copy,
268{
269    fn default_max_relative() -> Self::Epsilon {
270        FT::default_max_relative()
271    }
272    fn relative_eq(
273        &self,
274        other: &Self,
275        epsilon: Self::Epsilon,
276        max_relative: Self::Epsilon,
277    ) -> bool {
278        FT::relative_eq(&self.re, &other.re, epsilon, max_relative)
279            && FT::relative_eq(&self.im, &other.im, epsilon, max_relative)
280    }
281}
282
283#[cfg(feature = "approx")]
284impl<FT: UlpsEq + Copy> UlpsEq for Complex<FT>
285where
286    <FT as AbsDiffEq>::Epsilon: Copy,
287{
288    fn default_max_ulps() -> u32 {
289        FT::default_max_ulps()
290    }
291    fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
292        FT::ulps_eq(&self.re, &other.re, epsilon, max_ulps)
293            && FT::ulps_eq(&self.im, &other.im, epsilon, max_ulps)
294    }
295}