1 #[cfg(not(feature = "f16"))]
2 use crate::f16::panic_f16_feature_disabled;
7 Bool, Compare, Context, ConvertFrom, ConvertTo, Float, Int, Make, SInt, Select, UInt,
13 Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div,
14 DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub,
19 LanesAtMost32, Mask, Mask16, Mask32, Mask64, Mask8, SimdF32, SimdF64, SimdI16, SimdI32,
20 SimdI64, SimdI8, SimdU16, SimdU32, SimdU64, SimdU8,
23 #[cfg(not(feature = "f16"))]
27 #[derive(Copy, Clone, Debug)]
29 pub struct SimdF16<const LANES: usize>(pub(crate) SimdU16<LANES>)
31 SimdU16<LANES>: LanesAtMost32;
33 impl<const LANES: usize> SimdF16<LANES>
35 SimdU16<LANES>: LanesAtMost32,
36 SimdI16<LANES>: LanesAtMost32,
39 pub(crate) fn splat(_v: F16) -> Self {
40 panic_f16_feature_disabled()
42 pub(crate) fn abs(self) -> Self {
43 panic_f16_feature_disabled()
45 pub(crate) fn trunc(self) -> Self {
46 panic_f16_feature_disabled()
48 pub(crate) fn floor(self) -> Self {
49 panic_f16_feature_disabled()
51 pub(crate) fn ceil(self) -> Self {
52 panic_f16_feature_disabled()
54 pub(crate) fn round(self) -> Self {
55 panic_f16_feature_disabled()
57 pub(crate) fn from_bits(_v: SimdU16<LANES>) -> Self {
58 panic_f16_feature_disabled()
60 pub(crate) fn to_bits(self) -> SimdU16<LANES> {
61 panic_f16_feature_disabled()
63 pub(crate) fn is_finite(self) -> Mask16<LANES> {
64 panic_f16_feature_disabled()
66 pub(crate) fn lanes_eq(self, _rhs: Self) -> Mask16<LANES> {
67 panic_f16_feature_disabled()
69 pub(crate) fn lanes_ne(self, _rhs: Self) -> Mask16<LANES> {
70 panic_f16_feature_disabled()
72 pub(crate) fn lanes_gt(self, _rhs: Self) -> Mask16<LANES> {
73 panic_f16_feature_disabled()
75 pub(crate) fn lanes_ge(self, _rhs: Self) -> Mask16<LANES> {
76 panic_f16_feature_disabled()
78 pub(crate) fn lanes_lt(self, _rhs: Self) -> Mask16<LANES> {
79 panic_f16_feature_disabled()
81 pub(crate) fn lanes_le(self, _rhs: Self) -> Mask16<LANES> {
82 panic_f16_feature_disabled()
86 impl<const LANES: usize> From<[F16; LANES]> for SimdF16<LANES>
88 SimdU16<LANES>: LanesAtMost32,
90 fn from(_v: [F16; LANES]) -> Self {
91 panic_f16_feature_disabled()
95 impl<const LANES: usize> From<SimdF16<LANES>> for [F16; LANES]
97 SimdU16<LANES>: LanesAtMost32,
99 fn from(_v: SimdF16<LANES>) -> Self {
100 panic_f16_feature_disabled()
104 macro_rules! impl_f16_bin_op {
105 ($trait:ident, $fn:ident) => {
106 impl<const LANES: usize> $trait for SimdF16<LANES>
108 SimdU16<LANES>: LanesAtMost32,
112 fn $fn(self, _rhs: Self) -> Self::Output {
113 panic_f16_feature_disabled()
119 impl_f16_bin_op!(Add, add);
120 impl_f16_bin_op!(Sub, sub);
121 impl_f16_bin_op!(Mul, mul);
122 impl_f16_bin_op!(Div, div);
123 impl_f16_bin_op!(Rem, rem);
125 macro_rules! impl_f16_bin_assign_op {
126 ($trait:ident, $fn:ident) => {
127 impl<const LANES: usize> $trait for SimdF16<LANES>
129 SimdU16<LANES>: LanesAtMost32,
131 fn $fn(&mut self, _rhs: Self) {
132 panic_f16_feature_disabled()
138 impl_f16_bin_assign_op!(AddAssign, add_assign);
139 impl_f16_bin_assign_op!(SubAssign, sub_assign);
140 impl_f16_bin_assign_op!(MulAssign, mul_assign);
141 impl_f16_bin_assign_op!(DivAssign, div_assign);
142 impl_f16_bin_assign_op!(RemAssign, rem_assign);
144 impl<const LANES: usize> Neg for SimdF16<LANES>
146 SimdU16<LANES>: LanesAtMost32,
150 fn neg(self) -> Self::Output {
151 panic_f16_feature_disabled()
156 #[cfg(not(feature = "f16"))]
159 #[cfg(feature = "f16")]
160 compile_error!("core_simd doesn't yet support f16");
162 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default)]
163 pub struct StdSimd<const LANES: usize>(PhantomData<[(); LANES]>);
165 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)]
167 pub struct Wrapper<T, const LANES: usize>(pub T, PhantomData<[(); LANES]>);
169 impl<T, const LANES: usize> From<T> for Wrapper<T, LANES> {
170 fn from(v: T) -> Self {
171 Wrapper(v, PhantomData)
175 macro_rules! impl_bin_op_for_wrapper {
176 ($trait:ident, $fn:ident) => {
177 impl<T: $trait<Output = T>, const LANES: usize> $trait for Wrapper<T, LANES> {
180 fn $fn(self, rhs: Self) -> Self::Output {
181 self.0.$fn(rhs.0).into()
187 impl_bin_op_for_wrapper!(Add, add);
188 impl_bin_op_for_wrapper!(Sub, sub);
189 impl_bin_op_for_wrapper!(Mul, mul);
190 impl_bin_op_for_wrapper!(Div, div);
191 impl_bin_op_for_wrapper!(Rem, rem);
192 impl_bin_op_for_wrapper!(Shl, shl);
193 impl_bin_op_for_wrapper!(Shr, shr);
194 impl_bin_op_for_wrapper!(BitAnd, bitand);
195 impl_bin_op_for_wrapper!(BitOr, bitor);
196 impl_bin_op_for_wrapper!(BitXor, bitxor);
198 macro_rules! impl_bin_op_assign_for_wrapper {
199 ($trait:ident, $fn:ident) => {
200 impl<T: $trait, const LANES: usize> $trait for Wrapper<T, LANES> {
201 fn $fn(&mut self, rhs: Self) {
208 impl_bin_op_assign_for_wrapper!(AddAssign, add_assign);
209 impl_bin_op_assign_for_wrapper!(SubAssign, sub_assign);
210 impl_bin_op_assign_for_wrapper!(MulAssign, mul_assign);
211 impl_bin_op_assign_for_wrapper!(DivAssign, div_assign);
212 impl_bin_op_assign_for_wrapper!(RemAssign, rem_assign);
213 impl_bin_op_assign_for_wrapper!(ShlAssign, shl_assign);
214 impl_bin_op_assign_for_wrapper!(ShrAssign, shr_assign);
215 impl_bin_op_assign_for_wrapper!(BitAndAssign, bitand_assign);
216 impl_bin_op_assign_for_wrapper!(BitOrAssign, bitor_assign);
217 impl_bin_op_assign_for_wrapper!(BitXorAssign, bitxor_assign);
219 macro_rules! impl_un_op_for_wrapper {
220 ($trait:ident, $fn:ident) => {
221 impl<T: $trait<Output = T>, const LANES: usize> $trait for Wrapper<T, LANES> {
224 fn $fn(self) -> Self::Output {
231 impl_un_op_for_wrapper!(Not, not);
232 impl_un_op_for_wrapper!(Neg, neg);
234 macro_rules! impl_make_for_scalar {
236 impl<const LANES: usize> Make for Wrapper<$ty, LANES>
238 SimdI8<LANES>: LanesAtMost32,
239 SimdU8<LANES>: LanesAtMost32,
241 SimdI16<LANES>: LanesAtMost32,
242 SimdU16<LANES>: LanesAtMost32,
244 SimdI32<LANES>: LanesAtMost32,
245 SimdU32<LANES>: LanesAtMost32,
246 SimdF32<LANES>: LanesAtMost32,
248 SimdI64<LANES>: LanesAtMost32,
249 SimdU64<LANES>: LanesAtMost32,
250 SimdF64<LANES>: LanesAtMost32,
255 type Context = StdSimd<LANES>;
257 fn ctx(self) -> Self::Context {
261 fn make(_ctx: Self::Context, v: Self::Prim) -> Self {
268 impl_make_for_scalar!(bool);
269 impl_make_for_scalar!(i8);
270 impl_make_for_scalar!(u8);
271 impl_make_for_scalar!(i16);
272 impl_make_for_scalar!(u16);
273 impl_make_for_scalar!(F16);
274 impl_make_for_scalar!(i32);
275 impl_make_for_scalar!(u32);
276 impl_make_for_scalar!(f32);
277 impl_make_for_scalar!(i64);
278 impl_make_for_scalar!(u64);
279 impl_make_for_scalar!(f64);
281 impl<V, const LANES: usize> Select<V> for Wrapper<bool, LANES>
283 SimdI8<LANES>: LanesAtMost32,
284 SimdU8<LANES>: LanesAtMost32,
286 SimdI16<LANES>: LanesAtMost32,
287 SimdU16<LANES>: LanesAtMost32,
289 SimdI32<LANES>: LanesAtMost32,
290 SimdU32<LANES>: LanesAtMost32,
291 SimdF32<LANES>: LanesAtMost32,
293 SimdI64<LANES>: LanesAtMost32,
294 SimdU64<LANES>: LanesAtMost32,
295 SimdF64<LANES>: LanesAtMost32,
298 fn select(self, true_v: V, false_v: V) -> V {
307 macro_rules! impl_scalar_compare {
309 impl<const LANES: usize> Compare for Wrapper<$ty, LANES>
311 SimdI8<LANES>: LanesAtMost32,
312 SimdU8<LANES>: LanesAtMost32,
314 SimdI16<LANES>: LanesAtMost32,
315 SimdU16<LANES>: LanesAtMost32,
317 SimdI32<LANES>: LanesAtMost32,
318 SimdU32<LANES>: LanesAtMost32,
319 SimdF32<LANES>: LanesAtMost32,
321 SimdI64<LANES>: LanesAtMost32,
322 SimdU64<LANES>: LanesAtMost32,
323 SimdF64<LANES>: LanesAtMost32,
326 type Bool = Wrapper<bool, LANES>;
328 fn eq(self, rhs: Self) -> Self::Bool {
329 self.0.eq(&rhs.0).into()
332 fn ne(self, rhs: Self) -> Self::Bool {
333 self.0.ne(&rhs.0).into()
336 fn lt(self, rhs: Self) -> Self::Bool {
337 self.0.lt(&rhs.0).into()
340 fn gt(self, rhs: Self) -> Self::Bool {
341 self.0.gt(&rhs.0).into()
344 fn le(self, rhs: Self) -> Self::Bool {
345 self.0.le(&rhs.0).into()
348 fn ge(self, rhs: Self) -> Self::Bool {
349 self.0.ge(&rhs.0).into()
355 impl_scalar_compare!(bool);
356 impl_scalar_compare!(i8);
357 impl_scalar_compare!(u8);
358 impl_scalar_compare!(i16);
359 impl_scalar_compare!(u16);
360 impl_scalar_compare!(F16);
361 impl_scalar_compare!(i32);
362 impl_scalar_compare!(u32);
363 impl_scalar_compare!(f32);
364 impl_scalar_compare!(i64);
365 impl_scalar_compare!(u64);
366 impl_scalar_compare!(f64);
368 macro_rules! impl_vector_compare {
369 ($ty:ident, $mask:ident) => {
370 impl<const LANES: usize> Compare for Wrapper<$ty<LANES>, LANES>
372 SimdI8<LANES>: LanesAtMost32,
373 SimdU8<LANES>: LanesAtMost32,
375 SimdI16<LANES>: LanesAtMost32,
376 SimdU16<LANES>: LanesAtMost32,
378 SimdI32<LANES>: LanesAtMost32,
379 SimdU32<LANES>: LanesAtMost32,
380 SimdF32<LANES>: LanesAtMost32,
382 SimdI64<LANES>: LanesAtMost32,
383 SimdU64<LANES>: LanesAtMost32,
384 SimdF64<LANES>: LanesAtMost32,
387 type Bool = Wrapper<$mask<LANES>, LANES>;
389 fn eq(self, rhs: Self) -> Self::Bool {
390 self.0.lanes_eq(rhs.0).into()
393 fn ne(self, rhs: Self) -> Self::Bool {
394 self.0.lanes_ne(rhs.0).into()
397 fn lt(self, rhs: Self) -> Self::Bool {
398 self.0.lanes_lt(rhs.0).into()
401 fn gt(self, rhs: Self) -> Self::Bool {
402 self.0.lanes_gt(rhs.0).into()
405 fn le(self, rhs: Self) -> Self::Bool {
406 self.0.lanes_le(rhs.0).into()
409 fn ge(self, rhs: Self) -> Self::Bool {
410 self.0.lanes_ge(rhs.0).into()
416 impl_vector_compare!(SimdI8, Mask8);
417 impl_vector_compare!(SimdU8, Mask8);
418 impl_vector_compare!(SimdI16, Mask16);
419 impl_vector_compare!(SimdU16, Mask16);
420 impl_vector_compare!(SimdF16, Mask16);
421 impl_vector_compare!(SimdI32, Mask32);
422 impl_vector_compare!(SimdU32, Mask32);
423 impl_vector_compare!(SimdF32, Mask32);
424 impl_vector_compare!(SimdI64, Mask64);
425 impl_vector_compare!(SimdU64, Mask64);
426 impl_vector_compare!(SimdF64, Mask64);
428 macro_rules! impl_vector_mask_compare {
430 impl<const LANES: usize> Compare for Wrapper<$ty<LANES>, LANES>
432 SimdI8<LANES>: LanesAtMost32,
433 SimdU8<LANES>: LanesAtMost32,
435 SimdI16<LANES>: LanesAtMost32,
436 SimdU16<LANES>: LanesAtMost32,
438 SimdI32<LANES>: LanesAtMost32,
439 SimdU32<LANES>: LanesAtMost32,
440 SimdF32<LANES>: LanesAtMost32,
442 SimdI64<LANES>: LanesAtMost32,
443 SimdU64<LANES>: LanesAtMost32,
444 SimdF64<LANES>: LanesAtMost32,
449 fn eq(self, rhs: Self) -> Self::Bool {
452 fn ne(self, rhs: Self) -> Self::Bool {
455 fn lt(self, rhs: Self) -> Self::Bool {
458 fn gt(self, rhs: Self) -> Self::Bool {
461 fn le(self, rhs: Self) -> Self::Bool {
464 fn ge(self, rhs: Self) -> Self::Bool {
471 impl_vector_mask_compare!(Mask8);
472 impl_vector_mask_compare!(Mask16);
473 impl_vector_mask_compare!(Mask32);
474 impl_vector_mask_compare!(Mask64);
476 macro_rules! impl_int_scalar {
478 impl<const LANES: usize> Int for Wrapper<$ty, LANES>
480 SimdI8<LANES>: LanesAtMost32,
481 SimdU8<LANES>: LanesAtMost32,
483 SimdI16<LANES>: LanesAtMost32,
484 SimdU16<LANES>: LanesAtMost32,
486 SimdI32<LANES>: LanesAtMost32,
487 SimdU32<LANES>: LanesAtMost32,
488 SimdF32<LANES>: LanesAtMost32,
490 SimdI64<LANES>: LanesAtMost32,
491 SimdU64<LANES>: LanesAtMost32,
492 SimdF64<LANES>: LanesAtMost32,
495 fn leading_zeros(self) -> Self {
496 (self.0.leading_zeros() as $ty).into()
499 fn trailing_zeros(self) -> Self {
500 (self.0.trailing_zeros() as $ty).into()
503 fn count_ones(self) -> Self {
504 (self.0.count_ones() as $ty).into()
507 fn leading_ones(self) -> Self {
508 (self.0.leading_ones() as $ty).into()
511 fn trailing_ones(self) -> Self {
512 (self.0.trailing_ones() as $ty).into()
515 fn count_zeros(self) -> Self {
516 (self.0.count_zeros() as $ty).into()
522 macro_rules! impl_int_vector {
523 ($ty:ident, $count_leading_zeros:ident, $count_trailing_zeros:ident, $count_ones:ident) => {
524 impl<const LANES: usize> Int for Wrapper<$ty<LANES>, LANES>
526 SimdI8<LANES>: LanesAtMost32,
527 SimdU8<LANES>: LanesAtMost32,
529 SimdI16<LANES>: LanesAtMost32,
530 SimdU16<LANES>: LanesAtMost32,
532 SimdI32<LANES>: LanesAtMost32,
533 SimdU32<LANES>: LanesAtMost32,
534 SimdF32<LANES>: LanesAtMost32,
536 SimdI64<LANES>: LanesAtMost32,
537 SimdU64<LANES>: LanesAtMost32,
538 SimdF64<LANES>: LanesAtMost32,
541 fn leading_zeros(self) -> Self {
542 crate::algorithms::integer::$count_leading_zeros(self.ctx(), self)
545 fn trailing_zeros(self) -> Self {
546 crate::algorithms::integer::$count_trailing_zeros(self.ctx(), self)
549 fn count_ones(self) -> Self {
550 crate::algorithms::integer::$count_ones(self.ctx(), self)
556 macro_rules! impl_uint_sint_vector {
557 ($uint:ident, $sint:ident) => {
560 count_leading_zeros_uint,
561 count_trailing_zeros_uint,
566 count_leading_zeros_sint,
567 count_trailing_zeros_sint,
570 impl<const LANES: usize> UInt for Wrapper<$uint<LANES>, LANES>
572 SimdI8<LANES>: LanesAtMost32,
573 SimdU8<LANES>: LanesAtMost32,
575 SimdI16<LANES>: LanesAtMost32,
576 SimdU16<LANES>: LanesAtMost32,
578 SimdI32<LANES>: LanesAtMost32,
579 SimdU32<LANES>: LanesAtMost32,
580 SimdF32<LANES>: LanesAtMost32,
582 SimdI64<LANES>: LanesAtMost32,
583 SimdU64<LANES>: LanesAtMost32,
584 SimdF64<LANES>: LanesAtMost32,
587 type PrimUInt = Self::Prim;
588 type SignedType = Wrapper<$sint<LANES>, LANES>;
591 impl<const LANES: usize> SInt for Wrapper<$sint<LANES>, LANES>
593 SimdI8<LANES>: LanesAtMost32,
594 SimdU8<LANES>: LanesAtMost32,
596 SimdI16<LANES>: LanesAtMost32,
597 SimdU16<LANES>: LanesAtMost32,
599 SimdI32<LANES>: LanesAtMost32,
600 SimdU32<LANES>: LanesAtMost32,
601 SimdF32<LANES>: LanesAtMost32,
603 SimdI64<LANES>: LanesAtMost32,
604 SimdU64<LANES>: LanesAtMost32,
605 SimdF64<LANES>: LanesAtMost32,
608 type PrimSInt = Self::Prim;
609 type UnsignedType = Wrapper<$uint<LANES>, LANES>;
614 impl_uint_sint_vector!(SimdU8, SimdI8);
615 impl_uint_sint_vector!(SimdU16, SimdI16);
616 impl_uint_sint_vector!(SimdU32, SimdI32);
617 impl_uint_sint_vector!(SimdU64, SimdI64);
619 macro_rules! impl_uint_sint_scalar {
620 ($uint:ident, $sint:ident) => {
621 impl_int_scalar!($uint);
622 impl_int_scalar!($sint);
623 impl<const LANES: usize> UInt for Wrapper<$uint, LANES>
625 SimdI8<LANES>: LanesAtMost32,
626 SimdU8<LANES>: LanesAtMost32,
628 SimdI16<LANES>: LanesAtMost32,
629 SimdU16<LANES>: LanesAtMost32,
631 SimdI32<LANES>: LanesAtMost32,
632 SimdU32<LANES>: LanesAtMost32,
633 SimdF32<LANES>: LanesAtMost32,
635 SimdI64<LANES>: LanesAtMost32,
636 SimdU64<LANES>: LanesAtMost32,
637 SimdF64<LANES>: LanesAtMost32,
640 type PrimUInt = Self::Prim;
641 type SignedType = Wrapper<$sint, LANES>;
644 impl<const LANES: usize> SInt for Wrapper<$sint, LANES>
646 SimdI8<LANES>: LanesAtMost32,
647 SimdU8<LANES>: LanesAtMost32,
649 SimdI16<LANES>: LanesAtMost32,
650 SimdU16<LANES>: LanesAtMost32,
652 SimdI32<LANES>: LanesAtMost32,
653 SimdU32<LANES>: LanesAtMost32,
654 SimdF32<LANES>: LanesAtMost32,
656 SimdI64<LANES>: LanesAtMost32,
657 SimdU64<LANES>: LanesAtMost32,
658 SimdF64<LANES>: LanesAtMost32,
661 type PrimSInt = Self::Prim;
662 type UnsignedType = Wrapper<$uint, LANES>;
667 impl_uint_sint_scalar!(u8, i8);
668 impl_uint_sint_scalar!(u16, i16);
669 impl_uint_sint_scalar!(u32, i32);
670 impl_uint_sint_scalar!(u64, i64);
672 macro_rules! impl_float {
673 ($ty:ident, $prim:ident, $uint:ident, $sint:ident) => {
674 impl<const LANES: usize> Float for Wrapper<$prim, LANES>
676 SimdI8<LANES>: LanesAtMost32,
677 SimdU8<LANES>: LanesAtMost32,
679 SimdI16<LANES>: LanesAtMost32,
680 SimdU16<LANES>: LanesAtMost32,
682 SimdI32<LANES>: LanesAtMost32,
683 SimdU32<LANES>: LanesAtMost32,
684 SimdF32<LANES>: LanesAtMost32,
686 SimdI64<LANES>: LanesAtMost32,
687 SimdU64<LANES>: LanesAtMost32,
688 SimdF64<LANES>: LanesAtMost32,
691 type PrimFloat = $prim;
693 type BitsType = Wrapper<<$prim as PrimFloat>::BitsType, LANES>;
695 type SignedBitsType = Wrapper<<$prim as PrimFloat>::SignedBitsType, LANES>;
697 fn abs(self) -> Self {
701 fn trunc(self) -> Self {
702 self.0.trunc().into()
705 fn ceil(self) -> Self {
709 fn floor(self) -> Self {
710 self.0.floor().into()
713 fn round(self) -> Self {
714 self.0.round().into()
717 #[cfg(feature = "fma")]
718 fn fma(self, a: Self, b: Self) -> Self {
719 use crate::scalar::Value;
722 Value(self.0).fma(a, b).0.into()
725 fn is_finite(self) -> Self::Bool {
726 self.0.is_finite().into()
729 fn from_bits(v: Self::BitsType) -> Self {
730 $prim::from_bits(v.0).into()
733 fn to_bits(self) -> Self::BitsType {
734 self.0.to_bits().into()
738 impl<const LANES: usize> Float for Wrapper<$ty<LANES>, LANES>
740 SimdI8<LANES>: LanesAtMost32,
741 SimdU8<LANES>: LanesAtMost32,
743 SimdI16<LANES>: LanesAtMost32,
744 SimdU16<LANES>: LanesAtMost32,
746 SimdI32<LANES>: LanesAtMost32,
747 SimdU32<LANES>: LanesAtMost32,
748 SimdF32<LANES>: LanesAtMost32,
750 SimdI64<LANES>: LanesAtMost32,
751 SimdU64<LANES>: LanesAtMost32,
752 SimdF64<LANES>: LanesAtMost32,
755 type PrimFloat = $prim;
757 type BitsType = Wrapper<$uint<LANES>, LANES>;
759 type SignedBitsType = Wrapper<$sint<LANES>, LANES>;
761 fn abs(self) -> Self {
765 fn trunc(self) -> Self {
766 self.0.trunc().into()
769 fn ceil(self) -> Self {
773 fn floor(self) -> Self {
774 self.0.floor().into()
777 fn round(self) -> Self {
778 self.0.round().into()
781 #[cfg(feature = "fma")]
782 fn fma(self, _a: Self, _b: Self) -> Self {
783 // FIXME(programmerjake): implement once core_simd gains support:
784 // https://github.com/rust-lang/stdsimd/issues/102
788 fn is_finite(self) -> Self::Bool {
789 self.0.is_finite().into()
792 fn from_bits(v: Self::BitsType) -> Self {
793 $ty::<LANES>::from_bits(v.0).into()
796 fn to_bits(self) -> Self::BitsType {
797 self.0.to_bits().into()
803 impl_float!(SimdF16, F16, SimdU16, SimdI16);
804 impl_float!(SimdF32, f32, SimdU32, SimdI32);
805 impl_float!(SimdF64, f64, SimdU64, SimdI64);
807 macro_rules! impl_vector_convert_from_helper {
808 ($src:ty => $dest:ty) => {
809 impl<const LANES: usize> ConvertFrom<Wrapper<$src, LANES>> for Wrapper<$dest, LANES>
811 SimdI8<LANES>: LanesAtMost32,
812 SimdU8<LANES>: LanesAtMost32,
814 SimdI16<LANES>: LanesAtMost32,
815 SimdU16<LANES>: LanesAtMost32,
817 SimdI32<LANES>: LanesAtMost32,
818 SimdU32<LANES>: LanesAtMost32,
819 SimdF32<LANES>: LanesAtMost32,
821 SimdI64<LANES>: LanesAtMost32,
822 SimdU64<LANES>: LanesAtMost32,
823 SimdF64<LANES>: LanesAtMost32,
826 fn cvt_from(v: Wrapper<$src, LANES>) -> Self {
827 let v: $dest = v.0.to();
834 macro_rules! impl_vector_convert_from {
835 ($first:ty $(, $ty:ty)*) => {
837 impl_vector_convert_from_helper!($first => $ty);
838 impl_vector_convert_from_helper!($ty => $first);
840 impl_vector_convert_from![$($ty),*];
845 impl_vector_convert_from![u8, i8, u16, i16, F16, u32, i32, u64, i64, f32, f64];
847 macro_rules! impl_vector_convert_from_helper {
848 (($(#[From = $From:ident])? $src:ident, $src_prim:ident) => ($(#[From = $From2:ident])? $dest:ident, $dest_prim:ident)) => {
849 impl<const LANES: usize> ConvertFrom<Wrapper<$src<LANES>, LANES>>
850 for Wrapper<$dest<LANES>, LANES>
852 SimdI8<LANES>: LanesAtMost32,
853 SimdU8<LANES>: LanesAtMost32,
855 SimdI16<LANES>: LanesAtMost32,
856 SimdU16<LANES>: LanesAtMost32,
858 SimdI32<LANES>: LanesAtMost32,
859 SimdU32<LANES>: LanesAtMost32,
860 SimdF32<LANES>: LanesAtMost32,
862 SimdI64<LANES>: LanesAtMost32,
863 SimdU64<LANES>: LanesAtMost32,
864 SimdF64<LANES>: LanesAtMost32,
867 fn cvt_from(v: Wrapper<$src<LANES>, LANES>) -> Self {
868 // FIXME(programmerjake): workaround https://github.com/rust-lang/stdsimd/issues/116
869 let src: [$src_prim; LANES] = v.0.into();
870 let mut dest: [$dest_prim; LANES] = [Default::default(); LANES];
872 dest[i] = src[i].to();
874 $dest::<LANES>::from(dest).into()
878 $(impl<const LANES: usize> $From<Wrapper<$src<LANES>, LANES>> for Wrapper<$dest<LANES>, LANES>
880 SimdI8<LANES>: LanesAtMost32,
881 SimdU8<LANES>: LanesAtMost32,
883 SimdI16<LANES>: LanesAtMost32,
884 SimdU16<LANES>: LanesAtMost32,
886 SimdI32<LANES>: LanesAtMost32,
887 SimdU32<LANES>: LanesAtMost32,
888 SimdF32<LANES>: LanesAtMost32,
890 SimdI64<LANES>: LanesAtMost32,
891 SimdU64<LANES>: LanesAtMost32,
892 SimdF64<LANES>: LanesAtMost32,
895 fn from(v: Wrapper<$src<LANES>, LANES>) -> Self {
902 macro_rules! impl_vector_convert_from {
903 ($first:tt $(, $ty:tt)*) => {
905 impl_vector_convert_from_helper!($first => $ty);
906 impl_vector_convert_from_helper!($ty => $first);
908 impl_vector_convert_from![$($ty),*];
913 impl_vector_convert_from![
927 impl_vector_convert_from![
950 macro_rules! impl_from_helper {
951 (#[lanes = $LANES:ident] $src:ty => $dest:ty) => {
952 impl<const $LANES: usize> From<$src> for $dest
954 SimdI8<LANES>: LanesAtMost32,
955 SimdU8<LANES>: LanesAtMost32,
957 SimdI16<LANES>: LanesAtMost32,
958 SimdU16<LANES>: LanesAtMost32,
960 SimdI32<LANES>: LanesAtMost32,
961 SimdU32<LANES>: LanesAtMost32,
962 SimdF32<LANES>: LanesAtMost32,
964 SimdI64<LANES>: LanesAtMost32,
965 SimdU64<LANES>: LanesAtMost32,
966 SimdF64<LANES>: LanesAtMost32,
969 fn from(v: $src) -> Self {
976 macro_rules! impl_from {
977 (#[lanes = $LANES:ident] $src:ty => [$($dest:ty),*]) => {
978 $(impl_from_helper!(#[lanes = $LANES] $src => $dest);)*
982 macro_rules! impl_froms {
984 #[lanes = $LANES:ident]
997 impl_from!(#[lanes = $LANES] $u8 => [$u16, $i16, $f16, $u32, $i32, $f32, $u64, $i64, $f64]);
998 impl_from!(#[lanes = $LANES] $u16 => [$u32, $i32, $f32, $u64, $i64, $f64]);
999 impl_from!(#[lanes = $LANES] $u32 => [$u64, $i64, $f64]);
1000 impl_from!(#[lanes = $LANES] $i8 => [$i16, $f16, $i32, $f32, $i64, $f64]);
1001 impl_from!(#[lanes = $LANES] $i16 => [$i32, $f32, $i64, $f64]);
1002 impl_from!(#[lanes = $LANES] $i32 => [$i64, $f64]);
1003 impl_from!(#[lanes = $LANES] $f16 => [$f32, $f64]);
1004 impl_from!(#[lanes = $LANES] $f32 => [$f64]);
1010 #[u8] Wrapper<u8, LANES>;
1011 #[i8] Wrapper<i8, LANES>;
1012 #[u16] Wrapper<u16, LANES>;
1013 #[i16] Wrapper<i16, LANES>;
1014 #[f16] Wrapper<F16, LANES>;
1015 #[u32] Wrapper<u32, LANES>;
1016 #[i32] Wrapper<i32, LANES>;
1017 #[f32] Wrapper<f32, LANES>;
1018 #[u64] Wrapper<u64, LANES>;
1019 #[i64] Wrapper<i64, LANES>;
1020 #[f64] Wrapper<f64, LANES>;
1025 #[u8] Wrapper<SimdU8<LANES>, LANES>;
1026 #[i8] Wrapper<SimdI8<LANES>, LANES>;
1027 #[u16] Wrapper<SimdU16<LANES>, LANES>;
1028 #[i16] Wrapper<SimdI16<LANES>, LANES>;
1029 #[f16] Wrapper<SimdF16<LANES>, LANES>;
1030 #[u32] Wrapper<SimdU32<LANES>, LANES>;
1031 #[i32] Wrapper<SimdI32<LANES>, LANES>;
1032 #[f32] Wrapper<SimdF32<LANES>, LANES>;
1033 #[u64] Wrapper<SimdU64<LANES>, LANES>;
1034 #[i64] Wrapper<SimdI64<LANES>, LANES>;
1035 #[f64] Wrapper<SimdF64<LANES>, LANES>;
1038 macro_rules! impl_select {
1039 ($mask:ident, $ty:ident) => {
1040 impl<const LANES: usize> Select<Wrapper<$ty<LANES>, LANES>> for Wrapper<$mask<LANES>, LANES>
1042 SimdI8<LANES>: LanesAtMost32,
1043 SimdU8<LANES>: LanesAtMost32,
1045 SimdI16<LANES>: LanesAtMost32,
1046 SimdU16<LANES>: LanesAtMost32,
1047 Mask16<LANES>: Mask,
1048 SimdI32<LANES>: LanesAtMost32,
1049 SimdU32<LANES>: LanesAtMost32,
1050 SimdF32<LANES>: LanesAtMost32,
1051 Mask32<LANES>: Mask,
1052 SimdI64<LANES>: LanesAtMost32,
1053 SimdU64<LANES>: LanesAtMost32,
1054 SimdF64<LANES>: LanesAtMost32,
1055 Mask64<LANES>: Mask,
1059 true_v: Wrapper<$ty<LANES>, LANES>,
1060 false_v: Wrapper<$ty<LANES>, LANES>,
1061 ) -> Wrapper<$ty<LANES>, LANES> {
1062 self.0.select(true_v.0, false_v.0).into()
1068 impl_select!(Mask8, SimdU8);
1069 impl_select!(Mask8, SimdI8);
1070 impl_select!(Mask16, SimdU16);
1071 impl_select!(Mask16, SimdI16);
1072 impl_select!(Mask32, SimdU32);
1073 impl_select!(Mask32, SimdI32);
1074 impl_select!(Mask32, SimdF32);
1075 impl_select!(Mask64, SimdU64);
1076 impl_select!(Mask64, SimdI64);
1077 impl_select!(Mask64, SimdF64);
1079 #[cfg(not(feature = "f16"))]
1080 impl<const LANES: usize> Select<Wrapper<SimdF16<LANES>, LANES>> for Wrapper<Mask16<LANES>, LANES>
1082 SimdI8<LANES>: LanesAtMost32,
1083 SimdU8<LANES>: LanesAtMost32,
1085 SimdI16<LANES>: LanesAtMost32,
1086 SimdU16<LANES>: LanesAtMost32,
1087 Mask16<LANES>: Mask,
1088 SimdI32<LANES>: LanesAtMost32,
1089 SimdU32<LANES>: LanesAtMost32,
1090 SimdF32<LANES>: LanesAtMost32,
1091 Mask32<LANES>: Mask,
1092 SimdI64<LANES>: LanesAtMost32,
1093 SimdU64<LANES>: LanesAtMost32,
1094 SimdF64<LANES>: LanesAtMost32,
1095 Mask64<LANES>: Mask,
1099 _true_v: Wrapper<SimdF16<LANES>, LANES>,
1100 _false_v: Wrapper<SimdF16<LANES>, LANES>,
1101 ) -> Wrapper<SimdF16<LANES>, LANES> {
1102 panic_f16_feature_disabled()
1106 macro_rules! impl_select_mask {
1108 impl<const LANES: usize> Select<Self> for Wrapper<$ty<LANES>, LANES>
1110 SimdI8<LANES>: LanesAtMost32,
1111 SimdU8<LANES>: LanesAtMost32,
1113 SimdI16<LANES>: LanesAtMost32,
1114 SimdU16<LANES>: LanesAtMost32,
1115 Mask16<LANES>: Mask,
1116 SimdI32<LANES>: LanesAtMost32,
1117 SimdU32<LANES>: LanesAtMost32,
1118 SimdF32<LANES>: LanesAtMost32,
1119 Mask32<LANES>: Mask,
1120 SimdI64<LANES>: LanesAtMost32,
1121 SimdU64<LANES>: LanesAtMost32,
1122 SimdF64<LANES>: LanesAtMost32,
1123 Mask64<LANES>: Mask,
1125 fn select(self, true_v: Self, false_v: Self) -> Self {
1126 // FIXME(programmerjake): work around https://github.com/rust-lang/stdsimd/issues/114
1127 (self & true_v) | (!self & false_v)
1133 impl_select_mask!(Mask8);
1134 impl_select_mask!(Mask16);
1135 impl_select_mask!(Mask32);
1136 impl_select_mask!(Mask64);
1138 macro_rules! impl_mask {
1140 impl<const LANES: usize> Bool for Wrapper<$mask<LANES>, LANES>
1142 SimdI8<LANES>: LanesAtMost32,
1143 SimdU8<LANES>: LanesAtMost32,
1145 SimdI16<LANES>: LanesAtMost32,
1146 SimdU16<LANES>: LanesAtMost32,
1147 Mask16<LANES>: Mask,
1148 SimdI32<LANES>: LanesAtMost32,
1149 SimdU32<LANES>: LanesAtMost32,
1150 SimdF32<LANES>: LanesAtMost32,
1151 Mask32<LANES>: Mask,
1152 SimdI64<LANES>: LanesAtMost32,
1153 SimdU64<LANES>: LanesAtMost32,
1154 SimdF64<LANES>: LanesAtMost32,
1155 Mask64<LANES>: Mask,
1166 impl<const LANES: usize> Bool for Wrapper<bool, LANES>
1168 SimdI8<LANES>: LanesAtMost32,
1169 SimdU8<LANES>: LanesAtMost32,
1171 SimdI16<LANES>: LanesAtMost32,
1172 SimdU16<LANES>: LanesAtMost32,
1173 Mask16<LANES>: Mask,
1174 SimdI32<LANES>: LanesAtMost32,
1175 SimdU32<LANES>: LanesAtMost32,
1176 SimdF32<LANES>: LanesAtMost32,
1177 Mask32<LANES>: Mask,
1178 SimdI64<LANES>: LanesAtMost32,
1179 SimdU64<LANES>: LanesAtMost32,
1180 SimdF64<LANES>: LanesAtMost32,
1181 Mask64<LANES>: Mask,
1185 macro_rules! impl_make {
1186 ($ty:ident, $prim:ident) => {
1187 impl<const LANES: usize> Make for Wrapper<$ty<LANES>, LANES>
1189 SimdI8<LANES>: LanesAtMost32,
1190 SimdU8<LANES>: LanesAtMost32,
1192 SimdI16<LANES>: LanesAtMost32,
1193 SimdU16<LANES>: LanesAtMost32,
1194 Mask16<LANES>: Mask,
1195 SimdI32<LANES>: LanesAtMost32,
1196 SimdU32<LANES>: LanesAtMost32,
1197 SimdF32<LANES>: LanesAtMost32,
1198 Mask32<LANES>: Mask,
1199 SimdI64<LANES>: LanesAtMost32,
1200 SimdU64<LANES>: LanesAtMost32,
1201 SimdF64<LANES>: LanesAtMost32,
1202 Mask64<LANES>: Mask,
1206 type Context = StdSimd<LANES>;
1208 fn ctx(self) -> Self::Context {
1212 fn make(_ctx: Self::Context, v: Self::Prim) -> Self {
1213 $ty::splat(v).into()
1217 impl<const LANES: usize> From<Wrapper<$prim, LANES>> for Wrapper<$ty<LANES>, LANES>
1219 SimdI8<LANES>: LanesAtMost32,
1220 SimdU8<LANES>: LanesAtMost32,
1222 SimdI16<LANES>: LanesAtMost32,
1223 SimdU16<LANES>: LanesAtMost32,
1224 Mask16<LANES>: Mask,
1225 SimdI32<LANES>: LanesAtMost32,
1226 SimdU32<LANES>: LanesAtMost32,
1227 SimdF32<LANES>: LanesAtMost32,
1228 Mask32<LANES>: Mask,
1229 SimdI64<LANES>: LanesAtMost32,
1230 SimdU64<LANES>: LanesAtMost32,
1231 SimdF64<LANES>: LanesAtMost32,
1232 Mask64<LANES>: Mask,
1234 fn from(v: Wrapper<$prim, LANES>) -> Self {
1235 $ty::splat(v.0).into()
1241 impl_make!(Mask8, bool);
1242 impl_make!(Mask16, bool);
1243 impl_make!(Mask32, bool);
1244 impl_make!(Mask64, bool);
1245 impl_make!(SimdI8, i8);
1246 impl_make!(SimdI16, i16);
1247 impl_make!(SimdI32, i32);
1248 impl_make!(SimdI64, i64);
1249 impl_make!(SimdU8, u8);
1250 impl_make!(SimdU16, u16);
1251 impl_make!(SimdU32, u32);
1252 impl_make!(SimdU64, u64);
1253 impl_make!(SimdF16, F16);
1254 impl_make!(SimdF32, f32);
1255 impl_make!(SimdF64, f64);
1257 impl<const LANES: usize> Context for StdSimd<LANES>
1259 SimdI8<LANES>: LanesAtMost32,
1260 SimdU8<LANES>: LanesAtMost32,
1262 SimdI16<LANES>: LanesAtMost32,
1263 SimdU16<LANES>: LanesAtMost32,
1264 Mask16<LANES>: Mask,
1265 SimdI32<LANES>: LanesAtMost32,
1266 SimdU32<LANES>: LanesAtMost32,
1267 SimdF32<LANES>: LanesAtMost32,
1268 Mask32<LANES>: Mask,
1269 SimdI64<LANES>: LanesAtMost32,
1270 SimdU64<LANES>: LanesAtMost32,
1271 SimdF64<LANES>: LanesAtMost32,
1272 Mask64<LANES>: Mask,
1274 type Bool = Wrapper<bool, LANES>;
1275 type U8 = Wrapper<u8, LANES>;
1276 type I8 = Wrapper<i8, LANES>;
1277 type U16 = Wrapper<u16, LANES>;
1278 type I16 = Wrapper<i16, LANES>;
1279 type F16 = Wrapper<F16, LANES>;
1280 type U32 = Wrapper<u32, LANES>;
1281 type I32 = Wrapper<i32, LANES>;
1282 type F32 = Wrapper<f32, LANES>;
1283 type U64 = Wrapper<u64, LANES>;
1284 type I64 = Wrapper<i64, LANES>;
1285 type F64 = Wrapper<f64, LANES>;
1286 type VecBool8 = Wrapper<Mask8<LANES>, LANES>;
1287 type VecU8 = Wrapper<SimdU8<LANES>, LANES>;
1288 type VecI8 = Wrapper<SimdI8<LANES>, LANES>;
1289 type VecBool16 = Wrapper<Mask16<LANES>, LANES>;
1290 type VecU16 = Wrapper<SimdU16<LANES>, LANES>;
1291 type VecI16 = Wrapper<SimdI16<LANES>, LANES>;
1292 type VecF16 = Wrapper<SimdF16<LANES>, LANES>;
1293 type VecBool32 = Wrapper<Mask32<LANES>, LANES>;
1294 type VecU32 = Wrapper<SimdU32<LANES>, LANES>;
1295 type VecI32 = Wrapper<SimdI32<LANES>, LANES>;
1296 type VecF32 = Wrapper<SimdF32<LANES>, LANES>;
1297 type VecBool64 = Wrapper<Mask64<LANES>, LANES>;
1298 type VecU64 = Wrapper<SimdU64<LANES>, LANES>;
1299 type VecI64 = Wrapper<SimdI64<LANES>, LANES>;
1300 type VecF64 = Wrapper<SimdF64<LANES>, LANES>;
1303 pub type ScalarBool<const LANES: usize> = Wrapper<bool, LANES>;
1304 pub type ScalarU8<const LANES: usize> = Wrapper<u8, LANES>;
1305 pub type ScalarI8<const LANES: usize> = Wrapper<i8, LANES>;
1306 pub type ScalarU16<const LANES: usize> = Wrapper<u16, LANES>;
1307 pub type ScalarI16<const LANES: usize> = Wrapper<i16, LANES>;
1308 pub type ScalarF16<const LANES: usize> = Wrapper<F16, LANES>;
1309 pub type ScalarU32<const LANES: usize> = Wrapper<u32, LANES>;
1310 pub type ScalarI32<const LANES: usize> = Wrapper<i32, LANES>;
1311 pub type ScalarF32<const LANES: usize> = Wrapper<f32, LANES>;
1312 pub type ScalarU64<const LANES: usize> = Wrapper<u64, LANES>;
1313 pub type ScalarI64<const LANES: usize> = Wrapper<i64, LANES>;
1314 pub type ScalarF64<const LANES: usize> = Wrapper<f64, LANES>;
1315 pub type VecBool8<const LANES: usize> = Wrapper<Mask8<LANES>, LANES>;
1316 pub type VecU8<const LANES: usize> = Wrapper<SimdU8<LANES>, LANES>;
1317 pub type VecI8<const LANES: usize> = Wrapper<SimdI8<LANES>, LANES>;
1318 pub type VecBool16<const LANES: usize> = Wrapper<Mask16<LANES>, LANES>;
1319 pub type VecU16<const LANES: usize> = Wrapper<SimdU16<LANES>, LANES>;
1320 pub type VecI16<const LANES: usize> = Wrapper<SimdI16<LANES>, LANES>;
1321 pub type VecF16<const LANES: usize> = Wrapper<SimdF16<LANES>, LANES>;
1322 pub type VecBool32<const LANES: usize> = Wrapper<Mask32<LANES>, LANES>;
1323 pub type VecU32<const LANES: usize> = Wrapper<SimdU32<LANES>, LANES>;
1324 pub type VecI32<const LANES: usize> = Wrapper<SimdI32<LANES>, LANES>;
1325 pub type VecF32<const LANES: usize> = Wrapper<SimdF32<LANES>, LANES>;
1326 pub type VecBool64<const LANES: usize> = Wrapper<Mask64<LANES>, LANES>;
1327 pub type VecU64<const LANES: usize> = Wrapper<SimdU64<LANES>, LANES>;
1328 pub type VecI64<const LANES: usize> = Wrapper<SimdI64<LANES>, LANES>;
1329 pub type VecF64<const LANES: usize> = Wrapper<SimdF64<LANES>, LANES>;
1334 use crate::algorithms::ilogb::{
1335 ilogb_f32, ILOGB_NAN_RESULT_F32, ILOGB_OVERFLOW_RESULT_F32, ILOGB_UNDERFLOW_RESULT_F32,
1339 fn do_ilogb_f32x4(arg: VecF32<4>) -> VecI32<4> {
1340 ilogb_f32(StdSimd::default(), arg)
1344 fn test_ilogb_f32x4() {
1345 let ctx = StdSimd::<4>::default();
1347 do_ilogb_f32x4(ctx.make(0f32)),
1348 ctx.make(ILOGB_UNDERFLOW_RESULT_F32)
1350 assert_eq!(do_ilogb_f32x4(ctx.make(1f32)), ctx.make(0));
1351 assert_eq!(do_ilogb_f32x4(ctx.make(2f32)), ctx.make(1));
1352 assert_eq!(do_ilogb_f32x4(ctx.make(3f32)), ctx.make(1));
1353 assert_eq!(do_ilogb_f32x4(ctx.make(3.99999f32)), ctx.make(1));
1354 assert_eq!(do_ilogb_f32x4(ctx.make(0.5f32)), ctx.make(-1));
1355 assert_eq!(do_ilogb_f32x4(ctx.make(0.5f32.powi(130))), ctx.make(-130));
1357 do_ilogb_f32x4(ctx.make(f32::INFINITY)),
1358 ctx.make(ILOGB_OVERFLOW_RESULT_F32)
1361 do_ilogb_f32x4(ctx.make(f32::NAN)),
1362 ctx.make(ILOGB_NAN_RESULT_F32)