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