1#![allow(missing_docs)]
2#![allow(non_camel_case_types)] use crate::scalar::{Field, SubsetOf, SupersetOf};
7use crate::simd::{
8 PrimitiveSimdValue, SimdBool, SimdComplexField, SimdPartialOrd, SimdRealField, SimdSigned,
9 SimdValue,
10};
11use approx::AbsDiffEq;
12#[cfg(feature = "decimal")]
13use decimal::d128;
14use num::{FromPrimitive, Num, One, Zero};
15use std::{
16 fmt,
17 ops::{
18 Add, AddAssign, BitAnd, BitOr, BitXor, Div, DivAssign, Mul, MulAssign, Neg, Not, Rem,
19 RemAssign, Sub, SubAssign,
20 },
21};
22
23macro_rules! ident_to_value(
27 () => {
28 const _0: usize = 0; const _1: usize = 1; const _2: usize = 2; const _3: usize = 3; const _4: usize = 4; const _5: usize = 5; const _6: usize = 6; const _7: usize = 7;
29 const _8: usize = 8; const _9: usize = 9; const _10: usize = 10; const _11: usize = 11; const _12: usize = 12; const _13: usize = 13; const _14: usize = 14; const _15: usize = 15;
30 const _16: usize = 16; const _17: usize = 17; const _18: usize = 18; const _19: usize = 19; const _20: usize = 20; const _21: usize = 21; const _22: usize = 22; const _23: usize = 23;
31 const _24: usize = 24; const _25: usize = 25; const _26: usize = 26; const _27: usize = 27; const _28: usize = 28; const _29: usize = 29; const _30: usize = 30; const _31: usize = 31;
32 const _32: usize = 32; const _33: usize = 33; const _34: usize = 34; const _35: usize = 35; const _36: usize = 36; const _37: usize = 37; const _38: usize = 38; const _39: usize = 39;
33 const _40: usize = 40; const _41: usize = 41; const _42: usize = 42; const _43: usize = 43; const _44: usize = 44; const _45: usize = 45; const _46: usize = 46; const _47: usize = 47;
34 const _48: usize = 48; const _49: usize = 49; const _50: usize = 50; const _51: usize = 51; const _52: usize = 52; const _53: usize = 53; const _54: usize = 54; const _55: usize = 55;
35 const _56: usize = 56; const _57: usize = 57; const _58: usize = 58; const _59: usize = 59; const _60: usize = 60; const _61: usize = 61; const _62: usize = 62; const _63: usize = 63;
36 }
37);
38
39#[repr(align(16))]
43#[derive(Copy, Clone, PartialEq, Eq, Debug)]
44#[cfg_attr(
45 feature = "rkyv",
46 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize)
47)]
48#[cfg_attr(feature = "cuda", derive(cust_core::DeviceCopy))]
49pub struct AutoSimd<N>(pub N);
50
51#[repr(align(16))]
55#[derive(Copy, Clone, PartialEq, Eq, Debug)]
56#[cfg_attr(
57 feature = "rkyv",
58 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize)
59)]
60pub struct AutoBoolSimd<N>(pub N);
61
62macro_rules! impl_bool_simd(
63 ($($t: ty, $lanes: expr, $($i: ident),*;)*) => {$(
64 impl_simd_value!($t, bool, $lanes, AutoSimd<$t> $(, $i)*;);
65
66 impl From<[bool; $lanes]> for AutoSimd<$t> {
67 #[inline(always)]
68 fn from(vals: [bool; $lanes]) -> Self {
69 Self(vals)
70 }
71 }
72
73 impl Not for AutoSimd<$t> {
74 type Output = Self;
75
76 #[inline]
77 fn not(self) -> Self {
78 self.map(|x| !x)
79 }
80 }
81
82 impl BitAnd<AutoSimd<$t>> for AutoSimd<$t> {
83 type Output = Self;
84 fn bitand(self, rhs: Self) -> Self {
85 self.zip_map(rhs, |x, y| x & y)
86 }
87 }
88
89 impl BitOr<AutoSimd<$t>> for AutoSimd<$t> {
90 type Output = Self;
91 fn bitor(self, rhs: Self) -> Self {
92 self.zip_map(rhs, |x, y| x | y)
93 }
94 }
95
96 impl BitXor<AutoSimd<$t>> for AutoSimd<$t> {
97 type Output = Self;
98 fn bitxor(self, rhs: Self) -> Self {
99 self.zip_map(rhs, |x, y| x ^ y)
100 }
101 }
102
103 impl SimdBool for AutoSimd<$t> {
104 #[inline(always)]
105 fn bitmask(self) -> u64 {
106 ident_to_value!();
107 0u64 $(
108 | ((self.0[$i] as u64) << $i)
109 )*
110 }
111
112 #[inline(always)]
113 fn and(self) -> bool {
114 ident_to_value!();
115 true $(
116 && self.0[$i]
117 )*
118 }
119
120 #[inline(always)]
121 fn or(self) -> bool {
122 ident_to_value!();
123 false $(
124 || self.0[$i]
125 )*
126 }
127
128 #[inline(always)]
129 fn xor(self) -> bool {
130 ident_to_value!();
131 false $(
132 ^ self.0[$i]
133 )*
134 }
135
136 #[inline(always)]
137 fn all(self) -> bool {
138 self.and()
139 }
140
141 #[inline(always)]
142 fn any(self) -> bool {
143 self.or()
144 }
145
146 #[inline(always)]
147 fn none(self) -> bool {
148 !self.any()
149 }
150
151 #[inline(always)]
152 fn if_else<Res: SimdValue<SimdBool = Self>>(
153 self,
154 if_value: impl FnOnce() -> Res,
155 else_value: impl FnOnce() -> Res,
156 ) -> Res {
157 let a = if_value();
158 let b = else_value();
159 a.select(self, b)
160 }
161
162 #[inline(always)]
163 fn if_else2<Res: SimdValue<SimdBool = Self>>(
164 self,
165 if_value: impl FnOnce() -> Res,
166 else_if: (impl FnOnce() -> Self, impl FnOnce() -> Res),
167 else_value: impl FnOnce() -> Res,
168 ) -> Res {
169 let a = if_value();
170 let b = else_if.1();
171 let c = else_value();
172
173 let cond_a = self;
174 let cond_b = else_if.0();
175
176 a.select(cond_a, b.select(cond_b, c))
177 }
178
179 #[inline(always)]
180 fn if_else3<Res: SimdValue<SimdBool = Self>>(
181 self,
182 if_value: impl FnOnce() -> Res,
183 else_if: (impl FnOnce() -> Self, impl FnOnce() -> Res),
184 else_else_if: (impl FnOnce() -> Self, impl FnOnce() -> Res),
185 else_value: impl FnOnce() -> Res,
186 ) -> Res {
187 let a = if_value();
188 let b = else_if.1();
189 let c = else_else_if.1();
190 let d = else_value();
191
192 let cond_a = self;
193 let cond_b = else_if.0();
194 let cond_c = else_else_if.0();
195
196 a.select(cond_a, b.select(cond_b, c.select(cond_c, d)))
197 }
198 }
199 )*}
200);
201
202macro_rules! impl_scalar_subset_of_simd(
203 ($($t: ty),*) => {$(
204 impl<N2> SubsetOf<AutoSimd<N2>> for $t
205 where AutoSimd<N2>: SimdValue + Copy,
206 <AutoSimd<N2> as SimdValue>::Element: SupersetOf<$t> + PartialEq, {
207 #[inline(always)]
208 fn to_superset(&self) -> AutoSimd<N2> {
209 AutoSimd::<N2>::splat(<AutoSimd<N2> as SimdValue>::Element::from_subset(self))
210 }
211
212 #[inline(always)]
213 fn from_superset_unchecked(element: &AutoSimd<N2>) -> $t {
214 element.extract(0).to_subset_unchecked()
215 }
216
217 #[inline(always)]
218 fn is_in_subset(c: &AutoSimd<N2>) -> bool {
219 let elt0 = c.extract(0);
220 elt0.is_in_subset() &&
221 (1..AutoSimd::<N2>::lanes()).all(|i| c.extract(i) == elt0)
222 }
223 }
224 )*}
225);
226
227impl_scalar_subset_of_simd!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, f32, f64);
228#[cfg(feature = "decimal")]
229impl_scalar_subset_of_simd!(d128);
230
231macro_rules! impl_simd_value(
232 ($($t: ty, $elt: ty, $lanes: expr, $bool: ty, $($i: ident),*;)*) => ($(
233 impl ArrTransform for AutoSimd<$t> {
234 #[inline(always)]
235 fn map(self, f: impl Fn(Self::Element) -> Self::Element) -> Self {
236 ident_to_value!();
237 Self([$(f(self.0[$i])),*])
238 }
239
240 #[inline(always)]
241 fn zip_map(self, other: Self, f: impl Fn(Self::Element, Self::Element) -> Self::Element) -> Self {
242 ident_to_value!();
243 Self([$(f(self.0[$i], other.0[$i])),*])
244 }
245
246 #[inline(always)]
247 fn zip_zip_map(self, b: Self, c: Self, f: impl Fn(Self::Element, Self::Element, Self::Element) -> Self::Element) -> Self {
248 ident_to_value!();
249 Self([$(f(self.0[$i], b.0[$i], c.0[$i])),*])
250 }
251
252 #[inline(always)]
253 fn map_bool(self, f: impl Fn(Self::Element) -> bool) -> Self::SimdBool {
254 ident_to_value!();
255 AutoSimd([$(f(self.0[$i])),*])
256 }
257
258 #[inline(always)]
259 fn zip_map_bool(self, other: Self, f: impl Fn(Self::Element, Self::Element) -> bool) -> Self::SimdBool {
260 ident_to_value!();
261 AutoSimd([$(f(self.0[$i], other.0[$i])),*])
262 }
263 }
264
265 impl fmt::Display for AutoSimd<$t> {
266 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
267 if Self::lanes() == 1 {
268 return self.extract(0).fmt(f);
269 }
270
271 write!(f, "({}", self.extract(0))?;
272
273 for i in 1..Self::lanes() {
274 write!(f, ", {}", self.extract(i))?;
275 }
276
277 write!(f, ")")
278 }
279 }
280
281 impl AutoSimd<$t> {
282 pub fn new($($i: $elt),*) -> Self {
283 AutoSimd([$($i),*])
284 }
285 }
286
287 impl PrimitiveSimdValue for AutoSimd<$t> {}
288
289 impl SimdValue for AutoSimd<$t> {
290 type Element = $elt;
291 type SimdBool = $bool;
292
293 #[inline(always)]
294 fn lanes() -> usize {
295 $lanes
296 }
297
298 #[inline(always)]
299 fn splat(val: Self::Element) -> Self {
300 AutoSimd([val; $lanes])
301 }
302
303 #[inline(always)]
304 fn extract(&self, i: usize) -> Self::Element {
305 self.0[i]
306 }
307
308 #[inline(always)]
309 unsafe fn extract_unchecked(&self, i: usize) -> Self::Element {
310 *self.0.get_unchecked(i)
311 }
312
313 #[inline(always)]
314 fn replace(&mut self, i: usize, val: Self::Element) {
315 self.0[i] = val
316 }
317
318 #[inline(always)]
319 unsafe fn replace_unchecked(&mut self, i: usize, val: Self::Element) {
320 *self.0.get_unchecked_mut(i) = val
321 }
322
323 #[inline(always)]
324 fn select(self, cond: Self::SimdBool, other: Self) -> Self {
325 ident_to_value!();
326 Self([
327 $(if cond.0[$i] { self.0[$i] } else { other.0[$i] }),*
328 ])
329 }
330 }
331 )*)
332);
333
334macro_rules! impl_uint_simd(
335 ($($t: ty, $elt: ty, $lanes: expr, $bool: ty, $($i: ident),*;)*) => ($(
336 impl_simd_value!($t, $elt, $lanes, $bool $(, $i)*;);
337
338 impl From<[$elt; $lanes]> for AutoSimd<$t> {
339 #[inline(always)]
340 fn from(vals: [$elt; $lanes]) -> Self {
341 AutoSimd(vals)
342 }
343 }
344
345 impl From<AutoSimd<$t>> for [$elt; $lanes] {
346 #[inline(always)]
347 fn from(val: AutoSimd<$t>) -> [$elt; $lanes] {
348 val.0
349 }
350 }
351
352 impl SubsetOf<AutoSimd<$t>> for AutoSimd<$t> {
353 #[inline(always)]
354 fn to_superset(&self) -> Self {
355 *self
356 }
357
358 #[inline(always)]
359 fn from_superset(element: &Self) -> Option<Self> {
360 Some(*element)
361 }
362
363 #[inline(always)]
364 fn from_superset_unchecked(element: &Self) -> Self {
365 *element
366 }
367
368 #[inline(always)]
369 fn is_in_subset(_: &Self) -> bool {
370 true
371 }
372 }
373
374 impl Num for AutoSimd<$t> {
375 type FromStrRadixErr = <$elt as Num>::FromStrRadixErr;
376
377 #[inline(always)]
378 fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
379 <$elt>::from_str_radix(str, radix).map(Self::splat)
380 }
381 }
382
383 impl FromPrimitive for AutoSimd<$t> {
384 #[inline(always)]
385 fn from_i64(n: i64) -> Option<Self> {
386 <$elt>::from_i64(n).map(Self::splat)
387 }
388
389 #[inline(always)]
390 fn from_u64(n: u64) -> Option<Self> {
391 <$elt>::from_u64(n).map(Self::splat)
392 }
393
394 #[inline(always)]
395 fn from_isize(n: isize) -> Option<Self> {
396 <$elt>::from_isize(n).map(Self::splat)
397 }
398
399 #[inline(always)]
400 fn from_i8(n: i8) -> Option<Self> {
401 <$elt>::from_i8(n).map(Self::splat)
402 }
403
404 #[inline(always)]
405 fn from_i16(n: i16) -> Option<Self> {
406 <$elt>::from_i16(n).map(Self::splat)
407 }
408
409 #[inline(always)]
410 fn from_i32(n: i32) -> Option<Self> {
411 <$elt>::from_i32(n).map(Self::splat)
412 }
413
414 #[inline(always)]
415 fn from_usize(n: usize) -> Option<Self> {
416 <$elt>::from_usize(n).map(Self::splat)
417 }
418
419 #[inline(always)]
420 fn from_u8(n: u8) -> Option<Self> {
421 <$elt>::from_u8(n).map(Self::splat)
422 }
423
424 #[inline(always)]
425 fn from_u16(n: u16) -> Option<Self> {
426 <$elt>::from_u16(n).map(Self::splat)
427 }
428
429 #[inline(always)]
430 fn from_u32(n: u32) -> Option<Self> {
431 <$elt>::from_u32(n).map(Self::splat)
432 }
433
434 #[inline(always)]
435 fn from_f32(n: f32) -> Option<Self> {
436 <$elt>::from_f32(n).map(Self::splat)
437 }
438
439 #[inline(always)]
440 fn from_f64(n: f64) -> Option<Self> {
441 <$elt>::from_f64(n).map(Self::splat)
442 }
443 }
444
445
446 impl Zero for AutoSimd<$t> {
447 #[inline(always)]
448 fn zero() -> Self {
449 AutoSimd([<$elt>::zero(); $lanes])
450 }
451
452 #[inline(always)]
453 fn is_zero(&self) -> bool {
454 *self == Self::zero()
455 }
456 }
457
458 impl One for AutoSimd<$t> {
459 #[inline(always)]
460 fn one() -> Self {
461 AutoSimd([<$elt>::one(); $lanes])
462 }
463 }
464
465 impl Add<AutoSimd<$t>> for AutoSimd<$t> {
466 type Output = Self;
467
468 #[inline(always)]
469 fn add(self, rhs: Self) -> Self {
470 self.zip_map(rhs, |x, y| x + y)
471 }
472 }
473
474 impl Sub<AutoSimd<$t>> for AutoSimd<$t> {
475 type Output = Self;
476
477 #[inline(always)]
478 fn sub(self, rhs: Self) -> Self {
479 self.zip_map(rhs, |x, y| x - y)
480 }
481 }
482
483 impl Mul<AutoSimd<$t>> for AutoSimd<$t> {
484 type Output = Self;
485
486 #[inline(always)]
487 fn mul(self, rhs: Self) -> Self {
488 self.zip_map(rhs, |x, y| x * y)
489 }
490 }
491
492 impl Div<AutoSimd<$t>> for AutoSimd<$t> {
493 type Output = Self;
494
495 #[inline(always)]
496 fn div(self, rhs: Self) -> Self {
497 self.zip_map(rhs, |x, y| x / y)
498 }
499 }
500
501 impl Rem<AutoSimd<$t>> for AutoSimd<$t> {
502 type Output = Self;
503
504 #[inline(always)]
505 fn rem(self, rhs: Self) -> Self {
506 self.zip_map(rhs, |x, y| x % y)
507 }
508 }
509
510 impl AddAssign<AutoSimd<$t>> for AutoSimd<$t> {
511 #[inline(always)]
512 fn add_assign(&mut self, rhs: Self) {
513 *self = *self + rhs;
514 }
515 }
516
517 impl SubAssign<AutoSimd<$t>> for AutoSimd<$t> {
518 #[inline(always)]
519 fn sub_assign(&mut self, rhs: Self) {
520 *self = *self - rhs;
521 }
522 }
523
524 impl DivAssign<AutoSimd<$t>> for AutoSimd<$t> {
525 #[inline(always)]
526 fn div_assign(&mut self, rhs: Self) {
527 *self = *self / rhs;
528 }
529 }
530
531 impl MulAssign<AutoSimd<$t>> for AutoSimd<$t> {
532 #[inline(always)]
533 fn mul_assign(&mut self, rhs: Self) {
534 *self = *self * rhs;
535 }
536 }
537
538 impl RemAssign<AutoSimd<$t>> for AutoSimd<$t> {
539 #[inline(always)]
540 fn rem_assign(&mut self, rhs: Self) {
541 *self = *self % rhs;
542 }
543 }
544
545 impl SimdPartialOrd for AutoSimd<$t> {
546 #[inline(always)]
547 fn simd_gt(self, other: Self) -> Self::SimdBool {
548 self.zip_map_bool(other, |x, y| x.simd_gt(y))
549 }
550
551 #[inline(always)]
552 fn simd_lt(self, other: Self) -> Self::SimdBool {
553 self.zip_map_bool(other, |x, y| x.simd_lt(y))
554 }
555
556 #[inline(always)]
557 fn simd_ge(self, other: Self) -> Self::SimdBool {
558 self.zip_map_bool(other, |x, y| x.simd_ge(y))
559 }
560
561 #[inline(always)]
562 fn simd_le(self, other: Self) -> Self::SimdBool {
563 self.zip_map_bool(other, |x, y| x.simd_le(y))
564 }
565
566 #[inline(always)]
567 fn simd_eq(self, other: Self) -> Self::SimdBool {
568 self.zip_map_bool(other, |x, y| x.simd_eq(y))
569 }
570
571 #[inline(always)]
572 fn simd_ne(self, other: Self) -> Self::SimdBool {
573 self.zip_map_bool(other, |x, y| x.simd_ne(y))
574 }
575
576 #[inline(always)]
577 fn simd_max(self, other: Self) -> Self {
578 self.zip_map(other, |x, y| x.simd_max(y))
579 }
580 #[inline(always)]
581 fn simd_min(self, other: Self) -> Self {
582 self.zip_map(other, |x, y| x.simd_min(y))
583 }
584
585 #[inline(always)]
586 fn simd_clamp(self, min: Self, max: Self) -> Self {
587 self.simd_max(min).simd_min(max)
588 }
589
590 #[inline(always)]
591 fn simd_horizontal_min(self) -> Self::Element {
592 ident_to_value!();
593 self.0[0] $(.simd_min(self.0[$i]))*
594 }
595
596 #[inline(always)]
597 fn simd_horizontal_max(self) -> Self::Element {
598 ident_to_value!();
599 self.0[0] $(.simd_max(self.0[$i]))*
600 }
601 }
602
603)*)
617);
618
619macro_rules! impl_int_simd(
620 ($($t: ty, $elt: ty, $lanes: expr, $bool: ty, $($i: ident),*;)*) => ($(
621 impl_uint_simd!($t, $elt, $lanes, $bool $(, $i)*;);
622
623 impl Neg for AutoSimd<$t> {
624 type Output = Self;
625
626 #[inline(always)]
627 fn neg(self) -> Self {
628 self.map(|x| -x)
629 }
630 }
631 )*)
632);
633
634macro_rules! impl_float_simd(
635 ($($t: ty, $elt: ty, $lanes: expr, $int: ty, $bool: ty, $($i: ident),*;)*) => ($(
636 impl_int_simd!($t, $elt, $lanes, $bool $(, $i)*;);
637
638 impl SimdSigned for AutoSimd<$t> {
642 #[inline(always)]
643 fn simd_abs(&self) -> Self {
644 self.map(|x| x.simd_abs())
645 }
646
647 #[inline(always)]
648 fn simd_abs_sub(&self, other: &Self) -> Self {
649 self.zip_map(*other, |x, y| x.simd_abs_sub(&y))
650 }
651
652 #[inline(always)]
653 fn simd_signum(&self) -> Self {
654 self.map(|x| x.simd_signum())
655 }
656
657 #[inline(always)]
658 fn is_simd_positive(&self) -> Self::SimdBool {
659 self.map_bool(|x| x.is_simd_positive())
660 }
661
662 #[inline(always)]
663 fn is_simd_negative(&self) -> Self::SimdBool {
664 self.map_bool(|x| x.is_simd_negative())
665 }
666 }
667
668 impl Field for AutoSimd<$t> {}
669
670 #[cfg(any(feature = "std", feature = "libm", feature = "libm_force", all(any(target_arch = "nvptx", target_arch = "nvptx64"), feature = "cuda")))]
671 impl SimdRealField for AutoSimd<$t> {
672 #[inline(always)]
673 fn simd_atan2(self, other: Self) -> Self {
674 self.zip_map(other, |x, y| x.simd_atan2(y))
675 }
676
677 #[inline(always)]
678 fn simd_copysign(self, sign: Self) -> Self {
679 self.zip_map(sign, |me, sgn| me.simd_copysign(sgn))
680 }
681
682 #[inline(always)]
683 fn simd_default_epsilon() -> Self {
684 Self::splat(<$elt>::default_epsilon())
685 }
686
687 #[inline(always)]
688 fn simd_pi() -> Self {
689 Self::splat(<$elt>::simd_pi())
690 }
691
692 #[inline(always)]
693 fn simd_two_pi() -> Self {
694 Self::splat(<$elt>::simd_two_pi())
695 }
696
697 #[inline(always)]
698 fn simd_frac_pi_2() -> Self {
699 Self::splat(<$elt>::simd_frac_pi_2())
700 }
701
702 #[inline(always)]
703 fn simd_frac_pi_3() -> Self {
704 Self::splat(<$elt>::simd_frac_pi_3())
705 }
706
707 #[inline(always)]
708 fn simd_frac_pi_4() -> Self {
709 Self::splat(<$elt>::simd_frac_pi_4())
710 }
711
712 #[inline(always)]
713 fn simd_frac_pi_6() -> Self {
714 Self::splat(<$elt>::simd_frac_pi_6())
715 }
716
717 #[inline(always)]
718 fn simd_frac_pi_8() -> Self {
719 Self::splat(<$elt>::simd_frac_pi_8())
720 }
721
722 #[inline(always)]
723 fn simd_frac_1_pi() -> Self {
724 Self::splat(<$elt>::simd_frac_1_pi())
725 }
726
727 #[inline(always)]
728 fn simd_frac_2_pi() -> Self {
729 Self::splat(<$elt>::simd_frac_2_pi())
730 }
731
732 #[inline(always)]
733 fn simd_frac_2_sqrt_pi() -> Self {
734 Self::splat(<$elt>::simd_frac_2_sqrt_pi())
735 }
736
737
738 #[inline(always)]
739 fn simd_e() -> Self {
740 Self::splat(<$elt>::simd_e())
741 }
742
743 #[inline(always)]
744 fn simd_log2_e() -> Self {
745 Self::splat(<$elt>::simd_log2_e())
746 }
747
748 #[inline(always)]
749 fn simd_log10_e() -> Self {
750 Self::splat(<$elt>::simd_log10_e() )
751 }
752
753 #[inline(always)]
754 fn simd_ln_2() -> Self {
755 Self::splat(<$elt>::simd_ln_2())
756 }
757
758 #[inline(always)]
759 fn simd_ln_10() -> Self {
760 Self::splat(<$elt>::simd_ln_10())
761 }
762 }
763
764 #[cfg(any(feature = "std", feature = "libm", feature = "libm_force", all(any(target_arch = "nvptx", target_arch = "nvptx64"), feature = "cuda")))]
765 impl SimdComplexField for AutoSimd<$t> {
766 type SimdRealField = Self;
767
768 #[inline(always)]
769 fn simd_horizontal_sum(self) -> Self::Element {
770 self.0.iter().sum()
771 }
772
773 #[inline(always)]
774 fn simd_horizontal_product(self) -> Self::Element {
775 self.0.iter().product()
776 }
777
778 #[inline(always)]
779 fn from_simd_real(re: Self::SimdRealField) -> Self {
780 re
781 }
782
783 #[inline(always)]
784 fn simd_real(self) -> Self::SimdRealField {
785 self
786 }
787
788 #[inline(always)]
789 fn simd_imaginary(self) -> Self::SimdRealField {
790 Self::zero()
791 }
792
793 #[inline(always)]
794 fn simd_norm1(self) -> Self::SimdRealField {
795 self.map(|x| x.simd_norm1())
796 }
797
798 #[inline(always)]
799 fn simd_modulus(self) -> Self::SimdRealField {
800 self.map(|x| x.simd_modulus())
801 }
802
803 #[inline(always)]
804 fn simd_modulus_squared(self) -> Self::SimdRealField {
805 self.map(|x| x.simd_modulus_squared())
806 }
807
808 #[inline(always)]
809 fn simd_argument(self) -> Self::SimdRealField {
810 self.map(|x| x.simd_argument())
811 }
812
813 #[inline(always)]
814 fn simd_to_exp(self) -> (Self::SimdRealField, Self) {
815 let ge = self.simd_ge(Self::one());
816 let exp = Self::one().select(ge, -Self::one());
817 (self * exp, exp)
818 }
819
820 #[inline(always)]
821 fn simd_recip(self) -> Self {
822 self.map(|x| x.simd_recip())
823 }
824
825 #[inline(always)]
826 fn simd_conjugate(self) -> Self {
827 self.map(|x| x.simd_conjugate())
828 }
829
830 #[inline(always)]
831 fn simd_scale(self, factor: Self::SimdRealField) -> Self {
832 self.zip_map(factor, |x, y| x.simd_scale(y))
833 }
834
835 #[inline(always)]
836 fn simd_unscale(self, factor: Self::SimdRealField) -> Self {
837 self.zip_map(factor, |x, y| x.simd_unscale(y))
838 }
839
840 #[inline(always)]
841 fn simd_floor(self) -> Self {
842 self.map(|e| e.simd_floor())
843 }
844
845 #[inline(always)]
846 fn simd_ceil(self) -> Self {
847 self.map(|e| e.simd_ceil())
848 }
849
850 #[inline(always)]
851 fn simd_round(self) -> Self {
852 self.map(|e| e.simd_round())
853 }
854
855 #[inline(always)]
856 fn simd_trunc(self) -> Self {
857 self.map(|e| e.simd_trunc())
858 }
859
860 #[inline(always)]
861 fn simd_fract(self) -> Self {
862 self.map(|e| e.simd_fract())
863 }
864
865 #[inline(always)]
866 fn simd_abs(self) -> Self {
867 self.map(|e| e.simd_abs())
868 }
869
870 #[inline(always)]
871 fn simd_signum(self) -> Self {
872 self.map(|e| e.simd_signum())
873 }
874
875 #[inline(always)]
876 fn simd_mul_add(self, a: Self, b: Self) -> Self {
877 self.zip_zip_map(a, b, |x, y, z| x.simd_mul_add(y, z))
878 }
879
880 #[inline(always)]
881 fn simd_powi(self, n: i32) -> Self {
882 self.map(|e| e.simd_powi(n))
883 }
884
885 #[inline(always)]
886 fn simd_powf(self, n: Self) -> Self {
887 self.zip_map(n, |x, y| x.simd_powf(y))
888 }
889
890 #[inline(always)]
891 fn simd_powc(self, n: Self) -> Self {
892 self.zip_map(n, |x, y| x.simd_powc(y))
893 }
894
895 #[inline(always)]
896 fn simd_sqrt(self) -> Self {
897 self.map(|x| x.simd_sqrt())
898 }
899
900 #[inline(always)]
901 fn simd_exp(self) -> Self {
902 self.map(|x| x.simd_exp())
903 }
904
905 #[inline(always)]
906 fn simd_exp2(self) -> Self {
907 self.map(|x| x.simd_exp2())
908 }
909
910
911 #[inline(always)]
912 fn simd_exp_m1(self) -> Self {
913 self.map(|x| x.simd_exp_m1())
914 }
915
916 #[inline(always)]
917 fn simd_ln_1p(self) -> Self {
918 self.map(|x| x.simd_ln_1p())
919 }
920
921 #[inline(always)]
922 fn simd_ln(self) -> Self {
923 self.map(|x| x.simd_ln())
924 }
925
926 #[inline(always)]
927 fn simd_log(self, base: Self) -> Self {
928 self.zip_map(base, |x, y| x.simd_log(y))
929 }
930
931 #[inline(always)]
932 fn simd_log2(self) -> Self {
933 self.map(|x| x.simd_log2())
934 }
935
936 #[inline(always)]
937 fn simd_log10(self) -> Self {
938 self.map(|x| x.simd_log10())
939 }
940
941 #[inline(always)]
942 fn simd_cbrt(self) -> Self {
943 self.map(|x| x.simd_cbrt())
944 }
945
946 #[inline(always)]
947 fn simd_hypot(self, other: Self) -> Self::SimdRealField {
948 self.zip_map(other, |x, y| x.simd_hypot(y))
949 }
950
951 #[inline(always)]
952 fn simd_sin(self) -> Self {
953 self.map(|x| x.simd_sin())
954 }
955
956 #[inline(always)]
957 fn simd_cos(self) -> Self {
958 self.map(|x| x.simd_cos())
959 }
960
961 #[inline(always)]
962 fn simd_tan(self) -> Self {
963 self.map(|x| x.simd_tan())
964 }
965
966 #[inline(always)]
967 fn simd_asin(self) -> Self {
968 self.map(|x| x.simd_asin())
969 }
970
971 #[inline(always)]
972 fn simd_acos(self) -> Self {
973 self.map(|x| x.simd_acos())
974 }
975
976 #[inline(always)]
977 fn simd_atan(self) -> Self {
978 self.map(|x| x.simd_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(|x| x.simd_sinh())
999 }
1000
1001 #[inline(always)]
1002 fn simd_cosh(self) -> Self {
1003 self.map(|x| x.simd_cosh())
1004 }
1005
1006 #[inline(always)]
1007 fn simd_tanh(self) -> Self {
1008 self.map(|x| x.simd_tanh())
1009 }
1010
1011 #[inline(always)]
1012 fn simd_asinh(self) -> Self {
1013 self.map(|x| x.simd_asinh())
1014 }
1015
1016 #[inline(always)]
1017 fn simd_acosh(self) -> Self {
1018 self.map(|x| x.simd_acosh())
1019 }
1020
1021 #[inline(always)]
1022 fn simd_atanh(self) -> Self {
1023 self.map(|x| x.simd_atanh())
1024 }
1025 }
1026
1027 #[cfg(any(feature = "std", feature = "libm", feature = "libm_force", all(any(target_arch = "nvptx", target_arch = "nvptx64"), feature = "cuda")))]
1031 impl SimdComplexField for num_complex::Complex<AutoSimd<$t>> {
1032 type SimdRealField = AutoSimd<$t>;
1033
1034 #[inline(always)]
1035 fn simd_horizontal_sum(self) -> Self::Element {
1036 num_complex::Complex::new(self.re.simd_horizontal_sum(), self.im.simd_horizontal_sum())
1037 }
1038
1039 #[inline(always)]
1040 fn simd_horizontal_product(self) -> Self::Element {
1041 let mut prod = self.extract(0);
1042 for ii in 1..$lanes {
1043 prod = prod * self.extract(ii)
1044 }
1045 prod
1046 }
1047
1048 #[inline]
1049 fn from_simd_real(re: Self::SimdRealField) -> Self {
1050 Self::new(re, Self::SimdRealField::zero())
1051 }
1052
1053 #[inline]
1054 fn simd_real(self) -> Self::SimdRealField {
1055 self.re
1056 }
1057
1058 #[inline]
1059 fn simd_imaginary(self) -> Self::SimdRealField {
1060 self.im
1061 }
1062
1063 #[inline]
1064 fn simd_argument(self) -> Self::SimdRealField {
1065 self.im.simd_atan2(self.re)
1066 }
1067
1068 #[inline]
1069 fn simd_modulus(self) -> Self::SimdRealField {
1070 self.re.simd_hypot(self.im)
1071 }
1072
1073 #[inline]
1074 fn simd_modulus_squared(self) -> Self::SimdRealField {
1075 self.re * self.re + self.im * self.im
1076 }
1077
1078 #[inline]
1079 fn simd_norm1(self) -> Self::SimdRealField {
1080 self.re.simd_abs() + self.im.simd_abs()
1081 }
1082
1083 #[inline]
1084 fn simd_recip(self) -> Self {
1085 Self::one() / self
1086 }
1087
1088 #[inline]
1089 fn simd_conjugate(self) -> Self {
1090 self.conj()
1091 }
1092
1093 #[inline]
1094 fn simd_scale(self, factor: Self::SimdRealField) -> Self {
1095 self * factor
1096 }
1097
1098 #[inline]
1099 fn simd_unscale(self, factor: Self::SimdRealField) -> Self {
1100 self / factor
1101 }
1102
1103 #[inline]
1104 fn simd_floor(self) -> Self {
1105 Self::new(self.re.simd_floor(), self.im.simd_floor())
1106 }
1107
1108 #[inline]
1109 fn simd_ceil(self) -> Self {
1110 Self::new(self.re.simd_ceil(), self.im.simd_ceil())
1111 }
1112
1113 #[inline]
1114 fn simd_round(self) -> Self {
1115 Self::new(self.re.simd_round(), self.im.simd_round())
1116 }
1117
1118 #[inline]
1119 fn simd_trunc(self) -> Self {
1120 Self::new(self.re.simd_trunc(), self.im.simd_trunc())
1121 }
1122
1123 #[inline]
1124 fn simd_fract(self) -> Self {
1125 Self::new(self.re.simd_fract(), self.im.simd_fract())
1126 }
1127
1128 #[inline]
1129 fn simd_mul_add(self, a: Self, b: Self) -> Self {
1130 self * a + b
1131 }
1132
1133 #[inline]
1134 fn simd_abs(self) -> Self::SimdRealField {
1135 self.simd_modulus()
1136 }
1137
1138 #[inline]
1139 fn simd_exp2(self) -> Self {
1140 let _2 = AutoSimd::<$t>::one() + AutoSimd::<$t>::one();
1141 num_complex::Complex::new(_2, AutoSimd::<$t>::zero()).simd_powc(self)
1142 }
1143
1144 #[inline]
1145 fn simd_exp_m1(self) -> Self {
1146 self.simd_exp() - Self::one()
1147 }
1148
1149 #[inline]
1150 fn simd_ln_1p(self) -> Self {
1151 (Self::one() + self).simd_ln()
1152 }
1153
1154 #[inline]
1155 fn simd_log2(self) -> Self {
1156 let _2 = AutoSimd::<$t>::one() + AutoSimd::<$t>::one();
1157 self.simd_log(_2)
1158 }
1159
1160 #[inline]
1161 fn simd_log10(self) -> Self {
1162 let _10 = AutoSimd::<$t>::from_subset(&10.0f64);
1163 self.simd_log(_10)
1164 }
1165
1166 #[inline]
1167 fn simd_cbrt(self) -> Self {
1168 let one_third = AutoSimd::<$t>::from_subset(&(1.0 / 3.0));
1169 self.simd_powf(one_third)
1170 }
1171
1172 #[inline]
1173 fn simd_powi(self, n: i32) -> Self {
1174 let n = AutoSimd::<$t>::from_subset(&(n as f64));
1176 self.simd_powf(n)
1177 }
1178
1179 #[inline]
1190 fn simd_exp(self) -> Self {
1191 simd_complex_from_polar(self.re.simd_exp(), self.im)
1194 }
1195
1196 #[inline]
1204 fn simd_ln(self) -> Self {
1205 let (r, theta) = self.simd_to_polar();
1207 Self::new(r.simd_ln(), theta)
1208 }
1209
1210 #[inline]
1218 fn simd_sqrt(self) -> Self {
1219 let two = AutoSimd::<$t>::one() + AutoSimd::<$t>::one();
1221 let (r, theta) = self.simd_to_polar();
1222 simd_complex_from_polar(r.simd_sqrt(), theta / two)
1223 }
1224
1225 #[inline]
1226 fn simd_hypot(self, b: Self) -> Self::SimdRealField {
1227 (self.simd_modulus_squared() + b.simd_modulus_squared()).simd_sqrt()
1228 }
1229
1230 #[inline]
1232 fn simd_powf(self, exp: Self::SimdRealField) -> Self {
1233 let (r, theta) = self.simd_to_polar();
1236 simd_complex_from_polar(r.simd_powf(exp), theta * exp)
1237 }
1238
1239 #[inline]
1241 fn simd_log(self, base: AutoSimd<$t>) -> Self {
1242 let (r, theta) = self.simd_to_polar();
1246 Self::new(r.simd_log(base), theta / base.simd_ln())
1247 }
1248
1249 #[inline]
1251 fn simd_powc(self, exp: Self) -> Self {
1252 let (r, theta) = self.simd_to_polar();
1264 simd_complex_from_polar(
1265 r.simd_powf(exp.re) * (-exp.im * theta).simd_exp(),
1266 exp.re * theta + exp.im * r.simd_ln(),
1267 )
1268 }
1269
1270 #[inline]
1282 fn simd_sin(self) -> Self {
1283 Self::new(
1285 self.re.simd_sin() * self.im.simd_cosh(),
1286 self.re.simd_cos() * self.im.simd_sinh(),
1287 )
1288 }
1289
1290 #[inline]
1292 fn simd_cos(self) -> Self {
1293 Self::new(
1295 self.re.simd_cos() * self.im.simd_cosh(),
1296 -self.re.simd_sin() * self.im.simd_sinh(),
1297 )
1298 }
1299
1300 #[inline]
1301 fn simd_sin_cos(self) -> (Self, Self) {
1302 let (rsin, rcos) = self.re.simd_sin_cos();
1303 let (isinh, icosh) = self.im.simd_sinh_cosh();
1304 let sin = Self::new(rsin * icosh, rcos * isinh);
1305 let cos = Self::new(rcos * icosh, -rsin * isinh);
1306
1307 (sin, cos)
1308 }
1309
1310 #[inline]
1312 fn simd_tan(self) -> Self {
1313 let (two_re, two_im) = (self.re + self.re, self.im + self.im);
1315 Self::new(two_re.simd_sin(), two_im.simd_sinh()).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(AutoSimd::<$t>::zero(), AutoSimd::<$t>::one() / AutoSimd::<$t>::zero());
1365 } else if self == -i {
1366 return Self::new(AutoSimd::<$t>::zero(), -AutoSimd::<$t>::one() / AutoSimd::<$t>::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()).unscale(two_re.simd_cosh() + two_im.simd_cos())
1408 }
1409
1410 #[inline]
1419 fn simd_asinh(self) -> Self {
1420 let one = Self::one();
1422 (self + (one + self * self).simd_sqrt()).simd_ln()
1423 }
1424
1425 #[inline]
1433 fn simd_acosh(self) -> Self {
1434 let one = Self::one();
1436 let two = one + one;
1437 two * (((self + one) / two).simd_sqrt() + ((self - one) / two).simd_sqrt()).simd_ln()
1438 }
1439
1440 #[inline]
1449 fn simd_atanh(self) -> Self {
1450 let one = Self::one();
1452 let two = one + one;
1453 if self == one {
1454 return Self::new(AutoSimd::<$t>::one() / AutoSimd::<$t>::zero(), AutoSimd::<$t>::zero());
1455 } else if self == -one {
1456 return Self::new(-AutoSimd::<$t>::one() / AutoSimd::<$t>::zero(), AutoSimd::<$t>::zero());
1457 }
1458 ((one + self).simd_ln() - (one - self).simd_ln()) / two
1459 }
1460 }
1461 )*)
1462);
1463
1464#[inline]
1465fn simd_complex_from_polar<N: SimdRealField>(r: N, theta: N) -> num_complex::Complex<N> {
1466 num_complex::Complex::new(r.clone() * theta.clone().simd_cos(), r * theta.simd_sin())
1467}
1468
1469impl_float_simd!(
1470 [f32; 2], f32, 2, [i32; 2], AutoBoolx2, _0, _1;
1471 [f32; 4], f32, 4, [i32; 4], AutoBoolx4, _0, _1, _2, _3;
1472 [f32; 8], f32, 8, [i32; 8], AutoBoolx8, _0, _1, _2, _3, _4, _5, _6, _7;
1473 [f32; 16], f32, 16, [i32; 16], AutoBoolx16, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15;
1474 [f64; 2], f64, 2, [i64; 2], AutoBoolx2, _0, _1;
1475 [f64; 4], f64, 4, [i64; 4], AutoBoolx4, _0, _1, _2, _3;
1476 [f64; 8], f64, 8, [i64; 8], AutoBoolx8, _0, _1, _2, _3, _4, _5, _6, _7;
1477);
1478
1479impl_int_simd!(
1480 [i128; 1], i128, 1, AutoBoolx1, _0;
1481 [i128; 2], i128, 2, AutoBoolx2, _0, _1;
1482 [i128; 4], i128, 4, AutoBoolx4, _0, _1, _2, _3;
1483 [i16; 2], i16, 2, AutoBoolx2, _0, _1;
1484 [i16; 4], i16, 4, AutoBoolx4, _0, _1, _2, _3;
1485 [i16; 8], i16, 8, AutoBoolx8, _0, _1, _2, _3, _4, _5, _6, _7;
1486 [i16; 16], i16, 16, AutoBoolx16, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15;
1487 [i16; 32], i16, 32, AutoBoolx32, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31;
1488 [i32; 2], i32, 2, AutoBoolx2, _0, _1;
1489 [i32; 4], i32, 4, AutoBoolx4, _0, _1, _2, _3;
1490 [i32; 8], i32, 8, AutoBoolx8, _0, _1, _2, _3, _4, _5, _6, _7;
1491 [i32; 16], i32, 16, AutoBoolx16, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15;
1492 [i64; 2], i64, 2, AutoBoolx2, _0, _1;
1493 [i64; 4], i64, 4, AutoBoolx4, _0, _1, _2, _3;
1494 [i64; 8], i64, 8, AutoBoolx8, _0, _1, _2, _3, _4, _5, _6, _7;
1495 [i8; 2], i8, 2, AutoBoolx2, _0, _1;
1496 [i8; 4], i8, 4, AutoBoolx4, _0, _1, _2, _3;
1497 [i8; 8], i8, 8, AutoBoolx8, _0, _1, _2, _3, _4, _5, _6, _7;
1498 [i8; 16], i8, 16, AutoBoolx16, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15;
1499 [i8; 32], i8, 32, AutoBoolx32, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31;
1500 [isize; 2], isize, 2, AutoBoolx2, _0, _1;
1502 [isize; 4], isize, 4, AutoBoolx4, _0, _1, _2, _3;
1503 [isize; 8], isize, 8, AutoBoolx8, _0, _1, _2, _3, _4, _5, _6, _7;
1504);
1505
1506impl_uint_simd!(
1507 [u128; 1], u128, 1, AutoBoolx1, _0;
1508 [u128; 2], u128, 2, AutoBoolx2, _0, _1;
1509 [u128; 4], u128, 4, AutoBoolx4, _0, _1, _2, _3;
1510 [u16; 2], u16, 2, AutoBoolx2, _0, _1;
1511 [u16; 4], u16, 4, AutoBoolx4, _0, _1, _2, _3;
1512 [u16; 8], u16, 8, AutoBoolx8, _0, _1, _2, _3, _4, _5, _6, _7;
1513 [u16; 16], u16, 16, AutoBoolx16, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15;
1514 [u16; 32], u16, 32, AutoBoolx32, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31;
1515 [u32; 2], u32, 2, AutoBoolx2, _0, _1;
1516 [u32; 4], u32, 4, AutoBoolx4, _0, _1, _2, _3;
1517 [u32; 8], u32, 8, AutoBoolx8, _0, _1, _2, _3, _4, _5, _6, _7;
1518 [u32; 16], u32, 16, AutoBoolx16, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15;
1519 [u64; 2], u64, 2, AutoBoolx2, _0, _1;
1520 [u64; 4], u64, 4, AutoBoolx4, _0, _1, _2, _3;
1521 [u64; 8], u64, 8, AutoBoolx8, _0, _1, _2, _3, _4, _5, _6, _7;
1522 [u8; 2], u8, 2, AutoBoolx2, _0, _1;
1523 [u8; 4], u8, 4, AutoBoolx4, _0, _1, _2, _3;
1524 [u8; 8], u8, 8, AutoBoolx8, _0, _1, _2, _3, _4, _5, _6, _7;
1525 [u8; 16], u8, 16, AutoBoolx16, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15;
1526 [u8; 32], u8, 32, AutoBoolx32, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31;
1527 [usize; 2], usize, 2, AutoBoolx2, _0, _1;
1529 [usize; 4], usize, 4, AutoBoolx4, _0, _1, _2, _3;
1530 [usize; 8], usize, 8, AutoBoolx8, _0, _1, _2, _3, _4, _5, _6, _7;
1531);
1532
1533impl_bool_simd!(
1534 [bool; 1], 1, _0;
1535 [bool; 2], 2, _0, _1;
1536 [bool; 4], 4, _0, _1, _2, _3;
1537 [bool; 8], 8, _0, _1, _2, _3, _4, _5, _6, _7;
1538 [bool; 16], 16, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15;
1539 [bool; 32], 32, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31;
1540 );
1542
1543pub type AutoF32x2 = AutoSimd<[f32; 2]>;
1572pub type AutoF32x4 = AutoSimd<[f32; 4]>;
1573pub type AutoF32x8 = AutoSimd<[f32; 8]>;
1574pub type AutoF32x16 = AutoSimd<[f32; 16]>;
1575pub type AutoF64x2 = AutoSimd<[f64; 2]>;
1576pub type AutoF64x4 = AutoSimd<[f64; 4]>;
1577pub type AutoF64x8 = AutoSimd<[f64; 8]>;
1578pub type AutoI128x1 = AutoSimd<[i128; 1]>;
1579pub type AutoI128x2 = AutoSimd<[i128; 2]>;
1580pub type AutoI128x4 = AutoSimd<[i128; 4]>;
1581pub type AutoI16x2 = AutoSimd<[i16; 2]>;
1582pub type AutoI16x4 = AutoSimd<[i16; 4]>;
1583pub type AutoI16x8 = AutoSimd<[i16; 8]>;
1584pub type AutoI16x16 = AutoSimd<[i16; 16]>;
1585pub type AutoI16x32 = AutoSimd<[i16; 32]>;
1586pub type AutoI32x2 = AutoSimd<[i32; 2]>;
1587pub type AutoI32x4 = AutoSimd<[i32; 4]>;
1588pub type AutoI32x8 = AutoSimd<[i32; 8]>;
1589pub type AutoI32x16 = AutoSimd<[i32; 16]>;
1590pub type AutoI64x2 = AutoSimd<[i64; 2]>;
1591pub type AutoI64x4 = AutoSimd<[i64; 4]>;
1592pub type AutoI64x8 = AutoSimd<[i64; 8]>;
1593pub type AutoI8x2 = AutoSimd<[i8; 2]>;
1594pub type AutoI8x4 = AutoSimd<[i8; 4]>;
1595pub type AutoI8x8 = AutoSimd<[i8; 8]>;
1596pub type AutoI8x16 = AutoSimd<[i8; 16]>;
1597pub type AutoI8x32 = AutoSimd<[i8; 32]>;
1598pub type AutoIsizex2 = AutoSimd<[isize; 2]>;
1600pub type AutoIsizex4 = AutoSimd<[isize; 4]>;
1601pub type AutoIsizex8 = AutoSimd<[isize; 8]>;
1602pub type AutoU128x1 = AutoSimd<[u128; 1]>;
1603pub type AutoU128x2 = AutoSimd<[u128; 2]>;
1604pub type AutoU128x4 = AutoSimd<[u128; 4]>;
1605pub type AutoU16x2 = AutoSimd<[u16; 2]>;
1606pub type AutoU16x4 = AutoSimd<[u16; 4]>;
1607pub type AutoU16x8 = AutoSimd<[u16; 8]>;
1608pub type AutoU16x16 = AutoSimd<[u16; 16]>;
1609pub type AutoU16x32 = AutoSimd<[u16; 32]>;
1610pub type AutoU32x2 = AutoSimd<[u32; 2]>;
1611pub type AutoU32x4 = AutoSimd<[u32; 4]>;
1612pub type AutoU32x8 = AutoSimd<[u32; 8]>;
1613pub type AutoU32x16 = AutoSimd<[u32; 16]>;
1614pub type AutoU64x2 = AutoSimd<[u64; 2]>;
1615pub type AutoU64x4 = AutoSimd<[u64; 4]>;
1616pub type AutoU64x8 = AutoSimd<[u64; 8]>;
1617pub type AutoU8x2 = AutoSimd<[u8; 2]>;
1618pub type AutoU8x4 = AutoSimd<[u8; 4]>;
1619pub type AutoU8x8 = AutoSimd<[u8; 8]>;
1620pub type AutoU8x16 = AutoSimd<[u8; 16]>;
1621pub type AutoU8x32 = AutoSimd<[u8; 32]>;
1622pub type AutoUsizex2 = AutoSimd<[usize; 2]>;
1624pub type AutoUsizex4 = AutoSimd<[usize; 4]>;
1625pub type AutoUsizex8 = AutoSimd<[usize; 8]>;
1626
1627pub type AutoBoolx1 = AutoSimd<[bool; 1]>;
1628pub type AutoBoolx16 = AutoSimd<[bool; 16]>;
1629pub type AutoBoolx2 = AutoSimd<[bool; 2]>;
1630pub type AutoBoolx32 = AutoSimd<[bool; 32]>;
1631pub type AutoBoolx4 = AutoSimd<[bool; 4]>;
1632pub type AutoBoolx8 = AutoSimd<[bool; 8]>;
1634
1635trait ArrTransform: SimdValue {
1639 fn map(self, f: impl Fn(Self::Element) -> Self::Element) -> Self;
1640 fn zip_map(
1641 self,
1642 other: Self,
1643 f: impl Fn(Self::Element, Self::Element) -> Self::Element,
1644 ) -> Self;
1645 fn zip_zip_map(
1646 self,
1647 b: Self,
1648 c: Self,
1649 f: impl Fn(Self::Element, Self::Element, Self::Element) -> Self::Element,
1650 ) -> Self;
1651 fn map_bool(self, f: impl Fn(Self::Element) -> bool) -> Self::SimdBool;
1652 fn zip_map_bool(
1653 self,
1654 other: Self,
1655 f: impl Fn(Self::Element, Self::Element) -> bool,
1656 ) -> Self::SimdBool;
1657}