1#![allow(missing_docs)]
2#![allow(non_camel_case_types)] use crate::scalar::{ComplexField, Field, RealField, SubsetOf, SupersetOf};
7use crate::simd::{
8 PrimitiveSimdValue, SimdBool, SimdComplexField, SimdPartialOrd, SimdRealField, SimdSigned,
9 SimdValue,
10};
11use approx::AbsDiffEq;
12use num::{FromPrimitive, Num, One, Zero};
13use num_traits::Bounded;
14use std::{
15 cmp::PartialEq,
16 ops::{
17 Add, AddAssign, BitAnd, BitOr, BitXor, Div, DivAssign, Mul, MulAssign, Neg, Not, Rem,
18 RemAssign, Sub, SubAssign,
19 },
20};
21
22#[cfg(feature = "rkyv")]
23macro_rules! impl_rkyv {
24 ($type:ty, $array:ty) => {
25 impl rkyv::Archive for $type {
26 type Archived = $array;
27 type Resolver = ();
28
29 #[inline]
30 unsafe fn resolve(&self, _: usize, _: Self::Resolver, out: *mut Self::Archived) {
31 out.write((*self).into_arr());
32 }
33 }
34
35 impl<S: rkyv::Fallible + ?Sized> rkyv::Serialize<S> for $type {
36 #[inline]
37 fn serialize(&self, _: &mut S) -> Result<Self::Resolver, S::Error> {
38 Ok(())
39 }
40 }
41
42 impl<D: rkyv::Fallible + ?Sized> rkyv::Deserialize<$type, D> for rkyv::Archived<$type> {
43 #[inline]
44 fn deserialize(&self, _: &mut D) -> Result<$type, D::Error> {
45 Ok(<$type>::from_arr(*self))
46 }
47 }
48 };
49}
50
51#[repr(transparent)]
55#[derive(Copy, Clone, Debug, Default)]
56pub struct WideF32x4(pub wide::f32x4);
57
58#[cfg(feature = "rkyv")]
59impl_rkyv!(WideF32x4, [f32; 4]);
60
61#[repr(transparent)]
65#[derive(Copy, Clone, Debug, Default)]
66pub struct WideBoolF32x4(pub wide::f32x4);
67
68#[cfg(feature = "rkyv")]
69impl_rkyv!(WideBoolF32x4, [f32; 4]);
70
71#[repr(transparent)]
75#[derive(Copy, Clone, Debug, Default)]
76pub struct WideF32x8(pub wide::f32x8);
77
78#[cfg(feature = "rkyv")]
79impl_rkyv!(WideF32x8, [f32; 8]);
80
81#[repr(transparent)]
85#[derive(Copy, Clone, Debug, Default)]
86pub struct WideBoolF32x8(pub wide::f32x8);
87
88#[cfg(feature = "rkyv")]
89impl_rkyv!(WideBoolF32x8, [f32; 8]);
90
91#[repr(transparent)]
95#[derive(Copy, Clone, Debug, Default)]
96pub struct WideF64x4(pub wide::f64x4);
97
98#[cfg(feature = "rkyv")]
99impl_rkyv!(WideF64x4, [f64; 4]);
100
101#[repr(transparent)]
105#[derive(Copy, Clone, Debug, Default)]
106pub struct WideBoolF64x4(pub wide::f64x4);
107
108#[cfg(feature = "rkyv")]
109impl_rkyv!(WideBoolF64x4, [f64; 4]);
110
111macro_rules! impl_wide_f32 (
112 ($f32: ident, $f32xX: ident, $WideF32xX: ident, $WideBoolF32xX: ident, $lanes: expr; $($ii: expr),+) => {
113 impl PrimitiveSimdValue for $WideF32xX {}
114 impl PrimitiveSimdValue for $WideBoolF32xX {}
115
116 impl $WideF32xX {
117 pub const ZERO: Self = $WideF32xX(<wide::$f32xX>::ZERO);
118 pub const ONE: Self = $WideF32xX(<wide::$f32xX>::ONE);
119
120 #[inline(always)]
121 pub fn into_arr(self) -> [$f32; $lanes] {
122 self.0.into()
123 }
124
125 #[inline(always)]
126 pub fn from_arr(arr: [$f32; $lanes]) -> Self {
127 Self(arr.into())
128 }
129
130 #[inline(always)]
131 pub fn map(self, f: impl Fn($f32) -> $f32) -> Self {
132 let arr = self.into_arr();
133 Self::from([f(arr[0]), $(f(arr[$ii])),+])
134 }
135
136 #[inline(always)]
137 pub fn zip_map(self, rhs: Self, f: impl Fn($f32, $f32) -> $f32) -> Self {
138 let arr = self.into_arr();
139 let rhs = rhs.into_arr();
140 Self::from([
141 f(arr[0], rhs[0]),
142 $(f(arr[$ii], rhs[$ii])),+
143 ])
144 }
145 }
146
147 impl $WideBoolF32xX {
148 #[inline(always)]
149 pub fn from_arr(arr: [$f32; $lanes]) -> Self {
150 Self(arr.into())
151 }
152
153 #[inline(always)]
154 pub fn into_arr(self) -> [$f32; $lanes] {
155 self.0.into()
156 }
157 }
158
159 impl SimdValue for $WideF32xX {
160 const LANES: usize = $lanes;
161 type Element = $f32;
162 type SimdBool = $WideBoolF32xX;
163
164 #[inline(always)]
165 fn splat(val: Self::Element) -> Self {
166 $WideF32xX(wide::$f32xX::new([val, $({ let _ = $ii; val }),+]))
169 }
170
171 #[inline(always)]
172 fn extract(&self, i: usize) -> Self::Element {
173 self.into_arr()[i]
174 }
175
176 #[inline(always)]
177 unsafe fn extract_unchecked(&self, i: usize) -> Self::Element {
178 *self.into_arr().get_unchecked(i)
179 }
180
181 #[inline(always)]
182 fn replace(&mut self, i: usize, val: Self::Element) {
183 let mut arr = self.into_arr();
184 arr[i] = val;
185 *self = Self::from(arr);
186 }
187
188 #[inline(always)]
189 unsafe fn replace_unchecked(&mut self, i: usize, val: Self::Element) {
190 let mut arr = self.into_arr();
191 *arr.get_unchecked_mut(i) = val;
192 *self = Self::from(arr);
193 }
194
195 #[inline(always)]
196 fn select(self, cond: Self::SimdBool, other: Self) -> Self {
197 $WideF32xX(cond.0.blend(self.0, other.0))
198 }
199 }
200
201 impl SimdValue for $WideBoolF32xX {
202 const LANES: usize = $lanes;
203 type Element = bool;
204 type SimdBool = Self;
205
206 #[inline(always)]
207 fn splat(val: bool) -> Self {
208 let results = [
209 $WideBoolF32xX(wide::$f32xX::ZERO),
210 $WideBoolF32xX(!wide::$f32xX::ZERO),
211 ];
212 results[val as usize]
213 }
214
215 #[inline(always)]
216 fn extract(&self, i: usize) -> Self::Element {
217 self.into_arr()[i] != 0.0
218 }
219
220 #[inline(always)]
221 unsafe fn extract_unchecked(&self, i: usize) -> Self::Element {
222 *self.into_arr().get_unchecked(i) != 0.0
223 }
224
225 #[inline(always)]
226 fn replace(&mut self, i: usize, val: Self::Element) {
227 let vals = [0.0, <$f32>::from_bits(Bounded::max_value())];
228 let mut arr = self.into_arr();
229 arr[i] = vals[val as usize];
230 *self = Self::from_arr(arr);
231 }
232
233 #[inline(always)]
234 unsafe fn replace_unchecked(&mut self, i: usize, val: Self::Element) {
235 let vals = [0.0, <$f32>::from_bits(Bounded::max_value())];
236 let mut arr = self.into_arr();
237 *arr.get_unchecked_mut(i) = vals[val as usize];
238 *self = Self::from_arr(arr);
239 }
240
241 #[inline(always)]
242 fn select(self, cond: Self::SimdBool, other: Self) -> Self {
243 $WideBoolF32xX(cond.0.blend(self.0, other.0))
244 }
245 }
246
247 impl PartialEq for $WideF32xX {
248 #[inline]
249 fn eq(&self, rhs: &Self) -> bool {
250 self.0 == rhs.0
251 }
252 }
253
254 impl PartialEq for $WideBoolF32xX {
255 #[inline]
256 fn eq(&self, rhs: &Self) -> bool {
257 self.0 == rhs.0
258 }
259 }
260
261 impl Not for $WideBoolF32xX {
262 type Output = Self;
263
264 #[inline]
265 fn not(self) -> Self {
266 Self(!self.0)
267 }
268 }
269
270 impl BitXor for $WideBoolF32xX {
271 type Output = Self;
272
273 #[inline]
274 fn bitxor(self, rhs: Self) -> Self {
275 Self(self.0 ^ rhs.0)
276 }
277 }
278
279 impl BitOr for $WideBoolF32xX {
280 type Output = Self;
281
282 #[inline]
283 fn bitor(self, rhs: Self) -> Self {
284 Self(self.0 | rhs.0)
285 }
286 }
287
288 impl BitAnd for $WideBoolF32xX {
289 type Output = Self;
290
291 #[inline]
292 fn bitand(self, rhs: Self) -> Self {
293 Self(self.0 & rhs.0)
294 }
295 }
296
297 impl SimdBool for $WideBoolF32xX {
298 #[inline(always)]
299 fn bitmask(self) -> u64 {
300 let arr = self.into_arr();
301 (((arr[0] != 0.0) as u64) << 0)
302 $(| (((arr[$ii] != 0.0) as u64) << $ii))*
303 }
304
305 #[inline(always)]
306 fn and(self) -> bool {
307 let arr = self.into_arr();
308 (arr[0].to_bits() $(& arr[$ii].to_bits())*) != 0
309 }
310
311 #[inline(always)]
312 fn or(self) -> bool {
313 let arr = self.into_arr();
314 (arr[0].to_bits() $(| arr[$ii].to_bits())*) != 0
315 }
316
317 #[inline(always)]
318 fn xor(self) -> bool {
319 let arr = self.into_arr();
320 (arr[0].to_bits() $(^ arr[$ii].to_bits())*) != 0
321 }
322
323 #[inline(always)]
324 fn all(self) -> bool {
325 self.0.all()
326 }
327
328 #[inline(always)]
329 fn any(self) -> bool {
330 self.0.any()
331 }
332
333 #[inline(always)]
334 fn none(self) -> bool {
335 self.0.none()
336 }
337
338 #[inline(always)]
339 fn if_else<Res: SimdValue<SimdBool = Self>>(
340 self,
341 if_value: impl FnOnce() -> Res,
342 else_value: impl FnOnce() -> Res,
343 ) -> Res {
344 let a = if_value();
345 let b = else_value();
346 a.select(self, b)
347 }
348
349 #[inline(always)]
350 fn if_else2<Res: SimdValue<SimdBool = Self>>(
351 self,
352 if_value: impl FnOnce() -> Res,
353 else_if: (impl FnOnce() -> Self, impl FnOnce() -> Res),
354 else_value: impl FnOnce() -> Res,
355 ) -> Res {
356 let a = if_value();
357 let b = else_if.1();
358 let c = else_value();
359
360 let cond_a = self;
361 let cond_b = else_if.0();
362
363 a.select(cond_a, b.select(cond_b, c))
364 }
365
366 #[inline(always)]
367 fn if_else3<Res: SimdValue<SimdBool = Self>>(
368 self,
369 if_value: impl FnOnce() -> Res,
370 else_if: (impl FnOnce() -> Self, impl FnOnce() -> Res),
371 else_else_if: (impl FnOnce() -> Self, impl FnOnce() -> Res),
372 else_value: impl FnOnce() -> Res,
373 ) -> Res {
374 let a = if_value();
375 let b = else_if.1();
376 let c = else_else_if.1();
377 let d = else_value();
378
379 let cond_a = self;
380 let cond_b = else_if.0();
381 let cond_c = else_else_if.0();
382
383 a.select(cond_a, b.select(cond_b, c.select(cond_c, d)))
384 }
385 }
386
387 impl From<[$f32; $lanes]> for $WideF32xX {
388 #[inline(always)]
389 fn from(vals: [$f32; $lanes]) -> Self {
390 $WideF32xX(wide::$f32xX::from(vals))
391 }
392 }
393
394 impl From<$WideF32xX> for [$f32; $lanes] {
395 #[inline(always)]
396 fn from(val: $WideF32xX) -> [$f32; $lanes] {
397 val.0.into()
398 }
399 }
400
401 impl SubsetOf<$WideF32xX> for $WideF32xX {
402 #[inline(always)]
403 fn to_superset(&self) -> Self {
404 *self
405 }
406
407 #[inline(always)]
408 fn from_superset(element: &Self) -> Option<Self> {
409 Some(*element)
410 }
411
412 #[inline(always)]
413 fn from_superset_unchecked(element: &Self) -> Self {
414 *element
415 }
416
417 #[inline(always)]
418 fn is_in_subset(_: &Self) -> bool {
419 true
420 }
421 }
422
423 impl From<[bool; $lanes]> for $WideBoolF32xX {
424 #[inline(always)]
425 fn from(vals: [bool; $lanes]) -> Self {
426 let bits = [0.0, <$f32>::from_bits(Bounded::max_value())];
427 $WideBoolF32xX(wide::$f32xX::from([
428 bits[vals[0] as usize],
429 $(bits[vals[$ii] as usize]),*
430 ]))
431 }
432 }
433
434 impl SubsetOf<$WideBoolF32xX> for $WideBoolF32xX {
435 #[inline(always)]
436 fn to_superset(&self) -> Self {
437 *self
438 }
439
440 #[inline(always)]
441 fn from_superset(element: &Self) -> Option<Self> {
442 Some(*element)
443 }
444
445 #[inline(always)]
446 fn from_superset_unchecked(element: &Self) -> Self {
447 *element
448 }
449
450 #[inline(always)]
451 fn is_in_subset(_: &Self) -> bool {
452 true
453 }
454 }
455
456 impl Num for $WideF32xX {
457 type FromStrRadixErr = <$f32 as Num>::FromStrRadixErr;
458
459 #[inline(always)]
460 fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
461 <$f32>::from_str_radix(str, radix).map(Self::splat)
462 }
463 }
464
465 impl FromPrimitive for $WideF32xX {
466 #[inline(always)]
467 fn from_i64(n: i64) -> Option<Self> {
468 <$f32>::from_i64(n).map(Self::splat)
469 }
470
471 #[inline(always)]
472 fn from_u64(n: u64) -> Option<Self> {
473 <$f32>::from_u64(n).map(Self::splat)
474 }
475
476 #[inline(always)]
477 fn from_isize(n: isize) -> Option<Self> {
478 <$f32>::from_isize(n).map(Self::splat)
479 }
480
481 #[inline(always)]
482 fn from_i8(n: i8) -> Option<Self> {
483 <$f32>::from_i8(n).map(Self::splat)
484 }
485
486 #[inline(always)]
487 fn from_i16(n: i16) -> Option<Self> {
488 <$f32>::from_i16(n).map(Self::splat)
489 }
490
491 #[inline(always)]
492 fn from_i32(n: i32) -> Option<Self> {
493 <$f32>::from_i32(n).map(Self::splat)
494 }
495
496 #[inline(always)]
497 fn from_usize(n: usize) -> Option<Self> {
498 <$f32>::from_usize(n).map(Self::splat)
499 }
500
501 #[inline(always)]
502 fn from_u8(n: u8) -> Option<Self> {
503 <$f32>::from_u8(n).map(Self::splat)
504 }
505
506 #[inline(always)]
507 fn from_u16(n: u16) -> Option<Self> {
508 <$f32>::from_u16(n).map(Self::splat)
509 }
510
511 #[inline(always)]
512 fn from_u32(n: u32) -> Option<Self> {
513 <$f32>::from_u32(n).map(Self::splat)
514 }
515
516 #[inline(always)]
517 fn from_f32(n: f32) -> Option<Self> {
518 <$f32>::from_f32(n).map(Self::splat)
519 }
520
521 #[inline(always)]
522 fn from_f64(n: f64) -> Option<Self> {
523 <$f32>::from_f64(n).map(Self::splat)
524 }
525 }
526
527 impl Zero for $WideF32xX {
528 #[inline(always)]
529 fn zero() -> Self {
530 <$WideF32xX>::splat(<$f32>::zero())
531 }
532
533 #[inline(always)]
534 fn is_zero(&self) -> bool {
535 *self == Self::zero()
536 }
537 }
538
539 impl One for $WideF32xX {
540 #[inline(always)]
541 fn one() -> Self {
542 <$WideF32xX>::splat(<$f32>::one())
543 }
544 }
545
546 impl Add<$WideF32xX> for $WideF32xX {
547 type Output = Self;
548
549 #[inline(always)]
550 fn add(self, rhs: Self) -> Self {
551 Self(self.0 + rhs.0)
552 }
553 }
554
555 impl Sub<$WideF32xX> for $WideF32xX {
556 type Output = Self;
557
558 #[inline(always)]
559 fn sub(self, rhs: Self) -> Self {
560 Self(self.0 - rhs.0)
561 }
562 }
563
564 impl Mul<$WideF32xX> for $WideF32xX {
565 type Output = Self;
566
567 #[inline(always)]
568 fn mul(self, rhs: Self) -> Self {
569 Self(self.0 * rhs.0)
570 }
571 }
572
573 impl Div<$WideF32xX> for $WideF32xX {
574 type Output = Self;
575
576 #[inline(always)]
577 fn div(self, rhs: Self) -> Self {
578 Self(self.0 / rhs.0)
579 }
580 }
581
582 impl Rem<$WideF32xX> for $WideF32xX {
583 type Output = Self;
584
585 #[inline(always)]
586 fn rem(self, rhs: Self) -> Self {
587 self.zip_map(rhs, |a, b| a % b)
588 }
589 }
590
591 impl AddAssign<$WideF32xX> for $WideF32xX {
592 #[inline(always)]
593 fn add_assign(&mut self, rhs: Self) {
594 self.0 += rhs.0
595 }
596 }
597
598 impl SubAssign<$WideF32xX> for $WideF32xX {
599 #[inline(always)]
600 fn sub_assign(&mut self, rhs: Self) {
601 self.0 -= rhs.0
602 }
603 }
604
605 impl DivAssign<$WideF32xX> for $WideF32xX {
606 #[inline(always)]
607 fn div_assign(&mut self, rhs: Self) {
608 self.0 /= rhs.0
609 }
610 }
611
612 impl MulAssign<$WideF32xX> for $WideF32xX {
613 #[inline(always)]
614 fn mul_assign(&mut self, rhs: Self) {
615 self.0 *= rhs.0
616 }
617 }
618
619 impl RemAssign<$WideF32xX> for $WideF32xX {
620 #[inline(always)]
621 fn rem_assign(&mut self, rhs: Self) {
622 *self = *self % rhs;
623 }
624 }
625
626 impl SimdPartialOrd for $WideF32xX {
627 #[inline(always)]
628 fn simd_gt(self, other: Self) -> Self::SimdBool {
629 $WideBoolF32xX(self.0.simd_gt(other.0))
630 }
631
632 #[inline(always)]
633 fn simd_lt(self, other: Self) -> Self::SimdBool {
634 $WideBoolF32xX(self.0.simd_lt(other.0))
635 }
636
637 #[inline(always)]
638 fn simd_ge(self, other: Self) -> Self::SimdBool {
639 $WideBoolF32xX(self.0.simd_ge(other.0))
640 }
641
642 #[inline(always)]
643 fn simd_le(self, other: Self) -> Self::SimdBool {
644 $WideBoolF32xX(self.0.simd_le(other.0))
645 }
646
647 #[inline(always)]
648 fn simd_eq(self, other: Self) -> Self::SimdBool {
649 $WideBoolF32xX(self.0.simd_eq(other.0))
650 }
651
652 #[inline(always)]
653 fn simd_ne(self, other: Self) -> Self::SimdBool {
654 $WideBoolF32xX(self.0.simd_ne(other.0))
655 }
656
657 #[inline(always)]
658 fn simd_max(self, other: Self) -> Self {
659 $WideF32xX(self.0.max(other.0))
660 }
661 #[inline(always)]
662 fn simd_min(self, other: Self) -> Self {
663 $WideF32xX(self.0.min(other.0))
664 }
665
666 #[inline(always)]
667 fn simd_clamp(self, min: Self, max: Self) -> Self {
668 self.simd_min(max).simd_max(min)
669 }
670
671 #[inline(always)]
672 fn simd_horizontal_min(self) -> Self::Element {
673 let arr = self.into_arr();
674 arr[0]$(.min(arr[$ii]))*
675 }
676
677 #[inline(always)]
678 fn simd_horizontal_max(self) -> Self::Element {
679 let arr = self.into_arr();
680 arr[0]$(.max(arr[$ii]))*
681 }
682 }
683
684 impl Neg for $WideF32xX {
685 type Output = Self;
686
687 #[inline(always)]
688 fn neg(self) -> Self {
689 Self(-self.0)
690 }
691 }
692
693 impl SimdSigned for $WideF32xX {
694 #[inline(always)]
695 fn simd_abs(&self) -> Self {
696 $WideF32xX(self.0.abs())
697 }
698
699 #[inline(always)]
700 fn simd_abs_sub(&self, other: &Self) -> Self {
701 $WideF32xX((self.0 - other.0).max(Self::zero().0))
702 }
703
704 #[inline(always)]
705 fn simd_signum(&self) -> Self {
706 self.map(|x| x.signum())
708 }
709
710 #[inline(always)]
711 fn is_simd_positive(&self) -> Self::SimdBool {
712 self.simd_gt(Self::zero())
713 }
714
715 #[inline(always)]
716 fn is_simd_negative(&self) -> Self::SimdBool {
717 self.simd_lt(Self::zero())
718 }
719 }
720
721 impl Field for $WideF32xX {}
722
723 impl SimdRealField for $WideF32xX {
724 #[inline(always)]
725 fn simd_atan2(self, other: Self) -> Self {
726 self.zip_map_lanes(other, <$f32 as RealField>::atan2)
727 }
728
729 #[inline(always)]
730 fn simd_copysign(self, sign: Self) -> Self {
731 let neg_zero = <Self as SimdValue>::splat(-0.0).0;
732 $WideF32xX((neg_zero & sign.0) | ((!neg_zero) & self.0))
733 }
734
735 #[inline(always)]
736 fn simd_default_epsilon() -> Self {
737 Self::splat(<$f32>::default_epsilon())
738 }
739
740 #[inline(always)]
741 fn simd_pi() -> Self {
742 $WideF32xX(wide::$f32xX::PI)
743 }
744
745 #[inline(always)]
746 fn simd_two_pi() -> Self {
747 $WideF32xX(wide::$f32xX::PI + wide::$f32xX::PI)
748 }
749
750 #[inline(always)]
751 fn simd_frac_pi_2() -> Self {
752 $WideF32xX(wide::$f32xX::FRAC_PI_2)
753 }
754
755 #[inline(always)]
756 fn simd_frac_pi_3() -> Self {
757 $WideF32xX(wide::$f32xX::FRAC_PI_3)
758 }
759
760 #[inline(always)]
761 fn simd_frac_pi_4() -> Self {
762 $WideF32xX(wide::$f32xX::FRAC_PI_4)
763 }
764
765 #[inline(always)]
766 fn simd_frac_pi_6() -> Self {
767 $WideF32xX(wide::$f32xX::FRAC_PI_6)
768 }
769
770 #[inline(always)]
771 fn simd_frac_pi_8() -> Self {
772 $WideF32xX(wide::$f32xX::FRAC_PI_8)
773 }
774
775 #[inline(always)]
776 fn simd_frac_1_pi() -> Self {
777 $WideF32xX(wide::$f32xX::FRAC_1_PI)
778 }
779
780 #[inline(always)]
781 fn simd_frac_2_pi() -> Self {
782 $WideF32xX(wide::$f32xX::FRAC_2_PI)
783 }
784
785 #[inline(always)]
786 fn simd_frac_2_sqrt_pi() -> Self {
787 $WideF32xX(wide::$f32xX::FRAC_2_SQRT_PI)
788 }
789
790 #[inline(always)]
791 fn simd_e() -> Self {
792 $WideF32xX(wide::$f32xX::E)
793 }
794
795 #[inline(always)]
796 fn simd_log2_e() -> Self {
797 $WideF32xX(wide::$f32xX::LOG2_E)
798 }
799
800 #[inline(always)]
801 fn simd_log10_e() -> Self {
802 $WideF32xX(wide::$f32xX::LOG10_E)
803 }
804
805 #[inline(always)]
806 fn simd_ln_2() -> Self {
807 $WideF32xX(wide::$f32xX::LN_2)
808 }
809
810 #[inline(always)]
811 fn simd_ln_10() -> Self {
812 $WideF32xX(wide::$f32xX::LN_10)
813 }
814 }
815
816 impl SimdComplexField for $WideF32xX {
817 type SimdRealField = Self;
818
819 #[inline(always)]
820 fn simd_horizontal_sum(self) -> Self::Element {
821 self.0.reduce_add()
822 }
823
824 #[inline(always)]
825 fn simd_horizontal_product(self) -> Self::Element {
826 self.extract(0) $(* self.extract($ii))*
827 }
828
829 #[inline(always)]
830 fn from_simd_real(re: Self::SimdRealField) -> Self {
831 re
832 }
833
834 #[inline(always)]
835 fn simd_real(self) -> Self::SimdRealField {
836 self
837 }
838
839 #[inline(always)]
840 fn simd_imaginary(self) -> Self::SimdRealField {
841 Self::zero()
842 }
843
844 #[inline(always)]
845 fn simd_norm1(self) -> Self::SimdRealField {
846 $WideF32xX(self.0.abs())
847 }
848
849 #[inline(always)]
850 fn simd_modulus(self) -> Self::SimdRealField {
851 $WideF32xX(self.0.abs())
852 }
853
854 #[inline(always)]
855 fn simd_modulus_squared(self) -> Self::SimdRealField {
856 self * self
857 }
858
859 #[inline(always)]
860 fn simd_argument(self) -> Self::SimdRealField {
861 self.map_lanes(|e| e.argument())
862 }
863
864 #[inline(always)]
865 fn simd_to_exp(self) -> (Self::SimdRealField, Self) {
866 let ge = self.0.simd_ge(Self::one().0);
867 let exp = ge.blend(Self::one().0, -Self::one().0);
868 ($WideF32xX(self.0 * exp), $WideF32xX(exp))
869 }
870
871 #[inline(always)]
872 fn simd_recip(self) -> Self {
873 Self::one() / self
874 }
875
876 #[inline(always)]
877 fn simd_conjugate(self) -> Self {
878 self
879 }
880
881 #[inline(always)]
882 fn simd_scale(self, factor: Self::SimdRealField) -> Self {
883 $WideF32xX(self.0 * factor.0)
884 }
885
886 #[inline(always)]
887 fn simd_unscale(self, factor: Self::SimdRealField) -> Self {
888 $WideF32xX(self.0 / factor.0)
889 }
890
891 #[inline(always)]
892 fn simd_floor(self) -> Self {
893 self.map_lanes(|e| e.floor())
894 }
895
896 #[inline(always)]
897 fn simd_ceil(self) -> Self {
898 self.map_lanes(|e| e.ceil())
899 }
900
901 #[inline(always)]
902 fn simd_round(self) -> Self {
903 self.map_lanes(|e| e.round())
904 }
905
906 #[inline(always)]
907 fn simd_trunc(self) -> Self {
908 self.map_lanes(|e| e.trunc())
909 }
910
911 #[inline(always)]
912 fn simd_fract(self) -> Self {
913 self.map_lanes(|e| e.fract())
914 }
915
916 #[inline(always)]
917 fn simd_abs(self) -> Self {
918 $WideF32xX(self.0.abs())
919 }
920
921 #[inline(always)]
922 fn simd_signum(self) -> Self {
923 self.map_lanes(|e| e.signum())
924 }
925
926 #[inline(always)]
927 fn simd_mul_add(self, a: Self, b: Self) -> Self {
928 $WideF32xX(self.0.mul_add(a.0, b.0))
929 }
930
931 #[inline(always)]
932 fn simd_powi(self, n: i32) -> Self {
933 self.map_lanes(|e| e.powi(n))
934 }
935
936 #[inline(always)]
937 fn simd_powf(self, n: Self) -> Self {
938 self.zip_map_lanes(n, <$f32 as ComplexField>::powf)
939 }
940
941 #[inline(always)]
942 fn simd_powc(self, n: Self) -> Self {
943 self.zip_map_lanes(n, <$f32 as ComplexField>::powf)
944 }
945
946 #[inline(always)]
947 fn simd_sqrt(self) -> Self {
948 $WideF32xX(self.0.sqrt())
949 }
950
951 #[inline(always)]
952 fn simd_exp(self) -> Self {
953 self.map_lanes(<$f32 as ComplexField>::exp)
954 }
955
956 #[inline(always)]
957 fn simd_exp2(self) -> Self {
958 self.map_lanes(<$f32 as ComplexField>::exp2)
959 }
960
961 #[inline(always)]
962 fn simd_exp_m1(self) -> Self {
963 self.map_lanes(<$f32 as ComplexField>::exp_m1)
964 }
965
966 #[inline(always)]
967 fn simd_ln_1p(self) -> Self {
968 self.map_lanes(<$f32 as ComplexField>::ln_1p)
969 }
970
971 #[inline(always)]
972 fn simd_ln(self) -> Self {
973 self.map_lanes(<$f32 as ComplexField>::ln)
974 }
975
976 #[inline(always)]
977 fn simd_log(self, base: Self) -> Self {
978 self.zip_map_lanes(base, |e, b| <$f32 as ComplexField>::ln(e) / <$f32 as ComplexField>::ln(b))
980 }
981
982 #[inline(always)]
983 fn simd_log2(self) -> Self {
984 self.map_lanes(<$f32 as ComplexField>::log2)
985 }
986
987 #[inline(always)]
988 fn simd_log10(self) -> Self {
989 self.map_lanes(<$f32 as ComplexField>::log10)
990 }
991
992 #[inline(always)]
993 fn simd_cbrt(self) -> Self {
994 self.map_lanes(<$f32 as ComplexField>::cbrt)
995 }
996
997 #[inline(always)]
998 fn simd_hypot(self, other: Self) -> Self::SimdRealField {
999 self.zip_map_lanes(other, <$f32 as ComplexField>::hypot)
1000 }
1001
1002 #[cfg(not(feature = "libm_force"))]
1006 #[inline(always)]
1007 fn simd_sin(self) -> Self {
1008 $WideF32xX(self.0.sin())
1009 }
1010
1011 #[cfg(feature = "libm_force")]
1012 #[inline(always)]
1013 fn simd_sin(self) -> Self {
1014 self.map_lanes(<$f32 as ComplexField>::sin)
1015 }
1016
1017 #[cfg(not(feature = "libm_force"))]
1018 #[inline(always)]
1019 fn simd_cos(self) -> Self {
1020 $WideF32xX(self.0.cos())
1021 }
1022
1023 #[cfg(feature = "libm_force")]
1024 #[inline(always)]
1025 fn simd_cos(self) -> Self {
1026 self.map_lanes(<$f32 as ComplexField>::cos)
1027 }
1028
1029 #[inline(always)]
1030 fn simd_tan(self) -> Self {
1031 self.map_lanes(<$f32 as ComplexField>::tan)
1032 }
1033
1034 #[inline(always)]
1035 fn simd_asin(self) -> Self {
1036 self.map_lanes(<$f32 as ComplexField>::asin)
1037 }
1038
1039 #[inline(always)]
1040 fn simd_acos(self) -> Self {
1041 self.map_lanes(<$f32 as ComplexField>::acos)
1042 }
1043
1044 #[inline(always)]
1045 fn simd_atan(self) -> Self {
1046 self.map_lanes(<$f32 as ComplexField>::atan)
1047 }
1048
1049 #[cfg(not(feature = "libm_force"))]
1050 #[inline(always)]
1051 fn simd_sin_cos(self) -> (Self, Self) {
1052 let (sin, cos) = self.0.sin_cos();
1053 ($WideF32xX(sin), $WideF32xX(cos))
1054 }
1055
1056 #[cfg(feature = "libm_force")]
1057 #[inline(always)]
1058 fn simd_sin_cos(self) -> (Self, Self) {
1059 let mut sin = self;
1060 let mut cos = self;
1061 for ii in 0..$lanes {
1062 let (s, c) = <$f32 as ComplexField>::sin_cos(self.extract(ii));
1063 sin.replace(ii, s);
1064 cos.replace(ii, c);
1065 }
1066 (sin, cos)
1067 }
1068
1069 #[inline(always)]
1080 fn simd_sinh(self) -> Self {
1081 self.map_lanes(<$f32 as ComplexField>::sinh)
1082 }
1083
1084 #[inline(always)]
1085 fn simd_cosh(self) -> Self {
1086 self.map_lanes(<$f32 as ComplexField>::cosh)
1087 }
1088
1089 #[inline(always)]
1090 fn simd_tanh(self) -> Self {
1091 self.map_lanes(<$f32 as ComplexField>::tanh)
1092 }
1093
1094 #[inline(always)]
1095 fn simd_asinh(self) -> Self {
1096 self.map_lanes(<$f32 as ComplexField>::asinh)
1097 }
1098
1099 #[inline(always)]
1100 fn simd_acosh(self) -> Self {
1101 self.map_lanes(<$f32 as ComplexField>::acosh)
1102 }
1103
1104 #[inline(always)]
1105 fn simd_atanh(self) -> Self {
1106 self.map_lanes(<$f32 as ComplexField>::atanh)
1107 }
1108 }
1109
1110 impl SimdComplexField for num_complex::Complex<$WideF32xX> {
1114 type SimdRealField = $WideF32xX;
1115
1116 #[inline(always)]
1117 fn simd_horizontal_sum(self) -> Self::Element {
1118 num_complex::Complex::new(self.re.simd_horizontal_sum(), self.im.simd_horizontal_sum())
1119 }
1120
1121 #[inline(always)]
1122 fn simd_horizontal_product(self) -> Self::Element {
1123 let mut prod = self.extract(0);
1124 for ii in 1..Self::LANES {
1125 prod *= self.extract(ii)
1126 }
1127 prod
1128 }
1129
1130 #[inline]
1131 fn from_simd_real(re: Self::SimdRealField) -> Self {
1132 Self::new(re, Self::SimdRealField::zero())
1133 }
1134
1135 #[inline]
1136 fn simd_real(self) -> Self::SimdRealField {
1137 self.re
1138 }
1139
1140 #[inline]
1141 fn simd_imaginary(self) -> Self::SimdRealField {
1142 self.im
1143 }
1144
1145 #[inline]
1146 fn simd_argument(self) -> Self::SimdRealField {
1147 self.im.simd_atan2(self.re)
1148 }
1149
1150 #[inline]
1151 fn simd_modulus(self) -> Self::SimdRealField {
1152 self.re.simd_hypot(self.im)
1153 }
1154
1155 #[inline]
1156 fn simd_modulus_squared(self) -> Self::SimdRealField {
1157 self.re * self.re + self.im * self.im
1158 }
1159
1160 #[inline]
1161 fn simd_norm1(self) -> Self::SimdRealField {
1162 self.re.simd_abs() + self.im.simd_abs()
1163 }
1164
1165 #[inline]
1166 fn simd_recip(self) -> Self {
1167 Self::one() / self
1168 }
1169
1170 #[inline]
1171 fn simd_conjugate(self) -> Self {
1172 self.conj()
1173 }
1174
1175 #[inline]
1176 fn simd_scale(self, factor: Self::SimdRealField) -> Self {
1177 self * factor
1178 }
1179
1180 #[inline]
1181 fn simd_unscale(self, factor: Self::SimdRealField) -> Self {
1182 self / factor
1183 }
1184
1185 #[inline]
1186 fn simd_floor(self) -> Self {
1187 Self::new(self.re.simd_floor(), self.im.simd_floor())
1188 }
1189
1190 #[inline]
1191 fn simd_ceil(self) -> Self {
1192 Self::new(self.re.simd_ceil(), self.im.simd_ceil())
1193 }
1194
1195 #[inline]
1196 fn simd_round(self) -> Self {
1197 Self::new(self.re.simd_round(), self.im.simd_round())
1198 }
1199
1200 #[inline]
1201 fn simd_trunc(self) -> Self {
1202 Self::new(self.re.simd_trunc(), self.im.simd_trunc())
1203 }
1204
1205 #[inline]
1206 fn simd_fract(self) -> Self {
1207 Self::new(self.re.simd_fract(), self.im.simd_fract())
1208 }
1209
1210 #[inline]
1211 fn simd_mul_add(self, a: Self, b: Self) -> Self {
1212 self * a + b
1213 }
1214
1215 #[inline]
1216 fn simd_abs(self) -> Self::SimdRealField {
1217 self.simd_modulus()
1218 }
1219
1220 #[inline]
1221 fn simd_exp2(self) -> Self {
1222 let _2 = <$WideF32xX>::one() + <$WideF32xX>::one();
1223 num_complex::Complex::new(_2, <$WideF32xX>::zero()).simd_powc(self)
1224 }
1225
1226 #[inline]
1227 fn simd_exp_m1(self) -> Self {
1228 self.simd_exp() - Self::one()
1229 }
1230
1231 #[inline]
1232 fn simd_ln_1p(self) -> Self {
1233 (Self::one() + self).simd_ln()
1234 }
1235
1236 #[inline]
1237 fn simd_log2(self) -> Self {
1238 let _2 = <$WideF32xX>::one() + <$WideF32xX>::one();
1239 self.simd_log(_2)
1240 }
1241
1242 #[inline]
1243 fn simd_log10(self) -> Self {
1244 let _10 = <$WideF32xX>::from_subset(&10.0f64);
1245 self.simd_log(_10)
1246 }
1247
1248 #[inline]
1249 fn simd_cbrt(self) -> Self {
1250 let one_third = <$WideF32xX>::from_subset(&(1.0 / 3.0));
1251 self.simd_powf(one_third)
1252 }
1253
1254 #[inline]
1255 fn simd_powi(self, n: i32) -> Self {
1256 let n = <$WideF32xX>::from_subset(&(n as f64));
1258 self.simd_powf(n)
1259 }
1260
1261 #[inline]
1272 fn simd_exp(self) -> Self {
1273 simd_complex_from_polar(self.re.simd_exp(), self.im)
1276 }
1277
1278 #[inline]
1286 fn simd_ln(self) -> Self {
1287 let (r, theta) = self.simd_to_polar();
1289 Self::new(r.simd_ln(), theta)
1290 }
1291
1292 #[inline]
1300 fn simd_sqrt(self) -> Self {
1301 let two = <$WideF32xX>::one() + <$WideF32xX>::one();
1303 let (r, theta) = self.simd_to_polar();
1304 simd_complex_from_polar(r.simd_sqrt(), theta / two)
1305 }
1306
1307 #[inline]
1308 fn simd_hypot(self, b: Self) -> Self::SimdRealField {
1309 (self.simd_modulus_squared() + b.simd_modulus_squared()).simd_sqrt()
1310 }
1311
1312 #[inline]
1314 fn simd_powf(self, exp: Self::SimdRealField) -> Self {
1315 let (r, theta) = self.simd_to_polar();
1318 simd_complex_from_polar(r.simd_powf(exp), theta * exp)
1319 }
1320
1321 #[inline]
1323 fn simd_log(self, base: $WideF32xX) -> Self {
1324 let (r, theta) = self.simd_to_polar();
1328 Self::new(r.simd_log(base), theta / base.simd_ln())
1329 }
1330
1331 #[inline]
1333 fn simd_powc(self, exp: Self) -> Self {
1334 let (r, theta) = self.simd_to_polar();
1346 simd_complex_from_polar(
1347 r.simd_powf(exp.re) * (-exp.im * theta).simd_exp(),
1348 exp.re * theta + exp.im * r.simd_ln(),
1349 )
1350 }
1351
1352 #[inline]
1364 fn simd_sin(self) -> Self {
1365 Self::new(
1367 self.re.simd_sin() * self.im.simd_cosh(),
1368 self.re.simd_cos() * self.im.simd_sinh(),
1369 )
1370 }
1371
1372 #[inline]
1374 fn simd_cos(self) -> Self {
1375 Self::new(
1377 self.re.simd_cos() * self.im.simd_cosh(),
1378 -self.re.simd_sin() * self.im.simd_sinh(),
1379 )
1380 }
1381
1382 #[inline]
1383 fn simd_sin_cos(self) -> (Self, Self) {
1384 let (rsin, rcos) = self.re.simd_sin_cos();
1385 let (isinh, icosh) = self.im.simd_sinh_cosh();
1386 let sin = Self::new(rsin * icosh, rcos * isinh);
1387 let cos = Self::new(rcos * icosh, -rsin * isinh);
1388
1389 (sin, cos)
1390 }
1391
1392 #[inline]
1394 fn simd_tan(self) -> Self {
1395 let (two_re, two_im) = (self.re + self.re, self.im + self.im);
1397 Self::new(two_re.simd_sin(), two_im.simd_sinh())
1398 .unscale(two_re.simd_cos() + two_im.simd_cosh())
1399 }
1400
1401 #[inline]
1410 fn simd_asin(self) -> Self {
1411 let i = Self::i();
1413 -i * ((Self::one() - self * self).simd_sqrt() + i * self).simd_ln()
1414 }
1415
1416 #[inline]
1425 fn simd_acos(self) -> Self {
1426 let i = Self::i();
1428 -i * (i * (Self::one() - self * self).simd_sqrt() + self).simd_ln()
1429 }
1430
1431 #[inline]
1440 fn simd_atan(self) -> Self {
1441 let i = Self::i();
1443 let one = Self::one();
1444 let two = one + one;
1445
1446 if self == i {
1447 return Self::new(<$WideF32xX>::zero(), <$WideF32xX>::one() / <$WideF32xX>::zero());
1448 } else if self == -i {
1449 return Self::new(<$WideF32xX>::zero(), -<$WideF32xX>::one() / <$WideF32xX>::zero());
1450 }
1451
1452 ((one + i * self).simd_ln() - (one - i * self).simd_ln()) / (two * i)
1453 }
1454
1455 #[inline]
1457 fn simd_sinh(self) -> Self {
1458 Self::new(
1460 self.re.simd_sinh() * self.im.simd_cos(),
1461 self.re.simd_cosh() * self.im.simd_sin(),
1462 )
1463 }
1464
1465 #[inline]
1467 fn simd_cosh(self) -> Self {
1468 Self::new(
1470 self.re.simd_cosh() * self.im.simd_cos(),
1471 self.re.simd_sinh() * self.im.simd_sin(),
1472 )
1473 }
1474
1475 #[inline]
1476 fn simd_sinh_cosh(self) -> (Self, Self) {
1477 let (rsinh, rcosh) = self.re.simd_sinh_cosh();
1478 let (isin, icos) = self.im.simd_sin_cos();
1479 let sin = Self::new(rsinh * icos, rcosh * isin);
1480 let cos = Self::new(rcosh * icos, rsinh * isin);
1481
1482 (sin, cos)
1483 }
1484
1485 #[inline]
1487 fn simd_tanh(self) -> Self {
1488 let (two_re, two_im) = (self.re + self.re, self.im + self.im);
1490 Self::new(two_re.simd_sinh(), two_im.simd_sin())
1491 .unscale(two_re.simd_cosh() + two_im.simd_cos())
1492 }
1493
1494 #[inline]
1503 fn simd_asinh(self) -> Self {
1504 let one = Self::one();
1506 (self + (one + self * self).simd_sqrt()).simd_ln()
1507 }
1508
1509 #[inline]
1517 fn simd_acosh(self) -> Self {
1518 let one = Self::one();
1520 let two = one + one;
1521 two * (((self + one) / two).simd_sqrt() + ((self - one) / two).simd_sqrt()).simd_ln()
1522 }
1523
1524 #[inline]
1533 fn simd_atanh(self) -> Self {
1534 let one = Self::one();
1536 let two = one + one;
1537 if self == one {
1538 return Self::new(<$WideF32xX>::one() / <$WideF32xX>::zero(), <$WideF32xX>::zero());
1539 } else if self == -one {
1540 return Self::new(-<$WideF32xX>::one() / <$WideF32xX>::zero(), <$WideF32xX>::zero());
1541 }
1542 ((one + self).simd_ln() - (one - self).simd_ln()) / two
1543 }
1544 }
1545 }
1546);
1547
1548macro_rules! impl_scalar_subset_of_simd (
1549 ($WideF32xX: ty, $f32: ty, $lanes: expr; $($t: ty),*) => {$(
1550 impl SubsetOf<$WideF32xX> for $t {
1551 #[inline(always)]
1552 fn to_superset(&self) -> $WideF32xX {
1553 <$WideF32xX>::splat(<$f32>::from_subset(self))
1554 }
1555
1556 #[inline(always)]
1557 fn from_superset_unchecked(element: &$WideF32xX) -> $t {
1558 element.extract(0).to_subset_unchecked()
1559 }
1560
1561 #[inline(always)]
1562 fn is_in_subset(c: &$WideF32xX) -> bool {
1563 let elt0 = c.extract(0);
1564 <$t as SubsetOf<$f32>>::is_in_subset(&elt0) &&
1565 (1..$lanes).all(|i| c.extract(i) == elt0)
1566 }
1567 }
1568 )*}
1569);
1570
1571impl_scalar_subset_of_simd!(WideF32x4, f32, 4; u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, f32, f64);
1572impl_scalar_subset_of_simd!(WideF64x4, f64, 4; u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, f32, f64);
1573impl_scalar_subset_of_simd!(WideF32x8, f32, 8; u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, f32, f64);
1576impl_wide_f32!(f32, f32x4, WideF32x4, WideBoolF32x4, 4; 1, 2, 3);
1582impl_wide_f32!(f64, f64x4, WideF64x4, WideBoolF64x4, 4; 1, 2, 3);
1583impl_wide_f32!(f32, f32x8, WideF32x8, WideBoolF32x8, 8; 1, 2, 3, 4, 5, 6, 7);
1584
1585#[inline]
1586fn simd_complex_from_polar<N: SimdRealField>(r: N, theta: N) -> num_complex::Complex<N> {
1587 num_complex::Complex::new(r.clone() * theta.clone().simd_cos(), r * theta.simd_sin())
1588}