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