abels_complex/complex/
rectangular.rs1use core::ops::*;
2pub type Complex32 = Complex<f32>;
3pub type Complex64 = Complex<f64>;
4use crate::traits::Number;
5
6use super::ComplexPolar as Polar;
7
8#[inline(always)]
10#[must_use]
11pub const fn complex<FT>(re: FT, im: FT) -> Complex<FT> {
12 Complex::new(re, im)
13}
14
15#[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 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 pub fn conjugate(self) -> Self {
36 Self::new(self.re, -self.im)
37 }
38
39 pub fn abs(self) -> FT {
41 self.abs_sq().sqrt()
42 }
43
44 pub fn abs_sq(self) -> FT {
48 self.re * self.re + self.im * self.im
49 }
50
51 pub fn arg(self) -> FT {
53 self.im.atan2(self.re)
54 }
55
56 pub fn recip(self) -> Self {
58 self.conjugate() / self.abs_sq()
59 }
60
61 pub fn to_polar(self) -> Polar<FT> {
63 Polar::new(self.abs(), self.arg())
64 }
65
66 pub fn exp(self) -> Polar<FT> {
68 Polar::new(self.re.exp(), self.im)
69 }
70
71 pub fn ln(self) -> Self {
73 self.to_polar().ln()
74 }
75
76 pub fn log2(self) -> Self {
78 self.ln() / FT::LN_2()
79 }
80
81 pub fn log10(self) -> Self {
83 self.ln() / FT::LN_10()
84 }
85
86 pub fn powi(self, n: i32) -> Polar<FT> {
88 self.to_polar().powi(n)
89 }
90
91 pub fn powf(self, x: FT) -> Polar<FT> {
93 self.to_polar().powf(x)
94 }
95
96 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 pub fn distance(self, other: Self) -> FT {
108 (self - other).abs()
109 }
110
111 pub fn distance_squared(self, other: Self) -> FT {
113 (self - other).abs_sq()
114 }
115
116 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}