1use crate::complex_native::c32conj_impl::c32conj;
2use faer_entity::*;
3#[cfg(not(feature = "std"))]
4use num_traits::float::FloatCore;
5
6use num_traits::{One, Zero};
7use pulp::{cast, Simd};
8
9#[cfg(feature = "std")]
10use num_complex::ComplexFloat;
11
12#[cfg(feature = "std")]
13macro_rules! impl_from_num_complex {
14 ($( $method:ident ( self $( , $arg:ident : $ty:ty )* ) -> $ret:ty ; )*) => {
15 $(
16 #[inline(always)]
17 #[allow(missing_docs)]
18 pub fn $method(self $( , $arg : $ty )* ) -> $ret {
19 self.to_num_complex().$method( $( $arg , )* ).into()
20 }
21 )*
22 };
23}
24
25#[allow(non_camel_case_types)]
27#[derive(Copy, Clone, PartialEq)]
28#[repr(C)]
29pub struct c32 {
30 pub re: f32,
32 pub im: f32,
34}
35
36impl c32 {
37 #[inline(always)]
39 pub fn new(re: f32, im: f32) -> Self {
40 Self { re, im }
41 }
42
43 #[inline(always)]
45 pub fn i() -> Self {
46 Self::new(0.0, 1.0)
47 }
48
49 #[cfg(feature = "std")]
51 #[inline(always)]
52 pub fn cis(phase: f32) -> Self {
53 Self::new(phase.cos(), phase.sin())
54 }
55
56 #[cfg(feature = "std")]
58 #[inline(always)]
59 pub fn from_polar(r: f32, theta: f32) -> Self {
60 Self::new(r * theta.cos(), r * theta.sin())
61 }
62
63 #[inline(always)]
65 pub fn to_num_complex(self) -> num_complex::Complex<f32> {
66 self.into()
67 }
68
69 #[inline(always)]
71 pub fn re(self) -> f32 {
72 self.re
73 }
74
75 #[inline(always)]
77 pub fn im(self) -> f32 {
78 self.im
79 }
80
81 #[inline(always)]
83 pub fn conj(self) -> Self {
84 self.faer_conj()
85 }
86
87 #[cfg(feature = "std")]
88 impl_from_num_complex!(
89 is_nan(self) -> bool;
90 is_infinite(self) -> bool;
91 is_finite(self) -> bool;
92 is_normal(self) -> bool;
93 recip(self) -> Self;
94 powi(self, exp: i32) -> Self;
95 powu(self, exp: u32) -> Self;
96 powf(self, exp: f32) -> Self;
97 powc(self, exp: num_complex::Complex<f32>) -> Self;
98 sqrt(self) -> Self;
99 exp(self) -> Self;
100 exp2(self) -> Self;
101 expf(self, base: f32) -> Self;
102 ln(self) -> Self;
103 log(self, base: f32) -> Self;
104 log2(self) -> Self;
105 log10(self) -> Self;
106 cbrt(self) -> Self;
107 sin(self) -> Self;
108 cos(self) -> Self;
109 tan(self) -> Self;
110 asin(self) -> Self;
111 acos(self) -> Self;
112 atan(self) -> Self;
113 sinh(self) -> Self;
114 cosh(self) -> Self;
115 tanh(self) -> Self;
116 asinh(self) -> Self;
117 acosh(self) -> Self;
118 atanh(self) -> Self;
119 abs(self) -> f32;
120 arg(self) -> f32;
121 );
122
123 #[inline(always)]
125 pub fn norm(&self) -> f32 {
126 self.faer_abs()
127 }
128
129 #[inline(always)]
131 pub fn l1_norm(&self) -> f32 {
132 self.re.faer_abs() + self.im.faer_abs()
133 }
134
135 #[inline(always)]
137 pub fn norm_sqr(&self) -> f32 {
138 self.faer_abs2()
139 }
140
141 #[inline(always)]
143 pub fn inv(&self) -> Self {
144 let norm_sqr = self.faer_abs2();
145 Self::new(self.re / norm_sqr, -self.im / norm_sqr)
146 }
147}
148
149impl Zero for c32 {
150 #[inline(always)]
151 fn zero() -> Self {
152 Self::new(0.0, 0.0)
153 }
154
155 #[inline(always)]
156 fn is_zero(&self) -> bool {
157 self.re.is_zero() && self.im.is_zero()
158 }
159
160 #[inline(always)]
161 fn set_zero(&mut self) {
162 self.re.set_zero();
163 self.im.set_zero();
164 }
165}
166
167impl One for c32 {
168 #[inline(always)]
169 fn one() -> Self {
170 Self::new(1.0, 0.0)
171 }
172
173 #[inline(always)]
174 fn is_one(&self) -> bool {
175 self.re.is_one() && self.im.is_zero()
176 }
177
178 #[inline(always)]
179 fn set_one(&mut self) {
180 self.re.set_one();
181 self.im.set_zero();
182 }
183}
184
185impl core::ops::Neg for c32 {
186 type Output = c32;
187
188 #[inline(always)]
189 fn neg(self) -> Self::Output {
190 Self::new(-self.re, -self.im)
191 }
192}
193
194impl core::ops::Add<f32> for c32 {
195 type Output = c32;
196
197 #[inline(always)]
198 fn add(self, rhs: f32) -> Self::Output {
199 Self::new(self.re + rhs, self.im)
200 }
201}
202
203impl core::ops::Add<c32> for f32 {
204 type Output = c32;
205
206 #[inline(always)]
207 fn add(self, rhs: c32) -> Self::Output {
208 Self::Output::new(self + rhs.re, rhs.im)
209 }
210}
211
212impl core::ops::Add for c32 {
213 type Output = c32;
214
215 #[inline(always)]
216 fn add(self, rhs: Self) -> Self::Output {
217 Self::new(self.re + rhs.re, self.im + rhs.im)
218 }
219}
220
221impl core::ops::Add<c32conj> for c32 {
222 type Output = c32;
223
224 #[inline(always)]
225 fn add(self, rhs: c32conj) -> Self::Output {
226 Self::new(self.re + rhs.re, self.im - rhs.neg_im)
227 }
228}
229
230impl core::ops::Add<c32> for c32conj {
231 type Output = c32;
232
233 #[inline(always)]
234 fn add(self, rhs: c32) -> Self::Output {
235 Self::Output::new(self.re + rhs.re, rhs.im - self.neg_im)
236 }
237}
238
239impl core::ops::Sub<f32> for c32 {
240 type Output = c32;
241
242 #[inline(always)]
243 fn sub(self, rhs: f32) -> Self::Output {
244 Self::new(self.re - rhs, self.im)
245 }
246}
247
248impl core::ops::Sub<c32> for f32 {
249 type Output = c32;
250
251 #[inline(always)]
252 fn sub(self, rhs: c32) -> Self::Output {
253 Self::Output::new(self - rhs.re, -rhs.im)
254 }
255}
256
257impl core::ops::Sub for c32 {
258 type Output = c32;
259
260 #[inline(always)]
261 fn sub(self, rhs: Self) -> Self::Output {
262 Self::new(self.re - rhs.re, self.im - rhs.im)
263 }
264}
265
266impl core::ops::Sub<c32conj> for c32 {
267 type Output = c32;
268
269 #[inline(always)]
270 fn sub(self, rhs: c32conj) -> Self::Output {
271 Self::new(self.re - rhs.re, self.im + rhs.neg_im)
272 }
273}
274
275impl core::ops::Sub<c32> for c32conj {
276 type Output = c32;
277
278 #[inline(always)]
279 fn sub(self, rhs: c32) -> Self::Output {
280 Self::Output::new(self.re - rhs.re, -self.neg_im - rhs.im)
281 }
282}
283
284impl core::ops::Mul<f32> for c32 {
285 type Output = c32;
286
287 #[inline(always)]
288 fn mul(self, rhs: f32) -> Self::Output {
289 Self::new(self.re * rhs, self.im * rhs)
290 }
291}
292
293impl core::ops::Mul<c32> for f32 {
294 type Output = c32;
295
296 #[inline(always)]
297 fn mul(self, rhs: c32) -> Self::Output {
298 Self::Output::new(self * rhs.re, self * rhs.im)
299 }
300}
301
302impl core::ops::Mul for c32 {
303 type Output = c32;
304
305 #[inline(always)]
306 fn mul(self, rhs: Self) -> Self::Output {
307 Self::new(
308 self.re * rhs.re - self.im * rhs.im,
309 self.re * rhs.im + self.im * rhs.re,
310 )
311 }
312}
313
314impl core::ops::Mul<c32conj> for c32 {
315 type Output = c32;
316
317 #[inline(always)]
318 fn mul(self, rhs: c32conj) -> Self::Output {
319 Self::new(
320 self.re * rhs.re + self.im * rhs.neg_im,
321 self.im * rhs.re - self.re * rhs.neg_im,
322 )
323 }
324}
325
326impl core::ops::Mul<c32> for c32conj {
327 type Output = c32;
328
329 #[inline(always)]
330 fn mul(self, rhs: c32) -> Self::Output {
331 Self::Output::new(
332 self.re * rhs.re + self.neg_im * rhs.im,
333 rhs.im * self.re - rhs.re * self.neg_im,
334 )
335 }
336}
337
338impl core::ops::Div<f32> for c32 {
339 type Output = c32;
340
341 #[inline(always)]
342 fn div(self, rhs: f32) -> Self::Output {
343 Self::new(self.re / rhs, self.im / rhs)
344 }
345}
346
347impl core::ops::Div<c32> for f32 {
348 type Output = c32;
349
350 #[allow(clippy::suspicious_arithmetic_impl)]
351 #[inline(always)]
352 fn div(self, rhs: c32) -> Self::Output {
353 self * rhs.faer_inv()
354 }
355}
356
357impl core::ops::Div for c32 {
358 type Output = c32;
359
360 #[allow(clippy::suspicious_arithmetic_impl)]
361 #[inline(always)]
362 fn div(self, rhs: Self) -> Self::Output {
363 self * rhs.faer_inv()
364 }
365}
366
367impl core::ops::Div<c32conj> for c32 {
368 type Output = c32;
369
370 #[allow(clippy::suspicious_arithmetic_impl)]
371 #[inline(always)]
372 fn div(self, rhs: c32conj) -> Self::Output {
373 self * rhs.canonicalize().faer_inv()
374 }
375}
376
377impl core::ops::Div<c32> for c32conj {
378 type Output = c32;
379
380 #[allow(clippy::suspicious_arithmetic_impl)]
381 #[inline(always)]
382 fn div(self, rhs: c32) -> Self::Output {
383 self * rhs.faer_inv()
384 }
385}
386
387impl core::ops::Rem<f32> for c32 {
388 type Output = c32;
389
390 #[inline(always)]
391 fn rem(self, rhs: f32) -> Self::Output {
392 Self::new(self.re % rhs, self.im % rhs)
393 }
394}
395
396impl core::ops::Rem<c32> for f32 {
397 type Output = c32;
398
399 #[inline(always)]
400 fn rem(self, rhs: c32) -> Self::Output {
401 self.rem(rhs.to_num_complex()).into()
402 }
403}
404
405impl core::ops::Rem for c32 {
406 type Output = c32;
407
408 #[inline(always)]
409 fn rem(self, rhs: Self) -> Self::Output {
410 self.to_num_complex().rem(rhs.to_num_complex()).into()
411 }
412}
413
414impl core::ops::Rem<c32conj> for c32 {
415 type Output = c32;
416
417 #[inline(always)]
418 fn rem(self, rhs: c32conj) -> Self::Output {
419 self.rem(rhs.canonicalize())
420 }
421}
422
423impl core::ops::Rem<c32> for c32conj {
424 type Output = c32;
425
426 #[inline(always)]
427 fn rem(self, rhs: c32) -> Self::Output {
428 self.canonicalize().rem(rhs)
429 }
430}
431
432impl core::ops::AddAssign<f32> for c32 {
433 #[inline(always)]
434 fn add_assign(&mut self, rhs: f32) {
435 self.re += rhs;
436 }
437}
438
439impl core::ops::AddAssign for c32 {
440 #[inline(always)]
441 fn add_assign(&mut self, rhs: c32) {
442 self.re += rhs.re;
443 self.im += rhs.im;
444 }
445}
446
447impl core::ops::AddAssign<c32conj> for c32 {
448 #[inline(always)]
449 fn add_assign(&mut self, rhs: c32conj) {
450 self.re += rhs.re;
451 self.im -= rhs.neg_im;
452 }
453}
454
455impl core::ops::SubAssign<f32> for c32 {
456 #[inline(always)]
457 fn sub_assign(&mut self, rhs: f32) {
458 self.re -= rhs;
459 }
460}
461
462impl core::ops::SubAssign for c32 {
463 #[inline(always)]
464 fn sub_assign(&mut self, rhs: c32) {
465 self.re -= rhs.re;
466 self.im -= rhs.im;
467 }
468}
469
470impl core::ops::SubAssign<c32conj> for c32 {
471 #[inline(always)]
472 fn sub_assign(&mut self, rhs: c32conj) {
473 self.re -= rhs.re;
474 self.im += rhs.neg_im;
475 }
476}
477
478impl core::ops::MulAssign<f32> for c32 {
479 #[inline(always)]
480 fn mul_assign(&mut self, rhs: f32) {
481 self.re *= rhs;
482 self.im *= rhs;
483 }
484}
485
486impl core::ops::MulAssign for c32 {
487 #[inline(always)]
488 fn mul_assign(&mut self, rhs: c32) {
489 *self = *self * rhs;
490 }
491}
492
493impl core::ops::MulAssign<c32conj> for c32 {
494 #[inline(always)]
495 fn mul_assign(&mut self, rhs: c32conj) {
496 *self = *self * rhs;
497 }
498}
499
500impl core::ops::DivAssign<f32> for c32 {
501 #[inline(always)]
502 fn div_assign(&mut self, rhs: f32) {
503 self.re /= rhs;
504 self.im /= rhs;
505 }
506}
507
508impl core::ops::DivAssign for c32 {
509 #[inline(always)]
510 fn div_assign(&mut self, rhs: c32) {
511 *self *= rhs.faer_inv();
512 }
513}
514
515impl core::ops::DivAssign<c32conj> for c32 {
516 #[inline(always)]
517 fn div_assign(&mut self, rhs: c32conj) {
518 *self *= rhs.canonicalize().faer_inv();
519 }
520}
521
522impl core::ops::RemAssign<f32> for c32 {
523 #[inline(always)]
524 fn rem_assign(&mut self, rhs: f32) {
525 self.re %= rhs;
526 self.im %= rhs;
527 }
528}
529
530impl core::ops::RemAssign for c32 {
531 #[inline(always)]
532 fn rem_assign(&mut self, rhs: c32) {
533 *self = *self % rhs;
534 }
535}
536
537impl core::ops::RemAssign<c32conj> for c32 {
538 #[inline(always)]
539 fn rem_assign(&mut self, rhs: c32conj) {
540 *self = *self % rhs;
541 }
542}
543
544impl num_traits::Inv for c32 {
545 type Output = c32;
546
547 #[inline(always)]
548 fn inv(self) -> Self::Output {
549 self.faer_inv()
550 }
551}
552
553impl num_traits::Num for c32 {
554 type FromStrRadixErr =
555 num_complex::ParseComplexError<<f32 as num_traits::Num>::FromStrRadixErr>;
556
557 #[inline(always)]
558 fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
559 let num_complex = num_complex::Complex32::from_str_radix(str, radix)?;
560 Ok(num_complex.into())
561 }
562}
563
564impl From<c32> for num_complex::Complex32 {
565 #[inline(always)]
566 fn from(value: c32) -> Self {
567 Self {
568 re: value.re,
569 im: value.im,
570 }
571 }
572}
573
574impl From<num_complex::Complex32> for c32 {
575 #[inline(always)]
576 fn from(value: num_complex::Complex32) -> Self {
577 c32 {
578 re: value.re,
579 im: value.im,
580 }
581 }
582}
583
584impl From<f32> for c32 {
585 #[inline(always)]
586 fn from(value: f32) -> Self {
587 Self::new(value, 0.0)
588 }
589}
590
591impl<'a> From<&'a f32> for c32 {
592 #[inline(always)]
593 fn from(value: &'a f32) -> Self {
594 Self::new(*value, 0.0)
595 }
596}
597
598unsafe impl bytemuck::Zeroable for c32 {}
599unsafe impl bytemuck::Pod for c32 {}
600
601impl core::fmt::Debug for c32 {
602 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
603 self.re.fmt(f)?;
604 let im_abs = self.im.faer_abs();
605 if self.im.is_sign_positive() {
606 f.write_str(" + ")?;
607 im_abs.fmt(f)?;
608 } else {
609 f.write_str(" - ")?;
610 im_abs.fmt(f)?;
611 }
612 f.write_str(" * I")
613 }
614}
615
616impl core::fmt::Display for c32 {
617 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
618 <Self as core::fmt::Debug>::fmt(self, f)
619 }
620}
621
622impl ComplexField for c32 {
623 type Real = f32;
624 type Simd = pulp::Arch;
625 type ScalarSimd = NoSimd;
626 type PortableSimd = pulp::Arch;
627
628 #[inline(always)]
629 fn faer_from_f64(value: f64) -> Self {
630 Self {
631 re: value as _,
632 im: 0.0,
633 }
634 }
635
636 #[inline(always)]
637 fn faer_add(self, rhs: Self) -> Self {
638 Self {
639 re: self.re + rhs.re,
640 im: self.im + rhs.im,
641 }
642 }
643
644 #[inline(always)]
645 fn faer_sub(self, rhs: Self) -> Self {
646 Self {
647 re: self.re - rhs.re,
648 im: self.im - rhs.im,
649 }
650 }
651
652 #[inline(always)]
653 fn faer_mul(self, rhs: Self) -> Self {
654 Self {
655 re: self.re * rhs.re - self.im * rhs.im,
656 im: self.re * rhs.im + self.im * rhs.re,
657 }
658 }
659
660 #[inline(always)]
661 fn faer_neg(self) -> Self {
662 Self {
663 re: -self.re,
664 im: -self.im,
665 }
666 }
667
668 #[inline(always)]
669 fn faer_conj(self) -> Self {
670 Self {
671 re: self.re,
672 im: -self.im,
673 }
674 }
675
676 #[inline(always)]
677 fn faer_scale_real(self, rhs: Self::Real) -> Self {
678 Self {
679 re: rhs * self.re,
680 im: rhs * self.im,
681 }
682 }
683
684 #[inline(always)]
685 fn faer_scale_power_of_two(self, rhs: Self::Real) -> Self {
686 Self {
687 re: rhs * self.re,
688 im: rhs * self.im,
689 }
690 }
691
692 #[inline(always)]
693 fn faer_score(self) -> Self::Real {
694 self.faer_abs2()
695 }
696
697 #[inline(always)]
698 fn faer_abs2(self) -> Self::Real {
699 self.re * self.re + self.im * self.im
700 }
701
702 #[inline(always)]
703 fn faer_nan() -> Self {
704 Self {
705 re: Self::Real::NAN,
706 im: Self::Real::NAN,
707 }
708 }
709
710 #[inline(always)]
711 fn faer_from_real(real: Self::Real) -> Self {
712 Self { re: real, im: 0.0 }
713 }
714
715 #[inline(always)]
716 fn faer_real(self) -> Self::Real {
717 self.re
718 }
719
720 #[inline(always)]
721 fn faer_imag(self) -> Self::Real {
722 self.im
723 }
724
725 #[inline(always)]
726 fn faer_zero() -> Self {
727 Self { re: 0.0, im: 0.0 }
728 }
729
730 #[inline(always)]
731 fn faer_one() -> Self {
732 Self { re: 1.0, im: 0.0 }
733 }
734
735 #[inline(always)]
736 fn faer_inv(self) -> Self {
737 self.to_num_complex().faer_inv().into()
738 }
739
740 #[inline(always)]
741 fn faer_sqrt(self) -> Self {
742 self.to_num_complex().faer_sqrt().into()
743 }
744
745 #[inline(always)]
746 fn faer_abs(self) -> Self::Real {
747 self.to_num_complex().faer_abs()
748 }
749
750 #[inline(always)]
751 fn faer_slice_as_simd<S: Simd>(slice: &[Self::Unit]) -> (&[Self::SimdUnit<S>], &[Self::Unit]) {
752 let (head, tail) = S::c32s_as_simd(bytemuck::cast_slice(slice));
753 (bytemuck::cast_slice(head), bytemuck::cast_slice(tail))
754 }
755
756 #[inline(always)]
757 fn faer_slice_as_simd_mut<S: Simd>(
758 slice: &mut [Self::Unit],
759 ) -> (&mut [Self::SimdUnit<S>], &mut [Self::Unit]) {
760 let (head, tail) = S::c32s_as_mut_simd(bytemuck::cast_slice_mut(slice));
761 (
762 bytemuck::cast_slice_mut(head),
763 bytemuck::cast_slice_mut(tail),
764 )
765 }
766
767 #[inline(always)]
768 fn faer_partial_load_last_unit<S: Simd>(simd: S, slice: &[Self::Unit]) -> Self::SimdUnit<S> {
769 simd.c32s_partial_load_last(bytemuck::cast_slice(slice))
770 }
771
772 #[inline(always)]
773 fn faer_partial_store_last_unit<S: Simd>(
774 simd: S,
775 slice: &mut [Self::Unit],
776 values: Self::SimdUnit<S>,
777 ) {
778 simd.c32s_partial_store_last(bytemuck::cast_slice_mut(slice), values)
779 }
780
781 #[inline(always)]
782 fn faer_partial_load_unit<S: Simd>(simd: S, slice: &[Self::Unit]) -> Self::SimdUnit<S> {
783 simd.c32s_partial_load(bytemuck::cast_slice(slice))
784 }
785
786 #[inline(always)]
787 fn faer_partial_store_unit<S: Simd>(
788 simd: S,
789 slice: &mut [Self::Unit],
790 values: Self::SimdUnit<S>,
791 ) {
792 simd.c32s_partial_store(bytemuck::cast_slice_mut(slice), values)
793 }
794
795 #[inline(always)]
796 fn faer_simd_splat_unit<S: Simd>(simd: S, unit: Self::Unit) -> Self::SimdUnit<S> {
797 simd.c32s_splat(pulp::cast(unit))
798 }
799
800 #[inline(always)]
801 fn faer_simd_neg<S: Simd>(simd: S, values: SimdGroupFor<Self, S>) -> SimdGroupFor<Self, S> {
802 simd.c32s_neg(values)
803 }
804
805 #[inline(always)]
806 fn faer_simd_conj<S: Simd>(simd: S, values: SimdGroupFor<Self, S>) -> SimdGroupFor<Self, S> {
807 let _ = simd;
808 values
809 }
810
811 #[inline(always)]
812 fn faer_simd_add<S: Simd>(
813 simd: S,
814 lhs: SimdGroupFor<Self, S>,
815 rhs: SimdGroupFor<Self, S>,
816 ) -> SimdGroupFor<Self, S> {
817 simd.c32s_add(lhs, rhs)
818 }
819
820 #[inline(always)]
821 fn faer_simd_sub<S: Simd>(
822 simd: S,
823 lhs: SimdGroupFor<Self, S>,
824 rhs: SimdGroupFor<Self, S>,
825 ) -> SimdGroupFor<Self, S> {
826 simd.c32s_sub(lhs, rhs)
827 }
828
829 #[inline(always)]
830 fn faer_simd_mul<S: Simd>(
831 simd: S,
832 lhs: SimdGroupFor<Self, S>,
833 rhs: SimdGroupFor<Self, S>,
834 ) -> SimdGroupFor<Self, S> {
835 simd.c32s_mul(lhs, rhs)
836 }
837 #[inline(always)]
838 fn faer_simd_scale_real<S: Simd>(
839 simd: S,
840 lhs: SimdGroupFor<Self::Real, S>,
841 rhs: SimdGroupFor<Self, S>,
842 ) -> SimdGroupFor<Self, S> {
843 if coe::is_same::<pulp::Scalar, S>() {
844 let lhs: f32 = bytemuck::cast(lhs);
845 let rhs: num_complex::Complex32 = bytemuck::cast(rhs);
846 bytemuck::cast(lhs * rhs)
847 } else {
848 bytemuck::cast(simd.f32s_mul(lhs, bytemuck::cast(rhs)))
849 }
850 }
851 #[inline(always)]
852 fn faer_simd_conj_mul<S: Simd>(
853 simd: S,
854 lhs: SimdGroupFor<Self, S>,
855 rhs: SimdGroupFor<Self, S>,
856 ) -> SimdGroupFor<Self, S> {
857 simd.c32s_conj_mul(lhs, rhs)
858 }
859
860 #[inline(always)]
861 fn faer_simd_mul_adde<S: Simd>(
862 simd: S,
863 lhs: SimdGroupFor<Self, S>,
864 rhs: SimdGroupFor<Self, S>,
865 acc: SimdGroupFor<Self, S>,
866 ) -> SimdGroupFor<Self, S> {
867 simd.c32s_mul_add_e(lhs, rhs, acc)
868 }
869
870 #[inline(always)]
871 fn faer_simd_conj_mul_adde<S: Simd>(
872 simd: S,
873 lhs: SimdGroupFor<Self, S>,
874 rhs: SimdGroupFor<Self, S>,
875 acc: SimdGroupFor<Self, S>,
876 ) -> SimdGroupFor<Self, S> {
877 simd.c32s_conj_mul_add_e(lhs, rhs, acc)
878 }
879
880 #[inline(always)]
881 fn faer_simd_reduce_add<S: Simd>(simd: S, values: SimdGroupFor<Self, S>) -> Self {
882 pulp::cast(simd.c32s_reduce_sum(values))
883 }
884
885 #[inline(always)]
886 fn faer_simd_abs2_adde<S: Simd>(
887 simd: S,
888 values: SimdGroupFor<Self, S>,
889 acc: SimdGroupFor<Self::Real, S>,
890 ) -> SimdGroupFor<Self::Real, S> {
891 let _ = (simd, values, acc);
892 unimplemented!("c32/c64 require special treatment when converted to their real counterparts in simd kernels");
893 }
894 #[inline(always)]
895 fn faer_simd_abs2<S: Simd>(
896 simd: S,
897 values: SimdGroupFor<Self, S>,
898 ) -> SimdGroupFor<Self::Real, S> {
899 let _ = (simd, values);
900 unimplemented!("c32/c64 require special treatment when converted to their real counterparts in simd kernels");
901 }
902 #[inline(always)]
903 fn faer_simd_score<S: Simd>(
904 simd: S,
905 values: SimdGroupFor<Self, S>,
906 ) -> SimdGroupFor<Self::Real, S> {
907 let _ = (simd, values);
908 unimplemented!("c32/c64 require special treatment when converted to their real counterparts in simd kernels");
909 }
910
911 #[inline(always)]
912 fn faer_simd_scalar_mul<S: Simd>(simd: S, lhs: Self, rhs: Self) -> Self {
913 cast(simd.c32_scalar_mul(cast(lhs), cast(rhs)))
914 }
915 #[inline(always)]
916 fn faer_simd_scalar_conj_mul<S: Simd>(simd: S, lhs: Self, rhs: Self) -> Self {
917 cast(simd.c32_scalar_conj_mul(cast(lhs), cast(rhs)))
918 }
919 #[inline(always)]
920 fn faer_simd_scalar_mul_adde<S: Simd>(simd: S, lhs: Self, rhs: Self, acc: Self) -> Self {
921 cast(simd.c32_scalar_mul_add_e(cast(lhs), cast(rhs), cast(acc)))
922 }
923 #[inline(always)]
924 fn faer_simd_scalar_conj_mul_adde<S: Simd>(simd: S, lhs: Self, rhs: Self, acc: Self) -> Self {
925 cast(simd.c32_scalar_conj_mul_add_e(cast(lhs), cast(rhs), cast(acc)))
926 }
927
928 #[inline(always)]
929 fn faer_align_offset<S: Simd>(
930 simd: S,
931 ptr: *const UnitFor<Self>,
932 len: usize,
933 ) -> pulp::Offset<SimdMaskFor<Self, S>> {
934 simd.c32s_align_offset(ptr as _, len)
935 }
936
937 #[inline(always)]
938 fn faer_slice_as_aligned_simd<S: Simd>(
939 simd: S,
940 slice: &[UnitFor<Self>],
941 offset: pulp::Offset<SimdMaskFor<Self, S>>,
942 ) -> (
943 Self::PrefixUnit<'_, S>,
944 &[SimdUnitFor<Self, S>],
945 Self::SuffixUnit<'_, S>,
946 ) {
947 simd.c32s_as_aligned_simd(bytemuck::cast_slice(slice), offset)
948 }
949
950 #[inline(always)]
951 fn faer_slice_as_aligned_simd_mut<S: Simd>(
952 simd: S,
953 slice: &mut [UnitFor<Self>],
954 offset: pulp::Offset<SimdMaskFor<Self, S>>,
955 ) -> (
956 Self::PrefixMutUnit<'_, S>,
957 &mut [SimdUnitFor<Self, S>],
958 Self::SuffixMutUnit<'_, S>,
959 ) {
960 simd.c32s_as_aligned_mut_simd(bytemuck::cast_slice_mut(slice), offset)
961 }
962
963 #[inline(always)]
964 fn faer_simd_rotate_left<S: Simd>(
965 simd: S,
966 values: SimdGroupFor<Self, S>,
967 amount: usize,
968 ) -> SimdGroupFor<Self, S> {
969 simd.c32s_rotate_left(values, amount)
970 }
971}
972
973unsafe impl Entity for c32 {
974 type Unit = Self;
975 type Index = u32;
976 type SimdUnit<S: Simd> = S::c32s;
977 type SimdMask<S: Simd> = S::m32s;
978 type SimdIndex<S: Simd> = S::u32s;
979 type Group = IdentityGroup;
980 type Iter<I: Iterator> = I;
981
982 type PrefixUnit<'a, S: Simd> = pulp::Prefix<'a, num_complex::Complex32, S, S::m32s>;
983 type SuffixUnit<'a, S: Simd> = pulp::Suffix<'a, num_complex::Complex32, S, S::m32s>;
984 type PrefixMutUnit<'a, S: Simd> = pulp::PrefixMut<'a, num_complex::Complex32, S, S::m32s>;
985 type SuffixMutUnit<'a, S: Simd> = pulp::SuffixMut<'a, num_complex::Complex32, S, S::m32s>;
986
987 const N_COMPONENTS: usize = 1;
988 const UNIT: GroupCopyFor<Self, ()> = ();
989
990 #[inline(always)]
991 fn faer_first<T>(group: GroupFor<Self, T>) -> T {
992 group
993 }
994
995 #[inline(always)]
996 fn faer_from_units(group: GroupFor<Self, Self::Unit>) -> Self {
997 group
998 }
999
1000 #[inline(always)]
1001 fn faer_into_units(self) -> GroupFor<Self, Self::Unit> {
1002 self
1003 }
1004
1005 #[inline(always)]
1006 fn faer_as_ref<T>(group: &GroupFor<Self, T>) -> GroupFor<Self, &T> {
1007 group
1008 }
1009
1010 #[inline(always)]
1011 fn faer_as_mut<T>(group: &mut GroupFor<Self, T>) -> GroupFor<Self, &mut T> {
1012 group
1013 }
1014
1015 #[inline(always)]
1016 fn faer_as_ptr<T>(group: *mut GroupFor<Self, T>) -> GroupFor<Self, *mut T> {
1017 group
1018 }
1019
1020 #[inline(always)]
1021 fn faer_map_impl<T, U>(
1022 group: GroupFor<Self, T>,
1023 f: &mut impl FnMut(T) -> U,
1024 ) -> GroupFor<Self, U> {
1025 (*f)(group)
1026 }
1027
1028 #[inline(always)]
1029 fn faer_map_with_context<Ctx, T, U>(
1030 ctx: Ctx,
1031 group: GroupFor<Self, T>,
1032 f: &mut impl FnMut(Ctx, T) -> (Ctx, U),
1033 ) -> (Ctx, GroupFor<Self, U>) {
1034 (*f)(ctx, group)
1035 }
1036
1037 #[inline(always)]
1038 fn faer_zip<T, U>(
1039 first: GroupFor<Self, T>,
1040 second: GroupFor<Self, U>,
1041 ) -> GroupFor<Self, (T, U)> {
1042 (first, second)
1043 }
1044 #[inline(always)]
1045 fn faer_unzip<T, U>(zipped: GroupFor<Self, (T, U)>) -> (GroupFor<Self, T>, GroupFor<Self, U>) {
1046 zipped
1047 }
1048
1049 #[inline(always)]
1050 fn faer_into_iter<I: IntoIterator>(iter: GroupFor<Self, I>) -> Self::Iter<I::IntoIter> {
1051 iter.into_iter()
1052 }
1053}
1054
1055unsafe impl Conjugate for c32 {
1056 type Conj = c32conj;
1057 type Canonical = c32;
1058
1059 #[inline(always)]
1060 fn canonicalize(self) -> Self::Canonical {
1061 self
1062 }
1063}