Skip to main content

simba/simd/
simd_complex.rs

1use num::{NumAssignOps, NumOps, Zero};
2use std::any::Any;
3use std::f64;
4use std::fmt::Debug;
5use std::ops::Neg;
6
7use crate::scalar::{ComplexField, Field, SubsetOf, SupersetOf};
8use crate::simd::{SimdRealField, SimdValue};
9
10/// Lane-wise generalisation of `ComplexField` for SIMD complex fields.
11///
12/// Each lane of an SIMD complex field should contain one complex field.
13#[allow(missing_docs)]
14pub trait SimdComplexField:
15SubsetOf<Self>
16+ SupersetOf<f32>
17+ SupersetOf<f64>
18+ Field
19+ Clone
20+ Neg<Output=Self>
21//    + MeetSemilattice
22//    + JoinSemilattice
23+ Send
24+ Sync
25+ Any
26+ 'static
27+ Debug
28+ NumAssignOps
29+ NumOps
30+ PartialEq
31{
32    /// Type of the coefficients of a complex number.
33    type SimdRealField: SimdRealField<SimdBool=<Self as SimdValue>::SimdBool>;
34    /// Builds a pure-real complex number from the given value.
35    fn from_simd_real(re: Self::SimdRealField) -> Self;
36
37    /// The real part of this complex number.
38    fn simd_real(self) -> Self::SimdRealField;
39
40    /// The imaginary part of this complex number.
41    fn simd_imaginary(self) -> Self::SimdRealField;
42
43    /// The modulus of this complex number.
44    fn simd_modulus(self) -> Self::SimdRealField;
45
46    /// The squared modulus of this complex number.
47    fn simd_modulus_squared(self) -> Self::SimdRealField;
48
49    /// The argument of this complex number.
50    fn simd_argument(self) -> Self::SimdRealField;
51
52    /// The sum of the absolute value of this complex number's real and imaginary part.
53    fn simd_norm1(self) -> Self::SimdRealField;
54
55    /// Multiplies this complex number by `factor`.
56    fn simd_scale(self, factor: Self::SimdRealField) -> Self;
57
58    /// Divides this complex number by `factor`.
59    fn simd_unscale(self, factor: Self::SimdRealField) -> Self;
60
61    /// The polar form of this complex number: (modulus, arg)
62    fn simd_to_polar(self) -> (Self::SimdRealField, Self::SimdRealField) {
63        (self.clone().simd_modulus(), self.simd_argument())
64    }
65
66    /// The exponential form of this complex number: (modulus, e^{i arg})
67    fn simd_to_exp(self) -> (Self::SimdRealField, Self) {
68        let m = self.clone().simd_modulus();
69
70        if !m.is_zero() {
71            (m.clone(), self.simd_unscale(m))
72        } else {
73            (Self::SimdRealField::zero(), Self::one())
74        }
75    }
76
77    /// The exponential part of this complex number: `self / self.modulus()`
78    fn simd_signum(self) -> Self {
79        self.simd_to_exp().1
80    }
81
82    fn simd_floor(self) -> Self;
83    fn simd_ceil(self) -> Self;
84    fn simd_round(self) -> Self;
85    fn simd_trunc(self) -> Self;
86    fn simd_fract(self) -> Self;
87    fn simd_mul_add(self, a: Self, b: Self) -> Self;
88
89    /// The absolute value of this complex number: `self / self.signum()`.
90    ///
91    /// This is equivalent to `self.modulus()`.
92    fn simd_abs(self) -> Self::SimdRealField;
93
94    /// Computes (self.conjugate() * self + other.conjugate() * other).sqrt()
95    fn simd_hypot(self, other: Self) -> Self::SimdRealField;
96
97    fn simd_recip(self) -> Self;
98    fn simd_conjugate(self) -> Self;
99    fn simd_sin(self) -> Self;
100    fn simd_cos(self) -> Self;
101    fn simd_sin_cos(self) -> (Self, Self);
102    #[inline]
103    fn simd_sinh_cosh(self) -> (Self, Self) {
104        (self.clone().simd_sinh(), self.simd_cosh())
105    }
106    fn simd_tan(self) -> Self;
107    fn simd_asin(self) -> Self;
108    fn simd_acos(self) -> Self;
109    fn simd_atan(self) -> Self;
110    fn simd_sinh(self) -> Self;
111    fn simd_cosh(self) -> Self;
112    fn simd_tanh(self) -> Self;
113    fn simd_asinh(self) -> Self;
114    fn simd_acosh(self) -> Self;
115    fn simd_atanh(self) -> Self;
116
117    /// Cardinal sine
118    #[inline]
119    fn simd_sinc(self) -> Self {
120        if self.is_zero() {
121            Self::one()
122        } else {
123            self.clone().simd_sin() / self
124        }
125    }
126
127    #[inline]
128    fn simd_sinhc(self) -> Self {
129        if self.is_zero() {
130            Self::one()
131        } else {
132            self.clone().simd_sinh() / self
133        }
134    }
135
136    /// Cardinal cos
137    #[inline]
138    fn simd_cosc(self) -> Self {
139        if self.is_zero() {
140            Self::one()
141        } else {
142            self.clone().simd_cos() / self
143        }
144    }
145
146    #[inline]
147    fn simd_coshc(self) -> Self {
148        if self.is_zero() {
149            Self::one()
150        } else {
151            self.clone().simd_cosh() / self
152        }
153    }
154
155    fn simd_log(self, base: Self::SimdRealField) -> Self;
156    fn simd_log2(self) -> Self;
157    fn simd_log10(self) -> Self;
158    fn simd_ln(self) -> Self;
159    fn simd_ln_1p(self) -> Self;
160    fn simd_sqrt(self) -> Self;
161    fn simd_exp(self) -> Self;
162    fn simd_exp2(self) -> Self;
163    fn simd_exp_m1(self) -> Self;
164    fn simd_powi(self, n: i32) -> Self;
165    fn simd_powf(self, n: Self::SimdRealField) -> Self;
166    fn simd_powc(self, n: Self) -> Self;
167    fn simd_cbrt(self) -> Self;
168
169    /// Computes the sum of all the lanes of `self`.
170    fn simd_horizontal_sum(self) -> Self::Element;
171
172    /// Computes the product of all the lanes of `self`.
173    fn simd_horizontal_product(self) -> Self::Element;
174}
175
176// Blanket impl: ComplexField => SimdComplexField
177impl<T: ComplexField> SimdComplexField for T {
178    type SimdRealField = T::RealField;
179
180    #[inline(always)]
181    fn from_simd_real(re: Self::SimdRealField) -> Self {
182        Self::from_real(re)
183    }
184    #[inline(always)]
185    fn simd_real(self) -> Self::SimdRealField {
186        self.real()
187    }
188    #[inline(always)]
189    fn simd_imaginary(self) -> Self::SimdRealField {
190        self.imaginary()
191    }
192    #[inline(always)]
193    fn simd_modulus(self) -> Self::SimdRealField {
194        self.modulus()
195    }
196    #[inline(always)]
197    fn simd_modulus_squared(self) -> Self::SimdRealField {
198        self.modulus_squared()
199    }
200    #[inline(always)]
201    fn simd_argument(self) -> Self::SimdRealField {
202        self.argument()
203    }
204    #[inline(always)]
205    fn simd_norm1(self) -> Self::SimdRealField {
206        self.norm1()
207    }
208    #[inline(always)]
209    fn simd_scale(self, factor: Self::SimdRealField) -> Self {
210        self.scale(factor)
211    }
212    #[inline(always)]
213    fn simd_unscale(self, factor: Self::SimdRealField) -> Self {
214        self.unscale(factor)
215    }
216    #[inline(always)]
217    fn simd_to_polar(self) -> (Self::SimdRealField, Self::SimdRealField) {
218        self.to_polar()
219    }
220    #[inline(always)]
221    fn simd_to_exp(self) -> (Self::SimdRealField, Self) {
222        self.to_exp()
223    }
224    #[inline(always)]
225    fn simd_signum(self) -> Self {
226        self.signum()
227    }
228
229    #[inline(always)]
230    fn simd_floor(self) -> Self {
231        self.floor()
232    }
233    #[inline(always)]
234    fn simd_ceil(self) -> Self {
235        self.ceil()
236    }
237    #[inline(always)]
238    fn simd_round(self) -> Self {
239        self.round()
240    }
241    #[inline(always)]
242    fn simd_trunc(self) -> Self {
243        self.trunc()
244    }
245    #[inline(always)]
246    fn simd_fract(self) -> Self {
247        self.fract()
248    }
249    #[inline(always)]
250    fn simd_mul_add(self, a: Self, b: Self) -> Self {
251        self.mul_add(a, b)
252    }
253
254    #[inline(always)]
255    fn simd_abs(self) -> Self::SimdRealField {
256        self.abs()
257    }
258    #[inline(always)]
259    fn simd_hypot(self, other: Self) -> Self::SimdRealField {
260        self.hypot(other)
261    }
262
263    #[inline(always)]
264    fn simd_recip(self) -> Self {
265        self.recip()
266    }
267    #[inline(always)]
268    fn simd_conjugate(self) -> Self {
269        self.conjugate()
270    }
271    #[inline(always)]
272    fn simd_sin(self) -> Self {
273        self.sin()
274    }
275    #[inline(always)]
276    fn simd_cos(self) -> Self {
277        self.cos()
278    }
279    #[inline(always)]
280    fn simd_sin_cos(self) -> (Self, Self) {
281        self.sin_cos()
282    }
283    #[inline(always)]
284    fn simd_sinh_cosh(self) -> (Self, Self) {
285        self.sinh_cosh()
286    }
287    #[inline(always)]
288    fn simd_tan(self) -> Self {
289        self.tan()
290    }
291    #[inline(always)]
292    fn simd_asin(self) -> Self {
293        self.asin()
294    }
295    #[inline(always)]
296    fn simd_acos(self) -> Self {
297        self.acos()
298    }
299    #[inline(always)]
300    fn simd_atan(self) -> Self {
301        self.atan()
302    }
303    #[inline(always)]
304    fn simd_sinh(self) -> Self {
305        self.sinh()
306    }
307    #[inline(always)]
308    fn simd_cosh(self) -> Self {
309        self.cosh()
310    }
311    #[inline(always)]
312    fn simd_tanh(self) -> Self {
313        self.tanh()
314    }
315    #[inline(always)]
316    fn simd_asinh(self) -> Self {
317        self.asinh()
318    }
319    #[inline(always)]
320    fn simd_acosh(self) -> Self {
321        self.acosh()
322    }
323    #[inline(always)]
324    fn simd_atanh(self) -> Self {
325        self.atanh()
326    }
327
328    #[inline(always)]
329    fn simd_sinc(self) -> Self {
330        self.sinc()
331    }
332    #[inline(always)]
333    fn simd_sinhc(self) -> Self {
334        self.sinhc()
335    }
336
337    #[inline(always)]
338    fn simd_cosc(self) -> Self {
339        self.cosc()
340    }
341    #[inline(always)]
342    fn simd_coshc(self) -> Self {
343        self.coshc()
344    }
345
346    #[inline(always)]
347    fn simd_log(self, base: Self::SimdRealField) -> Self {
348        self.log(base)
349    }
350    #[inline(always)]
351    fn simd_log2(self) -> Self {
352        self.log2()
353    }
354    #[inline(always)]
355    fn simd_log10(self) -> Self {
356        self.log10()
357    }
358    #[inline(always)]
359    fn simd_ln(self) -> Self {
360        self.ln()
361    }
362    #[inline(always)]
363    fn simd_ln_1p(self) -> Self {
364        self.ln_1p()
365    }
366    #[inline(always)]
367    fn simd_sqrt(self) -> Self {
368        self.sqrt()
369    }
370    #[inline(always)]
371    fn simd_exp(self) -> Self {
372        self.exp()
373    }
374    #[inline(always)]
375    fn simd_exp2(self) -> Self {
376        self.exp2()
377    }
378    #[inline(always)]
379    fn simd_exp_m1(self) -> Self {
380        self.exp_m1()
381    }
382    #[inline(always)]
383    fn simd_powi(self, n: i32) -> Self {
384        self.powi(n)
385    }
386    #[inline(always)]
387    fn simd_powf(self, n: Self::SimdRealField) -> Self {
388        self.powf(n)
389    }
390    #[inline(always)]
391    fn simd_powc(self, n: Self) -> Self {
392        self.powc(n)
393    }
394    #[inline(always)]
395    fn simd_cbrt(self) -> Self {
396        self.cbrt()
397    }
398
399    #[inline(always)]
400    fn simd_horizontal_sum(self) -> Self::Element {
401        self
402    }
403    #[inline(always)]
404    fn simd_horizontal_product(self) -> Self::Element {
405        self
406    }
407}