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