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