1 #![allow(missing_docs)]
2 #![allow(non_camel_case_types)] // For the simd type aliases.
3
4 //! Traits for SIMD values.
5
6 use crate::scalar::{ComplexField, Field, SubsetOf, SupersetOf};
7 use crate::simd::{
8 PrimitiveSimdValue, SimdBool, SimdComplexField, SimdPartialOrd, SimdRealField, SimdSigned,
9 SimdValue,
10 };
11 use approx::AbsDiffEq;
12 #[cfg(feature = "decimal")]
13 use decimal::d128;
14 use num::{FromPrimitive, Num, One, Zero};
15 use 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
23 // This is a hack to allow use to reuse `_0` as integers or as identifier,
24 // depending on whether or not `ident_to_value` has been called in scope.
25 // This helps writing macros that define both `::new` and `From([T; lanes()])`.
26 macro_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 /// An Simd structure that implements all the relevant traits from `num` an `simba`.
40 ///
41 /// This is needed to overcome the orphan rules.
42 #[repr(transparent)]
43 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
44 pub struct Simd<N>(pub N);
45
46 macro_rules! impl_bool_simd(
47 ($($t: ty, $($i: ident),*;)*) => {$(
48 impl_simd_value!($t, bool, Simd<$t> $(, $i)*;);
49
50 impl From<[bool; <$t>::lanes()]> for Simd<$t> {
51 #[inline(always)]
52 fn from(vals: [bool; <$t>::lanes()]) -> Self {
53 ident_to_value!();
54 Simd(<$t>::new($(vals[$i]),*))
55 }
56 }
57
58 impl Not for Simd<$t> {
59 type Output = Self;
60
61 #[inline]
62 fn not(self) -> Self {
63 Self(!self.0)
64 }
65 }
66
67 impl BitAnd<Simd<$t>> for Simd<$t> {
68 type Output = Self;
69 fn bitand(self, rhs: Self) -> Self {
70 Simd(self.0.bitand(rhs.0))
71 }
72 }
73
74 impl BitOr<Simd<$t>> for Simd<$t> {
75 type Output = Self;
76 fn bitor(self, rhs: Self) -> Self {
77 Simd(self.0.bitor(rhs.0))
78 }
79 }
80
81 impl BitXor<Simd<$t>> for Simd<$t> {
82 type Output = Self;
83 fn bitxor(self, rhs: Self) -> Self {
84 Simd(self.0.bitxor(rhs.0))
85 }
86 }
87
88 impl SimdBool for Simd<$t> {
89 #[inline(always)]
90 fn bitmask(self) -> u64 {
91 self.0.bitmask() as u64
92 }
93
94 #[inline(always)]
95 fn and(self) -> bool {
96 self.0.and()
97 }
98
99 #[inline(always)]
100 fn or(self) -> bool {
101 self.0.or()
102 }
103
104 #[inline(always)]
105 fn xor(self) -> bool {
106 self.0.xor()
107 }
108
109 #[inline(always)]
110 fn all(self) -> bool {
111 self.0.all()
112 }
113
114 #[inline(always)]
115 fn any(self) -> bool {
116 self.0.any()
117 }
118
119 #[inline(always)]
120 fn none(self) -> bool {
121 self.0.none()
122 }
123
124 #[inline(always)]
125 fn if_else<Res: SimdValue<SimdBool = Self>>(
126 self,
127 if_value: impl FnOnce() -> Res,
128 else_value: impl FnOnce() -> Res,
129 ) -> Res {
130 let a = if_value();
131 let b = else_value();
132 a.select(self, b)
133 }
134
135 #[inline(always)]
136 fn if_else2<Res: SimdValue<SimdBool = Self>>(
137 self,
138 if_value: impl FnOnce() -> Res,
139 else_if: (impl FnOnce() -> Self, impl FnOnce() -> Res),
140 else_value: impl FnOnce() -> Res,
141 ) -> Res {
142 let a = if_value();
143 let b = else_if.1();
144 let c = else_value();
145
146 let cond_a = self;
147 let cond_b = else_if.0();
148
149 a.select(cond_a, b.select(cond_b, c))
150 }
151
152 #[inline(always)]
153 fn if_else3<Res: SimdValue<SimdBool = Self>>(
154 self,
155 if_value: impl FnOnce() -> Res,
156 else_if: (impl FnOnce() -> Self, impl FnOnce() -> Res),
157 else_else_if: (impl FnOnce() -> Self, impl FnOnce() -> Res),
158 else_value: impl FnOnce() -> Res,
159 ) -> Res {
160 let a = if_value();
161 let b = else_if.1();
162 let c = else_else_if.1();
163 let d = else_value();
164
165 let cond_a = self;
166 let cond_b = else_if.0();
167 let cond_c = else_else_if.0();
168
169 a.select(cond_a, b.select(cond_b, c.select(cond_c, d)))
170 }
171 }
172 )*}
173 );
174
175 macro_rules! impl_scalar_subset_of_simd(
176 ($($t: ty),*) => {$(
177 impl<N2> SubsetOf<Simd<N2>> for $t
178 where Simd<N2>: SimdValue + Copy,
179 <Simd<N2> as SimdValue>::Element: SupersetOf<$t> + PartialEq, {
180 #[inline(always)]
181 fn to_superset(&self) -> Simd<N2> {
182 Simd::<N2>::splat(<Simd<N2> as SimdValue>::Element::from_subset(self))
183 }
184
185 #[inline(always)]
186 fn from_superset_unchecked(element: &Simd<N2>) -> $t {
187 element.extract(0).to_subset_unchecked()
188 }
189
190 #[inline(always)]
191 fn is_in_subset(c: &Simd<N2>) -> bool {
192 let elt0 = c.extract(0);
193 elt0.is_in_subset() &&
194 (1..Simd::<N2>::lanes()).all(|i| c.extract(i) == elt0)
195 }
196 }
197 )*}
198 );
199
200 impl_scalar_subset_of_simd!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, f32, f64);
201 #[cfg(feature = "decimal")]
202 impl_scalar_subset_of_simd!(d128);
203
204 macro_rules! impl_simd_value(
205 ($($t: ty, $elt: ty, $bool: ty, $($i: ident),*;)*) => ($(
206 impl fmt::Display for Simd<$t> {
207 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
208 if Self::lanes() == 1 {
209 return self.extract(0).fmt(f);
210 }
211
212 write!(f, "({}", self.extract(0))?;
213
214 for i in 1..Self::lanes() {
215 write!(f, ", {}", self.extract(i))?;
216 }
217
218 write!(f, ")")
219 }
220 }
221
222 impl Simd<$t> {
223 #[inline]
224 pub fn new($($i: $elt),*) -> Self {
225 Simd(<$t>::new($($i),*))
226 }
227 }
228
229 impl PrimitiveSimdValue for Simd<$t> {}
230
231 impl SimdValue for Simd<$t> {
232 type Element = $elt;
233 type SimdBool = $bool;
234
235 #[inline(always)]
236 fn lanes() -> usize {
237 <$t>::lanes()
238 }
239
240 #[inline(always)]
241 fn splat(val: Self::Element) -> Self {
242 Simd(<$t>::splat(val))
243 }
244
245 #[inline(always)]
246 fn extract(&self, i: usize) -> Self::Element {
247 <$t>::extract(self.0, i)
248 }
249
250 #[inline(always)]
251 unsafe fn extract_unchecked(&self, i: usize) -> Self::Element {
252 <$t>::extract_unchecked(self.0, i)
253 }
254
255 #[inline(always)]
256 fn replace(&mut self, i: usize, val: Self::Element) {
257 *self = Simd(<$t>::replace(self.0, i, val))
258 }
259
260 #[inline(always)]
261 unsafe fn replace_unchecked(&mut self, i: usize, val: Self::Element) {
262 *self = Simd(<$t>::replace_unchecked(self.0, i, val))
263 }
264
265 #[inline(always)]
266 fn select(self, cond: Self::SimdBool, other: Self) -> Self {
267 Self(cond.0.select(self.0, other.0))
268 }
269 }
270 )*)
271 );
272
273 macro_rules! impl_uint_simd(
274 ($($t: ty, $elt: ty, $bool: ty, $($i: ident),*;)*) => ($(
275 impl_simd_value!($t, $elt, $bool $(, $i)*;);
276
277 impl Simd<$t> {
278 /// Instantiates a new vector with the values of the `slice`.
279 ///
280 /// # Panics
281 ///
282 /// If `slice.len() < Self::lanes()`.
283 #[inline]
284 pub fn from_slice_unaligned(slice: &[$elt]) -> Self {
285 Simd(<$t>::from_slice_unaligned(slice))
286 }
287 }
288
289 impl From<[$elt; <$t>::lanes()]> for Simd<$t> {
290 #[inline(always)]
291 fn from(vals: [$elt; <$t>::lanes()]) -> Self {
292 Simd(<$t>::from(vals))
293 }
294 }
295
296 impl From<Simd<$t>> for [$elt; <$t>::lanes()] {
297 #[inline(always)]
298 fn from(val: Simd<$t>) -> [$elt; <$t>::lanes()] {
299 let mut res = [<$elt>::zero(); <$t>::lanes()];
300 val.0.write_to_slice_unaligned(&mut res[..]);
301 res
302 }
303 }
304
305 impl SubsetOf<Simd<$t>> for Simd<$t> {
306 #[inline(always)]
307 fn to_superset(&self) -> Self {
308 *self
309 }
310
311 #[inline(always)]
312 fn from_superset(element: &Self) -> Option<Self> {
313 Some(*element)
314 }
315
316 #[inline(always)]
317 fn from_superset_unchecked(element: &Self) -> Self {
318 *element
319 }
320
321 #[inline(always)]
322 fn is_in_subset(_: &Self) -> bool {
323 true
324 }
325 }
326
327 impl Num for Simd<$t> {
328 type FromStrRadixErr = <$elt as Num>::FromStrRadixErr;
329
330 #[inline(always)]
331 fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
332 <$elt>::from_str_radix(str, radix).map(Self::splat)
333 }
334 }
335
336 impl FromPrimitive for Simd<$t> {
337 #[inline(always)]
338 fn from_i64(n: i64) -> Option<Self> {
339 <$elt>::from_i64(n).map(Self::splat)
340 }
341
342 #[inline(always)]
343 fn from_u64(n: u64) -> Option<Self> {
344 <$elt>::from_u64(n).map(Self::splat)
345 }
346
347 #[inline(always)]
348 fn from_isize(n: isize) -> Option<Self> {
349 <$elt>::from_isize(n).map(Self::splat)
350 }
351
352 #[inline(always)]
353 fn from_i8(n: i8) -> Option<Self> {
354 <$elt>::from_i8(n).map(Self::splat)
355 }
356
357 #[inline(always)]
358 fn from_i16(n: i16) -> Option<Self> {
359 <$elt>::from_i16(n).map(Self::splat)
360 }
361
362 #[inline(always)]
363 fn from_i32(n: i32) -> Option<Self> {
364 <$elt>::from_i32(n).map(Self::splat)
365 }
366
367 #[inline(always)]
368 fn from_usize(n: usize) -> Option<Self> {
369 <$elt>::from_usize(n).map(Self::splat)
370 }
371
372 #[inline(always)]
373 fn from_u8(n: u8) -> Option<Self> {
374 <$elt>::from_u8(n).map(Self::splat)
375 }
376
377 #[inline(always)]
378 fn from_u16(n: u16) -> Option<Self> {
379 <$elt>::from_u16(n).map(Self::splat)
380 }
381
382 #[inline(always)]
383 fn from_u32(n: u32) -> Option<Self> {
384 <$elt>::from_u32(n).map(Self::splat)
385 }
386
387 #[inline(always)]
388 fn from_f32(n: f32) -> Option<Self> {
389 <$elt>::from_f32(n).map(Self::splat)
390 }
391
392 #[inline(always)]
393 fn from_f64(n: f64) -> Option<Self> {
394 <$elt>::from_f64(n).map(Self::splat)
395 }
396 }
397
398
399 impl Zero for Simd<$t> {
400 #[inline(always)]
401 fn zero() -> Self {
402 Simd(<$t>::splat(<$elt>::zero()))
403 }
404
405 #[inline(always)]
406 fn is_zero(&self) -> bool {
407 *self == Self::zero()
408 }
409 }
410
411 impl One for Simd<$t> {
412 #[inline(always)]
413 fn one() -> Self {
414 Simd(<$t>::splat(<$elt>::one()))
415 }
416 }
417
418 impl Add<Simd<$t>> for Simd<$t> {
419 type Output = Self;
420
421 #[inline(always)]
422 fn add(self, rhs: Self) -> Self {
423 Self(self.0 + rhs.0)
424 }
425 }
426
427 impl Sub<Simd<$t>> for Simd<$t> {
428 type Output = Self;
429
430 #[inline(always)]
431 fn sub(self, rhs: Self) -> Self {
432 Self(self.0 - rhs.0)
433 }
434 }
435
436 impl Mul<Simd<$t>> for Simd<$t> {
437 type Output = Self;
438
439 #[inline(always)]
440 fn mul(self, rhs: Self) -> Self {
441 Self(self.0 * rhs.0)
442 }
443 }
444
445 impl Div<Simd<$t>> for Simd<$t> {
446 type Output = Self;
447
448 #[inline(always)]
449 fn div(self, rhs: Self) -> Self {
450 Self(self.0 / rhs.0)
451 }
452 }
453
454 impl Rem<Simd<$t>> for Simd<$t> {
455 type Output = Self;
456
457 #[inline(always)]
458 fn rem(self, rhs: Self) -> Self {
459 Self(self.0 % rhs.0)
460 }
461 }
462
463 impl AddAssign<Simd<$t>> for Simd<$t> {
464 #[inline(always)]
465 fn add_assign(&mut self, rhs: Self) {
466 self.0 += rhs.0
467 }
468 }
469
470 impl SubAssign<Simd<$t>> for Simd<$t> {
471 #[inline(always)]
472 fn sub_assign(&mut self, rhs: Self) {
473 self.0 -= rhs.0
474 }
475 }
476
477 impl DivAssign<Simd<$t>> for Simd<$t> {
478 #[inline(always)]
479 fn div_assign(&mut self, rhs: Self) {
480 self.0 /= rhs.0
481 }
482 }
483
484 impl MulAssign<Simd<$t>> for Simd<$t> {
485 #[inline(always)]
486 fn mul_assign(&mut self, rhs: Self) {
487 self.0 *= rhs.0
488 }
489 }
490
491 impl RemAssign<Simd<$t>> for Simd<$t> {
492 #[inline(always)]
493 fn rem_assign(&mut self, rhs: Self) {
494 self.0 %= rhs.0
495 }
496 }
497
498 impl SimdPartialOrd for Simd<$t> {
499 #[inline(always)]
500 fn simd_gt(self, other: Self) -> Self::SimdBool {
501 Simd(self.0.gt(other.0))
502 }
503
504 #[inline(always)]
505 fn simd_lt(self, other: Self) -> Self::SimdBool {
506 Simd(self.0.lt(other.0))
507 }
508
509 #[inline(always)]
510 fn simd_ge(self, other: Self) -> Self::SimdBool {
511 Simd(self.0.ge(other.0))
512 }
513
514 #[inline(always)]
515 fn simd_le(self, other: Self) -> Self::SimdBool {
516 Simd(self.0.le(other.0))
517 }
518
519 #[inline(always)]
520 fn simd_eq(self, other: Self) -> Self::SimdBool {
521 Simd(self.0.eq(other.0))
522 }
523
524 #[inline(always)]
525 fn simd_ne(self, other: Self) -> Self::SimdBool {
526 Simd(self.0.ne(other.0))
527 }
528
529 #[inline(always)]
530 fn simd_max(self, other: Self) -> Self {
531 Simd(self.0.max(other.0))
532 }
533 #[inline(always)]
534 fn simd_min(self, other: Self) -> Self {
535 Simd(self.0.min(other.0))
536 }
537
538 #[inline(always)]
539 fn simd_clamp(self, min: Self, max: Self) -> Self {
540 self.simd_max(min).simd_min(max)
541 }
542
543 #[inline(always)]
544 fn simd_horizontal_min(self) -> Self::Element {
545 self.0.min_element()
546 }
547
548 #[inline(always)]
549 fn simd_horizontal_max(self) -> Self::Element {
550 self.0.max_element()
551 }
552 }
553
554 // impl MeetSemilattice for Simd<$t> {
555 // #[inline(always)]
556 // fn meet(&self, other: &Self) -> Self {
557 // Simd(self.0.min(other.0))
558 // }
559 // }
560 //
561 // impl JoinSemilattice for Simd<$t> {
562 // #[inline(always)]
563 // fn join(&self, other: &Self) -> Self {
564 // Simd(self.0.max(other.0))
565 // }
566 // }
567 )*)
568 );
569
570 macro_rules! impl_int_simd(
571 ($($t: ty, $elt: ty, $bool: ty, $($i: ident),*;)*) => ($(
572 impl_uint_simd!($t, $elt, $bool $(, $i)*;);
573
574 impl Neg for Simd<$t> {
575 type Output = Self;
576
577 #[inline(always)]
578 fn neg(self) -> Self {
579 Self(-self.0)
580 }
581 }
582 )*)
583 );
584
585 macro_rules! impl_float_simd(
586 ($($t: ty, $elt: ty, $int: ty, $bool: ty, $($i: ident),*;)*) => ($(
587 impl_int_simd!($t, $elt, $bool $(, $i)*;);
588
589 // FIXME: this should be part of impl_int_simd
590 // but those methods do not seem to be implemented
591 // by packed_simd for integers.
592 impl SimdSigned for Simd<$t> {
593 #[inline(always)]
594 fn simd_abs(&self) -> Self {
595 Simd(self.0.abs())
596 }
597
598 #[inline(always)]
599 fn simd_abs_sub(&self, other: &Self) -> Self {
600 Simd((self.0 - other.0).max(Self::zero().0))
601 }
602
603 #[inline(always)]
604 fn simd_signum(&self) -> Self {
605 // NOTE: is there a more efficient way of doing this?
606 let zero = Self::zero().0;
607 let one = Self::one().0;
608 let gt = self.0.gt(zero);
609 let lt = self.0.lt(zero);
610 Simd(lt.select(-one, gt.select(one, zero)))
611 }
612
613 #[inline(always)]
614 fn is_simd_positive(&self) -> Self::SimdBool {
615 self.simd_gt(Self::zero())
616 }
617
618 #[inline(always)]
619 fn is_simd_negative(&self) -> Self::SimdBool {
620 self.simd_lt(Self::zero())
621 }
622 }
623
624 impl Field for Simd<$t> {}
625
626 impl SimdRealField for Simd<$t> {
627 #[inline(always)]
628 fn simd_atan2(self, other: Self) -> Self {
629 self.zip_map_lanes(other, |a, b| a.atan2(b))
630 }
631
632 #[inline(always)]
633 fn simd_copysign(self, sign: Self) -> Self {
634 use packed_simd::FromBits;
635 let sign_bits = <$int>::from_bits(<$t>::splat(-0.0));
636 let ref_bits = <$int>::from_bits(sign.0);
637 let self_bits = <$int>::from_bits(self.0);
638 let result =
639 <$t>::from_bits((sign_bits & ref_bits) | ((!sign_bits) & self_bits));
640 Simd(result)
641 }
642
643 #[inline(always)]
644 fn simd_default_epsilon() -> Self {
645 Self::splat(<$elt>::default_epsilon())
646 }
647
648 #[inline(always)]
649 fn simd_pi() -> Self {
650 Simd(<$t>::PI)
651 }
652
653 #[inline(always)]
654 fn simd_two_pi() -> Self {
655 Simd(<$t>::PI + <$t>::PI)
656 }
657
658 #[inline(always)]
659 fn simd_frac_pi_2() -> Self {
660 Simd(<$t>::FRAC_PI_2)
661 }
662
663 #[inline(always)]
664 fn simd_frac_pi_3() -> Self {
665 Simd(<$t>::FRAC_PI_3)
666 }
667
668 #[inline(always)]
669 fn simd_frac_pi_4() -> Self {
670 Simd(<$t>::FRAC_PI_4)
671 }
672
673 #[inline(always)]
674 fn simd_frac_pi_6() -> Self {
675 Simd(<$t>::FRAC_PI_6)
676 }
677
678 #[inline(always)]
679 fn simd_frac_pi_8() -> Self {
680 Simd(<$t>::FRAC_PI_8)
681 }
682
683 #[inline(always)]
684 fn simd_frac_1_pi() -> Self {
685 Simd(<$t>::FRAC_1_PI)
686 }
687
688 #[inline(always)]
689 fn simd_frac_2_pi() -> Self {
690 Simd(<$t>::FRAC_2_PI)
691 }
692
693 #[inline(always)]
694 fn simd_frac_2_sqrt_pi() -> Self {
695 Simd(<$t>::FRAC_2_SQRT_PI)
696 }
697
698
699 #[inline(always)]
700 fn simd_e() -> Self {
701 Simd(<$t>::E)
702 }
703
704 #[inline(always)]
705 fn simd_log2_e() -> Self {
706 Simd(<$t>::LOG2_E)
707 }
708
709 #[inline(always)]
710 fn simd_log10_e() -> Self {
711 Simd(<$t>::LOG10_E)
712 }
713
714 #[inline(always)]
715 fn simd_ln_2() -> Self {
716 Simd(<$t>::LN_2)
717 }
718
719 #[inline(always)]
720 fn simd_ln_10() -> Self {
721 Simd(<$t>::LN_10)
722 }
723 }
724
725 impl SimdComplexField for Simd<$t> {
726 type SimdRealField = Self;
727
728 #[inline(always)]
729 fn simd_horizontal_sum(self) -> Self::Element {
730 self.0.sum()
731 }
732
733 #[inline(always)]
734 fn simd_horizontal_product(self) -> Self::Element {
735 self.0.product()
736 }
737
738 #[inline(always)]
739 fn from_simd_real(re: Self::SimdRealField) -> Self {
740 re
741 }
742
743 #[inline(always)]
744 fn simd_real(self) -> Self::SimdRealField {
745 self
746 }
747
748 #[inline(always)]
749 fn simd_imaginary(self) -> Self::SimdRealField {
750 Self::zero()
751 }
752
753 #[inline(always)]
754 fn simd_norm1(self) -> Self::SimdRealField {
755 Simd(self.0.abs())
756 }
757
758 #[inline(always)]
759 fn simd_modulus(self) -> Self::SimdRealField {
760 Simd(self.0.abs())
761 }
762
763 #[inline(always)]
764 fn simd_modulus_squared(self) -> Self::SimdRealField {
765 self * self
766 }
767
768 #[inline(always)]
769 fn simd_argument(self) -> Self::SimdRealField {
770 self.map_lanes(|e| e.argument())
771 }
772
773 #[inline(always)]
774 fn simd_to_exp(self) -> (Self::SimdRealField, Self) {
775 let ge = self.0.ge(Self::one().0);
776 let exp = ge.select(Self::one().0, -Self::one().0);
777 (Simd(self.0 * exp), Simd(exp))
778 }
779
780 #[inline(always)]
781 fn simd_recip(self) -> Self {
782 Self::one() / self
783 }
784
785 #[inline(always)]
786 fn simd_conjugate(self) -> Self {
787 self
788 }
789
790 #[inline(always)]
791 fn simd_scale(self, factor: Self::SimdRealField) -> Self {
792 Simd(self.0 * factor.0)
793 }
794
795 #[inline(always)]
796 fn simd_unscale(self, factor: Self::SimdRealField) -> Self {
797 Simd(self.0 / factor.0)
798 }
799
800 #[inline(always)]
801 fn simd_floor(self) -> Self {
802 self.map_lanes(|e| e.floor())
803 }
804
805 #[inline(always)]
806 fn simd_ceil(self) -> Self {
807 self.map_lanes(|e| e.ceil())
808 }
809
810 #[inline(always)]
811 fn simd_round(self) -> Self {
812 self.map_lanes(|e| e.round())
813 }
814
815 #[inline(always)]
816 fn simd_trunc(self) -> Self {
817 self.map_lanes(|e| e.trunc())
818 }
819
820 #[inline(always)]
821 fn simd_fract(self) -> Self {
822 self.map_lanes(|e| e.fract())
823 }
824
825 #[inline(always)]
826 fn simd_abs(self) -> Self {
827 Simd(self.0.abs())
828 }
829
830 #[inline(always)]
831 fn simd_signum(self) -> Self {
832 self.map_lanes(|e| e.signum())
833 }
834
835 #[inline(always)]
836 fn simd_mul_add(self, a: Self, b: Self) -> Self {
837 Simd(self.0.mul_add(a.0, b.0))
838 }
839
840 #[inline(always)]
841 fn simd_powi(self, n: i32) -> Self {
842 Simd(self.0.powf(<$t>::splat(n as $elt)))
843 }
844
845 #[inline(always)]
846 fn simd_powf(self, n: Self) -> Self {
847 Simd(self.0.powf(n.0))
848 }
849
850 #[inline(always)]
851 fn simd_powc(self, n: Self) -> Self {
852 Simd(self.0.powf(n.0))
853 }
854
855 #[inline(always)]
856 fn simd_sqrt(self) -> Self {
857 Simd(self.0.sqrt())
858 }
859
860 #[inline(always)]
861 fn simd_exp(self) -> Self {
862 Simd(self.0.exp())
863 }
864
865 #[inline(always)]
866 fn simd_exp2(self) -> Self {
867 self.map_lanes(|e| e.exp2())
868 }
869
870
871 #[inline(always)]
872 fn simd_exp_m1(self) -> Self {
873 self.map_lanes(|e| e.exp_m1())
874 }
875
876 #[inline(always)]
877 fn simd_ln_1p(self) -> Self {
878 self.map_lanes(|e| e.ln_1p())
879 }
880
881 #[inline(always)]
882 fn simd_ln(self) -> Self {
883 Simd(self.0.ln())
884 }
885
886 #[inline(always)]
887 fn simd_log(self, base: Self) -> Self {
888 self.zip_map_lanes(base, |e, b| e.log(b))
889 }
890
891 #[inline(always)]
892 fn simd_log2(self) -> Self {
893 self.map_lanes(|e| e.log2())
894 }
895
896 #[inline(always)]
897 fn simd_log10(self) -> Self {
898 self.map_lanes(|e| e.log10())
899 }
900
901 #[inline(always)]
902 fn simd_cbrt(self) -> Self {
903 self.map_lanes(|e| e.cbrt())
904 }
905
906 #[inline(always)]
907 fn simd_hypot(self, other: Self) -> Self::SimdRealField {
908 self.zip_map_lanes(other, |e, o| e.hypot(o))
909 }
910
911 #[inline(always)]
912 fn simd_sin(self) -> Self {
913 Simd(self.0.sin())
914 }
915
916 #[inline(always)]
917 fn simd_cos(self) -> Self {
918 Simd(self.0.cos())
919 }
920
921 #[inline(always)]
922 fn simd_tan(self) -> Self {
923 self.map_lanes(|e| e.tan())
924 }
925
926 #[inline(always)]
927 fn simd_asin(self) -> Self {
928 self.map_lanes(|e| e.asin())
929 }
930
931 #[inline(always)]
932 fn simd_acos(self) -> Self {
933 self.map_lanes(|e| e.acos())
934 }
935
936 #[inline(always)]
937 fn simd_atan(self) -> Self {
938 self.map_lanes(|e| e.atan())
939 }
940
941 #[inline(always)]
942 fn simd_sin_cos(self) -> (Self, Self) {
943 (self.simd_sin(), self.simd_cos())
944 }
945
946 // #[inline(always]
947 // fn simd_exp_m1(self) -> Self {
948 // $libm::exp_m1(self)
949 // }
950 //
951 // #[inline(always]
952 // fn simd_ln_1p(self) -> Self {
953 // $libm::ln_1p(self)
954 // }
955 //
956 #[inline(always)]
957 fn simd_sinh(self) -> Self {
958 self.map_lanes(|e| e.sinh())
959 }
960
961 #[inline(always)]
962 fn simd_cosh(self) -> Self {
963 self.map_lanes(|e| e.cosh())
964 }
965
966 #[inline(always)]
967 fn simd_tanh(self) -> Self {
968 self.map_lanes(|e| e.tanh())
969 }
970
971 #[inline(always)]
972 fn simd_asinh(self) -> Self {
973 self.map_lanes(|e| e.asinh())
974 }
975
976 #[inline(always)]
977 fn simd_acosh(self) -> Self {
978 self.map_lanes(|e| e.acosh())
979 }
980
981 #[inline(always)]
982 fn simd_atanh(self) -> Self {
983 self.map_lanes(|e| e.atanh())
984 }
985 }
986
987 // NOTE: most of the impls in there are copy-paste from the implementation of
988 // ComplexField for num_complex::Complex. Unfortunately, we can't reuse the implementations
989 // so easily.
990 impl SimdComplexField for num_complex::Complex<Simd<$t>> {
991 type SimdRealField = Simd<$t>;
992
993 #[inline(always)]
994 fn simd_horizontal_sum(self) -> Self::Element {
995 num_complex::Complex::new(self.re.simd_horizontal_sum(), self.im.simd_horizontal_sum())
996 }
997
998 #[inline(always)]
999 fn simd_horizontal_product(self) -> Self::Element {
1000 let mut prod = self.extract(0);
1001 for ii in 1..Self::lanes() {
1002 prod = prod * self.extract(ii)
1003 }
1004 prod
1005 }
1006
1007 #[inline]
1008 fn from_simd_real(re: Self::SimdRealField) -> Self {
1009 Self::new(re, Self::SimdRealField::zero())
1010 }
1011
1012 #[inline]
1013 fn simd_real(self) -> Self::SimdRealField {
1014 self.re
1015 }
1016
1017 #[inline]
1018 fn simd_imaginary(self) -> Self::SimdRealField {
1019 self.im
1020 }
1021
1022 #[inline]
1023 fn simd_argument(self) -> Self::SimdRealField {
1024 self.im.simd_atan2(self.re)
1025 }
1026
1027 #[inline]
1028 fn simd_modulus(self) -> Self::SimdRealField {
1029 self.re.simd_hypot(self.im)
1030 }
1031
1032 #[inline]
1033 fn simd_modulus_squared(self) -> Self::SimdRealField {
1034 self.re * self.re + self.im * self.im
1035 }
1036
1037 #[inline]
1038 fn simd_norm1(self) -> Self::SimdRealField {
1039 self.re.simd_abs() + self.im.simd_abs()
1040 }
1041
1042 #[inline]
1043 fn simd_recip(self) -> Self {
1044 Self::one() / self
1045 }
1046
1047 #[inline]
1048 fn simd_conjugate(self) -> Self {
1049 self.conj()
1050 }
1051
1052 #[inline]
1053 fn simd_scale(self, factor: Self::SimdRealField) -> Self {
1054 self * factor
1055 }
1056
1057 #[inline]
1058 fn simd_unscale(self, factor: Self::SimdRealField) -> Self {
1059 self / factor
1060 }
1061
1062 #[inline]
1063 fn simd_floor(self) -> Self {
1064 Self::new(self.re.simd_floor(), self.im.simd_floor())
1065 }
1066
1067 #[inline]
1068 fn simd_ceil(self) -> Self {
1069 Self::new(self.re.simd_ceil(), self.im.simd_ceil())
1070 }
1071
1072 #[inline]
1073 fn simd_round(self) -> Self {
1074 Self::new(self.re.simd_round(), self.im.simd_round())
1075 }
1076
1077 #[inline]
1078 fn simd_trunc(self) -> Self {
1079 Self::new(self.re.simd_trunc(), self.im.simd_trunc())
1080 }
1081
1082 #[inline]
1083 fn simd_fract(self) -> Self {
1084 Self::new(self.re.simd_fract(), self.im.simd_fract())
1085 }
1086
1087 #[inline]
1088 fn simd_mul_add(self, a: Self, b: Self) -> Self {
1089 self * a + b
1090 }
1091
1092 #[inline]
1093 fn simd_abs(self) -> Self::SimdRealField {
1094 self.simd_modulus()
1095 }
1096
1097 #[inline]
1098 fn simd_exp2(self) -> Self {
1099 let _2 = Simd::<$t>::one() + Simd::<$t>::one();
1100 num_complex::Complex::new(_2, Simd::<$t>::zero()).simd_powc(self)
1101 }
1102
1103 #[inline]
1104 fn simd_exp_m1(self) -> Self {
1105 self.simd_exp() - Self::one()
1106 }
1107
1108 #[inline]
1109 fn simd_ln_1p(self) -> Self {
1110 (Self::one() + self).simd_ln()
1111 }
1112
1113 #[inline]
1114 fn simd_log2(self) -> Self {
1115 let _2 = Simd::<$t>::one() + Simd::<$t>::one();
1116 self.simd_log(_2)
1117 }
1118
1119 #[inline]
1120 fn simd_log10(self) -> Self {
1121 let _10 = Simd::<$t>::from_subset(&10.0f64);
1122 self.simd_log(_10)
1123 }
1124
1125 #[inline]
1126 fn simd_cbrt(self) -> Self {
1127 let one_third = Simd::<$t>::from_subset(&(1.0 / 3.0));
1128 self.simd_powf(one_third)
1129 }
1130
1131 #[inline]
1132 fn simd_powi(self, n: i32) -> Self {
1133 // FIXME: is there a more accurate solution?
1134 let n = Simd::<$t>::from_subset(&(n as f64));
1135 self.simd_powf(n)
1136 }
1137
1138 /*
1139 *
1140 *
1141 * Unfortunately we are forced to copy-paste all
1142 * those impls from https://github.com/rust-num/num-complex/blob/master/src/lib.rs
1143 * to avoid requiring `std`.
1144 *
1145 *
1146 */
1147 /// Computes `e^(self)`, where `e` is the base of the natural logarithm.
1148 #[inline]
1149 fn simd_exp(self) -> Self {
1150 // formula: e^(a + bi) = e^a (cos(b) + i*sin(b))
1151 // = from_polar(e^a, b)
1152 simd_complex_from_polar(self.re.simd_exp(), self.im)
1153 }
1154
1155 /// Computes the principal value of natural logarithm of `self`.
1156 ///
1157 /// This function has one branch cut:
1158 ///
1159 /// * `(-∞, 0]`, continuous from above.
1160 ///
1161 /// The branch satisfies `-π ≤ arg(ln(z)) ≤ π`.
1162 #[inline]
1163 fn simd_ln(self) -> Self {
1164 // formula: ln(z) = ln|z| + i*arg(z)
1165 let (r, theta) = self.simd_to_polar();
1166 Self::new(r.simd_ln(), theta)
1167 }
1168
1169 /// Computes the principal value of the square root of `self`.
1170 ///
1171 /// This function has one branch cut:
1172 ///
1173 /// * `(-∞, 0)`, continuous from above.
1174 ///
1175 /// The branch satisfies `-π/2 ≤ arg(sqrt(z)) ≤ π/2`.
1176 #[inline]
1177 fn simd_sqrt(self) -> Self {
1178 // formula: sqrt(r e^(it)) = sqrt(r) e^(it/2)
1179 let two = Simd::<$t>::one() + Simd::<$t>::one();
1180 let (r, theta) = self.simd_to_polar();
1181 simd_complex_from_polar(r.simd_sqrt(), theta / two)
1182 }
1183
1184 #[inline]
1185 fn simd_hypot(self, b: Self) -> Self::SimdRealField {
1186 (self.simd_modulus_squared() + b.simd_modulus_squared()).simd_sqrt()
1187 }
1188
1189 /// Raises `self` to a floating point power.
1190 #[inline]
1191 fn simd_powf(self, exp: Self::SimdRealField) -> Self {
1192 // formula: x^y = (ρ e^(i θ))^y = ρ^y e^(i θ y)
1193 // = from_polar(ρ^y, θ y)
1194 let (r, theta) = self.simd_to_polar();
1195 simd_complex_from_polar(r.simd_powf(exp), theta * exp)
1196 }
1197
1198 /// Returns the logarithm of `self` with respect to an arbitrary base.
1199 #[inline]
1200 fn simd_log(self, base: Simd<$t>) -> Self {
1201 // formula: log_y(x) = log_y(ρ e^(i θ))
1202 // = log_y(ρ) + log_y(e^(i θ)) = log_y(ρ) + ln(e^(i θ)) / ln(y)
1203 // = log_y(ρ) + i θ / ln(y)
1204 let (r, theta) = self.simd_to_polar();
1205 Self::new(r.simd_log(base), theta / base.simd_ln())
1206 }
1207
1208 /// Raises `self` to a complex power.
1209 #[inline]
1210 fn simd_powc(self, exp: Self) -> Self {
1211 // formula: x^y = (a + i b)^(c + i d)
1212 // = (ρ e^(i θ))^c (ρ e^(i θ))^(i d)
1213 // where ρ=|x| and θ=arg(x)
1214 // = ρ^c e^(−d θ) e^(i c θ) ρ^(i d)
1215 // = p^c e^(−d θ) (cos(c θ)
1216 // + i sin(c θ)) (cos(d ln(ρ)) + i sin(d ln(ρ)))
1217 // = p^c e^(−d θ) (
1218 // cos(c θ) cos(d ln(ρ)) − sin(c θ) sin(d ln(ρ))
1219 // + i(cos(c θ) sin(d ln(ρ)) + sin(c θ) cos(d ln(ρ))))
1220 // = p^c e^(−d θ) (cos(c θ + d ln(ρ)) + i sin(c θ + d ln(ρ)))
1221 // = from_polar(p^c e^(−d θ), c θ + d ln(ρ))
1222 let (r, theta) = self.simd_to_polar();
1223 simd_complex_from_polar(
1224 r.simd_powf(exp.re) * (-exp.im * theta).simd_exp(),
1225 exp.re * theta + exp.im * r.simd_ln(),
1226 )
1227 }
1228
1229 /*
1230 /// Raises a floating point number to the complex power `self`.
1231 #[inline]
1232 fn simd_expf(&self, base: T) -> Self {
1233 // formula: x^(a+bi) = x^a x^bi = x^a e^(b ln(x) i)
1234 // = from_polar(x^a, b ln(x))
1235 Self::from_polar(&base.powf(self.re), &(self.im * base.ln()))
1236 }
1237 */
1238
1239 /// Computes the sine of `self`.
1240 #[inline]
1241 fn simd_sin(self) -> Self {
1242 // formula: sin(a + bi) = sin(a)cosh(b) + i*cos(a)sinh(b)
1243 Self::new(
1244 self.re.simd_sin() * self.im.simd_cosh(),
1245 self.re.simd_cos() * self.im.simd_sinh(),
1246 )
1247 }
1248
1249 /// Computes the cosine of `self`.
1250 #[inline]
1251 fn simd_cos(self) -> Self {
1252 // formula: cos(a + bi) = cos(a)cosh(b) - i*sin(a)sinh(b)
1253 Self::new(
1254 self.re.simd_cos() * self.im.simd_cosh(),
1255 -self.re.simd_sin() * self.im.simd_sinh(),
1256 )
1257 }
1258
1259 #[inline]
1260 fn simd_sin_cos(self) -> (Self, Self) {
1261 let (rsin, rcos) = self.re.simd_sin_cos();
1262 let (isinh, icosh) = self.im.simd_sinh_cosh();
1263 let sin = Self::new(rsin * icosh, rcos * isinh);
1264 let cos = Self::new(rcos * icosh, -rsin * isinh);
1265
1266 (sin, cos)
1267 }
1268
1269 /// Computes the tangent of `self`.
1270 #[inline]
1271 fn simd_tan(self) -> Self {
1272 // formula: tan(a + bi) = (sin(2a) + i*sinh(2b))/(cos(2a) + cosh(2b))
1273 let (two_re, two_im) = (self.re + self.re, self.im + self.im);
1274 Self::new(two_re.simd_sin(), two_im.simd_sinh()).unscale(two_re.simd_cos() + two_im.simd_cosh())
1275 }
1276
1277 /// Computes the principal value of the inverse sine of `self`.
1278 ///
1279 /// This function has two branch cuts:
1280 ///
1281 /// * `(-∞, -1)`, continuous from above.
1282 /// * `(1, ∞)`, continuous from below.
1283 ///
1284 /// The branch satisfies `-π/2 ≤ Re(asin(z)) ≤ π/2`.
1285 #[inline]
1286 fn simd_asin(self) -> Self {
1287 // formula: arcsin(z) = -i ln(sqrt(1-z^2) + iz)
1288 let i = Self::i();
1289 -i * ((Self::one() - self * self).simd_sqrt() + i * self).simd_ln()
1290 }
1291
1292 /// Computes the principal value of the inverse cosine of `self`.
1293 ///
1294 /// This function has two branch cuts:
1295 ///
1296 /// * `(-∞, -1)`, continuous from above.
1297 /// * `(1, ∞)`, continuous from below.
1298 ///
1299 /// The branch satisfies `0 ≤ Re(acos(z)) ≤ π`.
1300 #[inline]
1301 fn simd_acos(self) -> Self {
1302 // formula: arccos(z) = -i ln(i sqrt(1-z^2) + z)
1303 let i = Self::i();
1304 -i * (i * (Self::one() - self * self).simd_sqrt() + self).simd_ln()
1305 }
1306
1307 /// Computes the principal value of the inverse tangent of `self`.
1308 ///
1309 /// This function has two branch cuts:
1310 ///
1311 /// * `(-∞i, -i]`, continuous from the left.
1312 /// * `[i, ∞i)`, continuous from the right.
1313 ///
1314 /// The branch satisfies `-π/2 ≤ Re(atan(z)) ≤ π/2`.
1315 #[inline]
1316 fn simd_atan(self) -> Self {
1317 // formula: arctan(z) = (ln(1+iz) - ln(1-iz))/(2i)
1318 let i = Self::i();
1319 let one = Self::one();
1320 let two = one + one;
1321
1322 if self == i {
1323 return Self::new(Simd::<$t>::zero(), Simd::<$t>::one() / Simd::<$t>::zero());
1324 } else if self == -i {
1325 return Self::new(Simd::<$t>::zero(), -Simd::<$t>::one() / Simd::<$t>::zero());
1326 }
1327
1328 ((one + i * self).simd_ln() - (one - i * self).simd_ln()) / (two * i)
1329 }
1330
1331 /// Computes the hyperbolic sine of `self`.
1332 #[inline]
1333 fn simd_sinh(self) -> Self {
1334 // formula: sinh(a + bi) = sinh(a)cos(b) + i*cosh(a)sin(b)
1335 Self::new(
1336 self.re.simd_sinh() * self.im.simd_cos(),
1337 self.re.simd_cosh() * self.im.simd_sin(),
1338 )
1339 }
1340
1341 /// Computes the hyperbolic cosine of `self`.
1342 #[inline]
1343 fn simd_cosh(self) -> Self {
1344 // formula: cosh(a + bi) = cosh(a)cos(b) + i*sinh(a)sin(b)
1345 Self::new(
1346 self.re.simd_cosh() * self.im.simd_cos(),
1347 self.re.simd_sinh() * self.im.simd_sin(),
1348 )
1349 }
1350
1351 #[inline]
1352 fn simd_sinh_cosh(self) -> (Self, Self) {
1353 let (rsinh, rcosh) = self.re.simd_sinh_cosh();
1354 let (isin, icos) = self.im.simd_sin_cos();
1355 let sin = Self::new(rsinh * icos, rcosh * isin);
1356 let cos = Self::new(rcosh * icos, rsinh * isin);
1357
1358 (sin, cos)
1359 }
1360
1361 /// Computes the hyperbolic tangent of `self`.
1362 #[inline]
1363 fn simd_tanh(self) -> Self {
1364 // formula: tanh(a + bi) = (sinh(2a) + i*sin(2b))/(cosh(2a) + cos(2b))
1365 let (two_re, two_im) = (self.re + self.re, self.im + self.im);
1366 Self::new(two_re.simd_sinh(), two_im.simd_sin()).unscale(two_re.simd_cosh() + two_im.simd_cos())
1367 }
1368
1369 /// Computes the principal value of inverse hyperbolic sine of `self`.
1370 ///
1371 /// This function has two branch cuts:
1372 ///
1373 /// * `(-∞i, -i)`, continuous from the left.
1374 /// * `(i, ∞i)`, continuous from the right.
1375 ///
1376 /// The branch satisfies `-π/2 ≤ Im(asinh(z)) ≤ π/2`.
1377 #[inline]
1378 fn simd_asinh(self) -> Self {
1379 // formula: arcsinh(z) = ln(z + sqrt(1+z^2))
1380 let one = Self::one();
1381 (self + (one + self * self).simd_sqrt()).simd_ln()
1382 }
1383
1384 /// Computes the principal value of inverse hyperbolic cosine of `self`.
1385 ///
1386 /// This function has one branch cut:
1387 ///
1388 /// * `(-∞, 1)`, continuous from above.
1389 ///
1390 /// The branch satisfies `-π ≤ Im(acosh(z)) ≤ π` and `0 ≤ Re(acosh(z)) < ∞`.
1391 #[inline]
1392 fn simd_acosh(self) -> Self {
1393 // formula: arccosh(z) = 2 ln(sqrt((z+1)/2) + sqrt((z-1)/2))
1394 let one = Self::one();
1395 let two = one + one;
1396 two * (((self + one) / two).simd_sqrt() + ((self - one) / two).simd_sqrt()).simd_ln()
1397 }
1398
1399 /// Computes the principal value of inverse hyperbolic tangent of `self`.
1400 ///
1401 /// This function has two branch cuts:
1402 ///
1403 /// * `(-∞, -1]`, continuous from above.
1404 /// * `[1, ∞)`, continuous from below.
1405 ///
1406 /// The branch satisfies `-π/2 ≤ Im(atanh(z)) ≤ π/2`.
1407 #[inline]
1408 fn simd_atanh(self) -> Self {
1409 // formula: arctanh(z) = (ln(1+z) - ln(1-z))/2
1410 let one = Self::one();
1411 let two = one + one;
1412 if self == one {
1413 return Self::new(Simd::<$t>::one() / Simd::<$t>::zero(), Simd::<$t>::zero());
1414 } else if self == -one {
1415 return Self::new(-Simd::<$t>::one() / Simd::<$t>::zero(), Simd::<$t>::zero());
1416 }
1417 ((one + self).simd_ln() - (one - self).simd_ln()) / two
1418 }
1419 }
1420 )*)
1421 );
1422
1423 #[inline]
simd_complex_from_polar<N: SimdRealField>(r: N, theta: N) -> num_complex::Complex<N>1424 fn simd_complex_from_polar<N: SimdRealField>(r: N, theta: N) -> num_complex::Complex<N> {
1425 num_complex::Complex::new(r.clone() * theta.clone().simd_cos(), r * theta.simd_sin())
1426 }
1427
1428 impl_float_simd!(
1429 packed_simd::f32x2, f32, packed_simd::i32x2, m32x2, _0, _1;
1430 packed_simd::f32x4, f32, packed_simd::i32x4, m32x4, _0, _1, _2, _3;
1431 packed_simd::f32x8, f32, packed_simd::i32x8, m32x8, _0, _1, _2, _3, _4, _5, _6, _7;
1432 packed_simd::f32x16, f32, packed_simd::i32x16, m32x16, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15;
1433 packed_simd::f64x2, f64, packed_simd::i64x2, m64x2, _0, _1;
1434 packed_simd::f64x4, f64, packed_simd::i64x4, m64x4, _0, _1, _2, _3;
1435 packed_simd::f64x8, f64, packed_simd::i64x8, m64x8, _0, _1, _2, _3, _4, _5, _6, _7;
1436 );
1437
1438 impl_int_simd!(
1439 packed_simd::i128x1, i128, m128x1, _0;
1440 packed_simd::i128x2, i128, m128x2, _0, _1;
1441 packed_simd::i128x4, i128, m128x4, _0, _1, _2, _3;
1442 packed_simd::i16x2, i16, m16x2, _0, _1;
1443 packed_simd::i16x4, i16, m16x4, _0, _1, _2, _3;
1444 packed_simd::i16x8, i16, m16x8, _0, _1, _2, _3, _4, _5, _6, _7;
1445 packed_simd::i16x16, i16, m16x16, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15;
1446 packed_simd::i16x32, i16, m16x32, _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;
1447 packed_simd::i32x2, i32, m32x2, _0, _1;
1448 packed_simd::i32x4, i32, m32x4, _0, _1, _2, _3;
1449 packed_simd::i32x8, i32, m32x8, _0, _1, _2, _3, _4, _5, _6, _7;
1450 packed_simd::i32x16, i32, m32x16, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15;
1451 packed_simd::i64x2, i64, m64x2, _0, _1;
1452 packed_simd::i64x4, i64, m64x4, _0, _1, _2, _3;
1453 packed_simd::i64x8, i64, m64x8, _0, _1, _2, _3, _4, _5, _6, _7;
1454 packed_simd::i8x2, i8, m8x2, _0, _1;
1455 packed_simd::i8x4, i8, m8x4, _0, _1, _2, _3;
1456 packed_simd::i8x8, i8, m8x8, _0, _1, _2, _3, _4, _5, _6, _7;
1457 packed_simd::i8x16, i8, m8x16, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15;
1458 packed_simd::i8x32, i8, m8x32, _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;
1459 packed_simd::i8x64, i8, m8x64, _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, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63;
1460 packed_simd::isizex2, isize, msizex2, _0, _1;
1461 packed_simd::isizex4, isize, msizex4, _0, _1, _2, _3;
1462 packed_simd::isizex8, isize, msizex8, _0, _1, _2, _3, _4, _5, _6, _7;
1463 );
1464
1465 impl_uint_simd!(
1466 packed_simd::u128x1, u128, m128x1, _0;
1467 packed_simd::u128x2, u128, m128x2, _0, _1;
1468 packed_simd::u128x4, u128, m128x4, _0, _1, _2, _3;
1469 packed_simd::u16x2, u16, m16x2, _0, _1;
1470 packed_simd::u16x4, u16, m16x4, _0, _1, _2, _3;
1471 packed_simd::u16x8, u16, m16x8, _0, _1, _2, _3, _4, _5, _6, _7;
1472 packed_simd::u16x16, u16, m16x16, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15;
1473 packed_simd::u16x32, u16, m16x32, _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;
1474 packed_simd::u32x2, u32, m32x2, _0, _1;
1475 packed_simd::u32x4, u32, m32x4, _0, _1, _2, _3;
1476 packed_simd::u32x8, u32, m32x8, _0, _1, _2, _3, _4, _5, _6, _7;
1477 packed_simd::u32x16, u32, m32x16, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15;
1478 packed_simd::u64x2, u64, m64x2, _0, _1;
1479 packed_simd::u64x4, u64, m64x4, _0, _1, _2, _3;
1480 packed_simd::u64x8, u64, m64x8, _0, _1, _2, _3, _4, _5, _6, _7;
1481 packed_simd::u8x2, u8, m8x2, _0, _1;
1482 packed_simd::u8x4, u8, m8x4, _0, _1, _2, _3;
1483 packed_simd::u8x8, u8, m8x8, _0, _1, _2, _3, _4, _5, _6, _7;
1484 packed_simd::u8x16, u8, m8x16, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15;
1485 packed_simd::u8x32, u8, m8x32, _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;
1486 packed_simd::u8x64, u8, m8x64, _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, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63;
1487 packed_simd::usizex2, usize, msizex2, _0, _1;
1488 packed_simd::usizex4, usize, msizex4, _0, _1, _2, _3;
1489 packed_simd::usizex8, usize, msizex8, _0, _1, _2, _3, _4, _5, _6, _7;
1490 );
1491
1492 impl_bool_simd!(
1493 packed_simd::m128x1, _0;
1494 packed_simd::m128x2, _0, _1;
1495 packed_simd::m128x4, _0, _1, _2, _3;
1496 packed_simd::m16x2, _0, _1;
1497 packed_simd::m16x4, _0, _1, _2, _3;
1498 packed_simd::m16x8, _0, _1, _2, _3, _4, _5, _6, _7;
1499 packed_simd::m16x16, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15;
1500 packed_simd::m16x32, _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;
1501 packed_simd::m32x2, _0, _1;
1502 packed_simd::m32x4, _0, _1, _2, _3;
1503 packed_simd::m32x8, _0, _1, _2, _3, _4, _5, _6, _7;
1504 packed_simd::m32x16, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15;
1505 packed_simd::m64x2, _0, _1;
1506 packed_simd::m64x4, _0, _1, _2, _3;
1507 packed_simd::m64x8, _0, _1, _2, _3, _4, _5, _6, _7;
1508 packed_simd::m8x2, _0, _1;
1509 packed_simd::m8x4, _0, _1, _2, _3;
1510 packed_simd::m8x8, _0, _1, _2, _3, _4, _5, _6, _7;
1511 packed_simd::m8x16, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15;
1512 packed_simd::m8x32, _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;
1513 packed_simd::m8x64, _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, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63;
1514 packed_simd::msizex2, _0, _1;
1515 packed_simd::msizex4, _0, _1, _2, _3;
1516 packed_simd::msizex8, _0, _1, _2, _3, _4, _5, _6, _7;
1517 );
1518
1519 //
1520 // NOTE: the following does not work because of the orphan rules.
1521 //
1522 //macro_rules! impl_simd_complex_from(
1523 // ($($t: ty, $elt: ty $(, $i: expr)*;)*) => ($(
1524 // impl From<[num_complex::Complex<$elt>; <$t>::lanes()]> for num_complex::Complex<Simd<$t>> {
1525 // #[inline(always)]
1526 // fn from(vals: [num_complex::Complex<$elt>; <$t>::lanes()]) -> Self {
1527 // num_complex::Complex {
1528 // re: <$t>::from([$(vals[$i].re),*]),
1529 // im: <$t>::from([$(vals[$i].im),*]),
1530 // }
1531 // }
1532 // }
1533 // )*)
1534 //);
1535 //
1536 //impl_simd_complex_from!(
1537 // packed_simd::f32x2, f32, 0, 1;
1538 // packed_simd::f32x4, f32, 0, 1, 2, 3;
1539 // packed_simd::f32x8, f32, 0, 1, 2, 3, 4, 5, 6, 7;
1540 // packed_simd::f32x16, f32, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15;
1541 //);
1542
1543 //////////////////////////////////////////
1544 // Aliases //
1545 //////////////////////////////////////////
1546
1547 pub type f32x2 = Simd<packed_simd::f32x2>;
1548 pub type f32x4 = Simd<packed_simd::f32x4>;
1549 pub type f32x8 = Simd<packed_simd::f32x8>;
1550 pub type f32x16 = Simd<packed_simd::f32x16>;
1551 pub type f64x2 = Simd<packed_simd::f64x2>;
1552 pub type f64x4 = Simd<packed_simd::f64x4>;
1553 pub type f64x8 = Simd<packed_simd::f64x8>;
1554 pub type i128x1 = Simd<packed_simd::i128x1>;
1555 pub type i128x2 = Simd<packed_simd::i128x2>;
1556 pub type i128x4 = Simd<packed_simd::i128x4>;
1557 pub type i16x2 = Simd<packed_simd::i16x2>;
1558 pub type i16x4 = Simd<packed_simd::i16x4>;
1559 pub type i16x8 = Simd<packed_simd::i16x8>;
1560 pub type i16x16 = Simd<packed_simd::i16x16>;
1561 pub type i16x32 = Simd<packed_simd::i16x32>;
1562 pub type i32x2 = Simd<packed_simd::i32x2>;
1563 pub type i32x4 = Simd<packed_simd::i32x4>;
1564 pub type i32x8 = Simd<packed_simd::i32x8>;
1565 pub type i32x16 = Simd<packed_simd::i32x16>;
1566 pub type i64x2 = Simd<packed_simd::i64x2>;
1567 pub type i64x4 = Simd<packed_simd::i64x4>;
1568 pub type i64x8 = Simd<packed_simd::i64x8>;
1569 pub type i8x2 = Simd<packed_simd::i8x2>;
1570 pub type i8x4 = Simd<packed_simd::i8x4>;
1571 pub type i8x8 = Simd<packed_simd::i8x8>;
1572 pub type i8x16 = Simd<packed_simd::i8x16>;
1573 pub type i8x32 = Simd<packed_simd::i8x32>;
1574 pub type i8x64 = Simd<packed_simd::i8x64>;
1575 pub type isizex2 = Simd<packed_simd::isizex2>;
1576 pub type isizex4 = Simd<packed_simd::isizex4>;
1577 pub type isizex8 = Simd<packed_simd::isizex8>;
1578 pub type u128x1 = Simd<packed_simd::u128x1>;
1579 pub type u128x2 = Simd<packed_simd::u128x2>;
1580 pub type u128x4 = Simd<packed_simd::u128x4>;
1581 pub type u16x2 = Simd<packed_simd::u16x2>;
1582 pub type u16x4 = Simd<packed_simd::u16x4>;
1583 pub type u16x8 = Simd<packed_simd::u16x8>;
1584 pub type u16x16 = Simd<packed_simd::u16x16>;
1585 pub type u16x32 = Simd<packed_simd::u16x32>;
1586 pub type u32x2 = Simd<packed_simd::u32x2>;
1587 pub type u32x4 = Simd<packed_simd::u32x4>;
1588 pub type u32x8 = Simd<packed_simd::u32x8>;
1589 pub type u32x16 = Simd<packed_simd::u32x16>;
1590 pub type u64x2 = Simd<packed_simd::u64x2>;
1591 pub type u64x4 = Simd<packed_simd::u64x4>;
1592 pub type u64x8 = Simd<packed_simd::u64x8>;
1593 pub type u8x2 = Simd<packed_simd::u8x2>;
1594 pub type u8x4 = Simd<packed_simd::u8x4>;
1595 pub type u8x8 = Simd<packed_simd::u8x8>;
1596 pub type u8x16 = Simd<packed_simd::u8x16>;
1597 pub type u8x32 = Simd<packed_simd::u8x32>;
1598 pub type u8x64 = Simd<packed_simd::u8x64>;
1599 pub type usizex2 = Simd<packed_simd::usizex2>;
1600 pub type usizex4 = Simd<packed_simd::usizex4>;
1601 pub type usizex8 = Simd<packed_simd::usizex8>;
1602
1603 pub type m128x1 = Simd<packed_simd::m128x1>;
1604 pub type m128x2 = Simd<packed_simd::m128x2>;
1605 pub type m128x4 = Simd<packed_simd::m128x4>;
1606 pub type m16x16 = Simd<packed_simd::m16x16>;
1607 pub type m16x2 = Simd<packed_simd::m16x2>;
1608 pub type m16x32 = Simd<packed_simd::m16x32>;
1609 pub type m16x4 = Simd<packed_simd::m16x4>;
1610 pub type m16x8 = Simd<packed_simd::m16x8>;
1611 pub type m32x16 = Simd<packed_simd::m32x16>;
1612 pub type m32x2 = Simd<packed_simd::m32x2>;
1613 pub type m32x4 = Simd<packed_simd::m32x4>;
1614 pub type m32x8 = Simd<packed_simd::m32x8>;
1615 pub type m64x2 = Simd<packed_simd::m64x2>;
1616 pub type m64x4 = Simd<packed_simd::m64x4>;
1617 pub type m64x8 = Simd<packed_simd::m64x8>;
1618 pub type m8x16 = Simd<packed_simd::m8x16>;
1619 pub type m8x2 = Simd<packed_simd::m8x2>;
1620 pub type m8x32 = Simd<packed_simd::m8x32>;
1621 pub type m8x4 = Simd<packed_simd::m8x4>;
1622 pub type m8x64 = Simd<packed_simd::m8x64>;
1623 pub type m8x8 = Simd<packed_simd::m8x8>;
1624 pub type msizex2 = Simd<packed_simd::msizex2>;
1625 pub type msizex4 = Simd<packed_simd::msizex4>;
1626 pub type msizex8 = Simd<packed_simd::msizex8>;
1627