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 {
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 {
545 fn trailing_zeros(self) -> Self {
549 fn count_ones(self) -> Self {
553 fn leading_ones(self) -> Self {
557 fn trailing_ones(self) -> Self {
561 fn count_zeros(self) -> Self {
568 macro_rules! impl_uint_sint_vector {
569 ($uint:ident, $sint:ident) => {
570 impl_int_vector!($uint);
571 impl_int_vector!($sint);
572 impl<const LANES: usize> UInt for Wrapper<$uint<LANES>, LANES>
574 SimdI8<LANES>: LanesAtMost32,
575 SimdU8<LANES>: LanesAtMost32,
577 SimdI16<LANES>: LanesAtMost32,
578 SimdU16<LANES>: LanesAtMost32,
580 SimdI32<LANES>: LanesAtMost32,
581 SimdU32<LANES>: LanesAtMost32,
582 SimdF32<LANES>: LanesAtMost32,
584 SimdI64<LANES>: LanesAtMost32,
585 SimdU64<LANES>: LanesAtMost32,
586 SimdF64<LANES>: LanesAtMost32,
589 type PrimUInt = Self::Prim;
590 type SignedType = Wrapper<$sint<LANES>, LANES>;
593 impl<const LANES: usize> SInt for Wrapper<$sint<LANES>, LANES>
595 SimdI8<LANES>: LanesAtMost32,
596 SimdU8<LANES>: LanesAtMost32,
598 SimdI16<LANES>: LanesAtMost32,
599 SimdU16<LANES>: LanesAtMost32,
601 SimdI32<LANES>: LanesAtMost32,
602 SimdU32<LANES>: LanesAtMost32,
603 SimdF32<LANES>: LanesAtMost32,
605 SimdI64<LANES>: LanesAtMost32,
606 SimdU64<LANES>: LanesAtMost32,
607 SimdF64<LANES>: LanesAtMost32,
610 type PrimSInt = Self::Prim;
611 type UnsignedType = Wrapper<$uint<LANES>, LANES>;
616 impl_uint_sint_vector!(SimdU8, SimdI8);
617 impl_uint_sint_vector!(SimdU16, SimdI16);
618 impl_uint_sint_vector!(SimdU32, SimdI32);
619 impl_uint_sint_vector!(SimdU64, SimdI64);
621 macro_rules! impl_uint_sint_scalar {
622 ($uint:ident, $sint:ident) => {
623 impl_int_scalar!($uint);
624 impl_int_scalar!($sint);
625 impl<const LANES: usize> UInt for Wrapper<$uint, LANES>
627 SimdI8<LANES>: LanesAtMost32,
628 SimdU8<LANES>: LanesAtMost32,
630 SimdI16<LANES>: LanesAtMost32,
631 SimdU16<LANES>: LanesAtMost32,
633 SimdI32<LANES>: LanesAtMost32,
634 SimdU32<LANES>: LanesAtMost32,
635 SimdF32<LANES>: LanesAtMost32,
637 SimdI64<LANES>: LanesAtMost32,
638 SimdU64<LANES>: LanesAtMost32,
639 SimdF64<LANES>: LanesAtMost32,
642 type PrimUInt = Self::Prim;
643 type SignedType = Wrapper<$sint, LANES>;
646 impl<const LANES: usize> SInt for Wrapper<$sint, LANES>
648 SimdI8<LANES>: LanesAtMost32,
649 SimdU8<LANES>: LanesAtMost32,
651 SimdI16<LANES>: LanesAtMost32,
652 SimdU16<LANES>: LanesAtMost32,
654 SimdI32<LANES>: LanesAtMost32,
655 SimdU32<LANES>: LanesAtMost32,
656 SimdF32<LANES>: LanesAtMost32,
658 SimdI64<LANES>: LanesAtMost32,
659 SimdU64<LANES>: LanesAtMost32,
660 SimdF64<LANES>: LanesAtMost32,
663 type PrimSInt = Self::Prim;
664 type UnsignedType = Wrapper<$uint, LANES>;
669 impl_uint_sint_scalar!(u8, i8);
670 impl_uint_sint_scalar!(u16, i16);
671 impl_uint_sint_scalar!(u32, i32);
672 impl_uint_sint_scalar!(u64, i64);
674 macro_rules! impl_float {
675 ($ty:ident, $prim:ident, $uint:ident, $sint:ident) => {
676 impl<const LANES: usize> Float for Wrapper<$prim, LANES>
678 SimdI8<LANES>: LanesAtMost32,
679 SimdU8<LANES>: LanesAtMost32,
681 SimdI16<LANES>: LanesAtMost32,
682 SimdU16<LANES>: LanesAtMost32,
684 SimdI32<LANES>: LanesAtMost32,
685 SimdU32<LANES>: LanesAtMost32,
686 SimdF32<LANES>: LanesAtMost32,
688 SimdI64<LANES>: LanesAtMost32,
689 SimdU64<LANES>: LanesAtMost32,
690 SimdF64<LANES>: LanesAtMost32,
693 type PrimFloat = $prim;
695 type BitsType = Wrapper<<$prim as PrimFloat>::BitsType, LANES>;
697 type SignedBitsType = Wrapper<<$prim as PrimFloat>::SignedBitsType, LANES>;
699 fn abs(self) -> Self {
703 fn trunc(self) -> Self {
704 self.0.trunc().into()
707 fn ceil(self) -> Self {
711 fn floor(self) -> Self {
712 self.0.floor().into()
715 fn round(self) -> Self {
716 self.0.round().into()
719 #[cfg(feature = "fma")]
720 fn fma(self, a: Self, b: Self) -> Self {
721 use crate::scalar::Value;
724 Value(self.0).fma(a, b).0.into()
727 fn is_finite(self) -> Self::Bool {
728 self.0.is_finite().into()
731 fn from_bits(v: Self::BitsType) -> Self {
732 $prim::from_bits(v.0).into()
735 fn to_bits(self) -> Self::BitsType {
736 self.0.to_bits().into()
740 impl<const LANES: usize> Float for Wrapper<$ty<LANES>, LANES>
742 SimdI8<LANES>: LanesAtMost32,
743 SimdU8<LANES>: LanesAtMost32,
745 SimdI16<LANES>: LanesAtMost32,
746 SimdU16<LANES>: LanesAtMost32,
748 SimdI32<LANES>: LanesAtMost32,
749 SimdU32<LANES>: LanesAtMost32,
750 SimdF32<LANES>: LanesAtMost32,
752 SimdI64<LANES>: LanesAtMost32,
753 SimdU64<LANES>: LanesAtMost32,
754 SimdF64<LANES>: LanesAtMost32,
757 type PrimFloat = $prim;
759 type BitsType = Wrapper<$uint<LANES>, LANES>;
761 type SignedBitsType = Wrapper<$sint<LANES>, LANES>;
763 fn abs(self) -> Self {
767 fn trunc(self) -> Self {
768 self.0.trunc().into()
771 fn ceil(self) -> Self {
775 fn floor(self) -> Self {
776 self.0.floor().into()
779 fn round(self) -> Self {
780 self.0.round().into()
783 #[cfg(feature = "fma")]
784 fn fma(self, _a: Self, _b: Self) -> Self {
785 // FIXME(programmerjake): implement once core_simd gains support:
786 // https://github.com/rust-lang/stdsimd/issues/102
790 fn is_finite(self) -> Self::Bool {
791 self.0.is_finite().into()
794 fn from_bits(v: Self::BitsType) -> Self {
795 $ty::<LANES>::from_bits(v.0).into()
798 fn to_bits(self) -> Self::BitsType {
799 self.0.to_bits().into()
805 impl_float!(SimdF16, F16, SimdU16, SimdI16);
806 impl_float!(SimdF32, f32, SimdU32, SimdI32);
807 impl_float!(SimdF64, f64, SimdU64, SimdI64);
809 macro_rules! impl_vector_convert_from_helper {
810 ($src:ty => $dest:ty) => {
811 impl<const LANES: usize> ConvertFrom<Wrapper<$src, LANES>> for Wrapper<$dest, LANES>
813 SimdI8<LANES>: LanesAtMost32,
814 SimdU8<LANES>: LanesAtMost32,
816 SimdI16<LANES>: LanesAtMost32,
817 SimdU16<LANES>: LanesAtMost32,
819 SimdI32<LANES>: LanesAtMost32,
820 SimdU32<LANES>: LanesAtMost32,
821 SimdF32<LANES>: LanesAtMost32,
823 SimdI64<LANES>: LanesAtMost32,
824 SimdU64<LANES>: LanesAtMost32,
825 SimdF64<LANES>: LanesAtMost32,
828 fn cvt_from(v: Wrapper<$src, LANES>) -> Self {
829 let v: $dest = v.0.to();
836 macro_rules! impl_vector_convert_from {
837 ($first:ty $(, $ty:ty)*) => {
839 impl_vector_convert_from_helper!($first => $ty);
840 impl_vector_convert_from_helper!($ty => $first);
842 impl_vector_convert_from![$($ty),*];
847 impl_vector_convert_from![u8, i8, u16, i16, F16, u32, i32, u64, i64, f32, f64];
849 macro_rules! impl_vector_convert_from_helper {
850 (($(#[From = $From:ident])? $src:ident, $src_prim:ident) => ($(#[From = $From2:ident])? $dest:ident, $dest_prim:ident)) => {
851 impl<const LANES: usize> ConvertFrom<Wrapper<$src<LANES>, LANES>>
852 for Wrapper<$dest<LANES>, LANES>
854 SimdI8<LANES>: LanesAtMost32,
855 SimdU8<LANES>: LanesAtMost32,
857 SimdI16<LANES>: LanesAtMost32,
858 SimdU16<LANES>: LanesAtMost32,
860 SimdI32<LANES>: LanesAtMost32,
861 SimdU32<LANES>: LanesAtMost32,
862 SimdF32<LANES>: LanesAtMost32,
864 SimdI64<LANES>: LanesAtMost32,
865 SimdU64<LANES>: LanesAtMost32,
866 SimdF64<LANES>: LanesAtMost32,
869 fn cvt_from(v: Wrapper<$src<LANES>, LANES>) -> Self {
870 // FIXME(programmerjake): workaround https://github.com/rust-lang/stdsimd/issues/116
871 let src: [$src_prim; LANES] = v.0.into();
872 let mut dest: [$dest_prim; LANES] = [Default::default(); LANES];
874 dest[i] = src[i].to();
876 $dest::<LANES>::from(dest).into()
880 $(impl<const LANES: usize> $From<Wrapper<$src<LANES>, LANES>> for Wrapper<$dest<LANES>, LANES>
882 SimdI8<LANES>: LanesAtMost32,
883 SimdU8<LANES>: LanesAtMost32,
885 SimdI16<LANES>: LanesAtMost32,
886 SimdU16<LANES>: LanesAtMost32,
888 SimdI32<LANES>: LanesAtMost32,
889 SimdU32<LANES>: LanesAtMost32,
890 SimdF32<LANES>: LanesAtMost32,
892 SimdI64<LANES>: LanesAtMost32,
893 SimdU64<LANES>: LanesAtMost32,
894 SimdF64<LANES>: LanesAtMost32,
897 fn from(v: Wrapper<$src<LANES>, LANES>) -> Self {
904 macro_rules! impl_vector_convert_from {
905 ($first:tt $(, $ty:tt)*) => {
907 impl_vector_convert_from_helper!($first => $ty);
908 impl_vector_convert_from_helper!($ty => $first);
910 impl_vector_convert_from![$($ty),*];
915 impl_vector_convert_from![
929 impl_vector_convert_from![
952 macro_rules! impl_from_helper {
953 (#[lanes = $LANES:ident] $src:ty => $dest:ty) => {
954 impl<const $LANES: usize> From<$src> for $dest
956 SimdI8<LANES>: LanesAtMost32,
957 SimdU8<LANES>: LanesAtMost32,
959 SimdI16<LANES>: LanesAtMost32,
960 SimdU16<LANES>: LanesAtMost32,
962 SimdI32<LANES>: LanesAtMost32,
963 SimdU32<LANES>: LanesAtMost32,
964 SimdF32<LANES>: LanesAtMost32,
966 SimdI64<LANES>: LanesAtMost32,
967 SimdU64<LANES>: LanesAtMost32,
968 SimdF64<LANES>: LanesAtMost32,
971 fn from(v: $src) -> Self {
978 macro_rules! impl_from {
979 (#[lanes = $LANES:ident] $src:ty => [$($dest:ty),*]) => {
980 $(impl_from_helper!(#[lanes = $LANES] $src => $dest);)*
984 macro_rules! impl_froms {
986 #[lanes = $LANES:ident]
999 impl_from!(#[lanes = $LANES] $u8 => [$u16, $i16, $f16, $u32, $i32, $f32, $u64, $i64, $f64]);
1000 impl_from!(#[lanes = $LANES] $u16 => [$u32, $i32, $f32, $u64, $i64, $f64]);
1001 impl_from!(#[lanes = $LANES] $u32 => [$u64, $i64, $f64]);
1002 impl_from!(#[lanes = $LANES] $i8 => [$i16, $f16, $i32, $f32, $i64, $f64]);
1003 impl_from!(#[lanes = $LANES] $i16 => [$i32, $f32, $i64, $f64]);
1004 impl_from!(#[lanes = $LANES] $i32 => [$i64, $f64]);
1005 impl_from!(#[lanes = $LANES] $f16 => [$f32, $f64]);
1006 impl_from!(#[lanes = $LANES] $f32 => [$f64]);
1012 #[u8] Wrapper<u8, LANES>;
1013 #[i8] Wrapper<i8, LANES>;
1014 #[u16] Wrapper<u16, LANES>;
1015 #[i16] Wrapper<i16, LANES>;
1016 #[f16] Wrapper<F16, LANES>;
1017 #[u32] Wrapper<u32, LANES>;
1018 #[i32] Wrapper<i32, LANES>;
1019 #[f32] Wrapper<f32, LANES>;
1020 #[u64] Wrapper<u64, LANES>;
1021 #[i64] Wrapper<i64, LANES>;
1022 #[f64] Wrapper<f64, LANES>;
1027 #[u8] Wrapper<SimdU8<LANES>, LANES>;
1028 #[i8] Wrapper<SimdI8<LANES>, LANES>;
1029 #[u16] Wrapper<SimdU16<LANES>, LANES>;
1030 #[i16] Wrapper<SimdI16<LANES>, LANES>;
1031 #[f16] Wrapper<SimdF16<LANES>, LANES>;
1032 #[u32] Wrapper<SimdU32<LANES>, LANES>;
1033 #[i32] Wrapper<SimdI32<LANES>, LANES>;
1034 #[f32] Wrapper<SimdF32<LANES>, LANES>;
1035 #[u64] Wrapper<SimdU64<LANES>, LANES>;
1036 #[i64] Wrapper<SimdI64<LANES>, LANES>;
1037 #[f64] Wrapper<SimdF64<LANES>, LANES>;
1040 macro_rules! impl_select {
1041 ($mask:ident, $ty:ident) => {
1042 impl<const LANES: usize> Select<Wrapper<$ty<LANES>, LANES>> for Wrapper<$mask<LANES>, LANES>
1044 SimdI8<LANES>: LanesAtMost32,
1045 SimdU8<LANES>: LanesAtMost32,
1047 SimdI16<LANES>: LanesAtMost32,
1048 SimdU16<LANES>: LanesAtMost32,
1049 Mask16<LANES>: Mask,
1050 SimdI32<LANES>: LanesAtMost32,
1051 SimdU32<LANES>: LanesAtMost32,
1052 SimdF32<LANES>: LanesAtMost32,
1053 Mask32<LANES>: Mask,
1054 SimdI64<LANES>: LanesAtMost32,
1055 SimdU64<LANES>: LanesAtMost32,
1056 SimdF64<LANES>: LanesAtMost32,
1057 Mask64<LANES>: Mask,
1061 true_v: Wrapper<$ty<LANES>, LANES>,
1062 false_v: Wrapper<$ty<LANES>, LANES>,
1063 ) -> Wrapper<$ty<LANES>, LANES> {
1064 self.0.select(true_v.0, false_v.0).into()
1070 impl_select!(Mask8, SimdU8);
1071 impl_select!(Mask8, SimdI8);
1072 impl_select!(Mask16, SimdU16);
1073 impl_select!(Mask16, SimdI16);
1074 impl_select!(Mask32, SimdU32);
1075 impl_select!(Mask32, SimdI32);
1076 impl_select!(Mask32, SimdF32);
1077 impl_select!(Mask64, SimdU64);
1078 impl_select!(Mask64, SimdI64);
1079 impl_select!(Mask64, SimdF64);
1081 #[cfg(not(feature = "f16"))]
1082 impl<const LANES: usize> Select<Wrapper<SimdF16<LANES>, LANES>> for Wrapper<Mask16<LANES>, LANES>
1084 SimdI8<LANES>: LanesAtMost32,
1085 SimdU8<LANES>: LanesAtMost32,
1087 SimdI16<LANES>: LanesAtMost32,
1088 SimdU16<LANES>: LanesAtMost32,
1089 Mask16<LANES>: Mask,
1090 SimdI32<LANES>: LanesAtMost32,
1091 SimdU32<LANES>: LanesAtMost32,
1092 SimdF32<LANES>: LanesAtMost32,
1093 Mask32<LANES>: Mask,
1094 SimdI64<LANES>: LanesAtMost32,
1095 SimdU64<LANES>: LanesAtMost32,
1096 SimdF64<LANES>: LanesAtMost32,
1097 Mask64<LANES>: Mask,
1101 _true_v: Wrapper<SimdF16<LANES>, LANES>,
1102 _false_v: Wrapper<SimdF16<LANES>, LANES>,
1103 ) -> Wrapper<SimdF16<LANES>, LANES> {
1104 panic_f16_feature_disabled()
1108 macro_rules! impl_select_mask {
1110 impl<const LANES: usize> Select<Self> for Wrapper<$ty<LANES>, LANES>
1112 SimdI8<LANES>: LanesAtMost32,
1113 SimdU8<LANES>: LanesAtMost32,
1115 SimdI16<LANES>: LanesAtMost32,
1116 SimdU16<LANES>: LanesAtMost32,
1117 Mask16<LANES>: Mask,
1118 SimdI32<LANES>: LanesAtMost32,
1119 SimdU32<LANES>: LanesAtMost32,
1120 SimdF32<LANES>: LanesAtMost32,
1121 Mask32<LANES>: Mask,
1122 SimdI64<LANES>: LanesAtMost32,
1123 SimdU64<LANES>: LanesAtMost32,
1124 SimdF64<LANES>: LanesAtMost32,
1125 Mask64<LANES>: Mask,
1127 fn select(self, true_v: Self, false_v: Self) -> Self {
1128 // FIXME(programmerjake): work around https://github.com/rust-lang/stdsimd/issues/114
1129 (self & true_v) | (!self & false_v)
1135 impl_select_mask!(Mask8);
1136 impl_select_mask!(Mask16);
1137 impl_select_mask!(Mask32);
1138 impl_select_mask!(Mask64);
1140 macro_rules! impl_mask {
1142 impl<const LANES: usize> Bool for Wrapper<$mask<LANES>, LANES>
1144 SimdI8<LANES>: LanesAtMost32,
1145 SimdU8<LANES>: LanesAtMost32,
1147 SimdI16<LANES>: LanesAtMost32,
1148 SimdU16<LANES>: LanesAtMost32,
1149 Mask16<LANES>: Mask,
1150 SimdI32<LANES>: LanesAtMost32,
1151 SimdU32<LANES>: LanesAtMost32,
1152 SimdF32<LANES>: LanesAtMost32,
1153 Mask32<LANES>: Mask,
1154 SimdI64<LANES>: LanesAtMost32,
1155 SimdU64<LANES>: LanesAtMost32,
1156 SimdF64<LANES>: LanesAtMost32,
1157 Mask64<LANES>: Mask,
1168 impl<const LANES: usize> Bool for Wrapper<bool, LANES>
1170 SimdI8<LANES>: LanesAtMost32,
1171 SimdU8<LANES>: LanesAtMost32,
1173 SimdI16<LANES>: LanesAtMost32,
1174 SimdU16<LANES>: LanesAtMost32,
1175 Mask16<LANES>: Mask,
1176 SimdI32<LANES>: LanesAtMost32,
1177 SimdU32<LANES>: LanesAtMost32,
1178 SimdF32<LANES>: LanesAtMost32,
1179 Mask32<LANES>: Mask,
1180 SimdI64<LANES>: LanesAtMost32,
1181 SimdU64<LANES>: LanesAtMost32,
1182 SimdF64<LANES>: LanesAtMost32,
1183 Mask64<LANES>: Mask,
1187 macro_rules! impl_make {
1188 ($ty:ident, $prim:ident) => {
1189 impl<const LANES: usize> Make for Wrapper<$ty<LANES>, LANES>
1191 SimdI8<LANES>: LanesAtMost32,
1192 SimdU8<LANES>: LanesAtMost32,
1194 SimdI16<LANES>: LanesAtMost32,
1195 SimdU16<LANES>: LanesAtMost32,
1196 Mask16<LANES>: Mask,
1197 SimdI32<LANES>: LanesAtMost32,
1198 SimdU32<LANES>: LanesAtMost32,
1199 SimdF32<LANES>: LanesAtMost32,
1200 Mask32<LANES>: Mask,
1201 SimdI64<LANES>: LanesAtMost32,
1202 SimdU64<LANES>: LanesAtMost32,
1203 SimdF64<LANES>: LanesAtMost32,
1204 Mask64<LANES>: Mask,
1208 type Context = StdSimd<LANES>;
1210 fn ctx(self) -> Self::Context {
1214 fn make(_ctx: Self::Context, v: Self::Prim) -> Self {
1215 $ty::splat(v).into()
1219 impl<const LANES: usize> From<Wrapper<$prim, LANES>> for Wrapper<$ty<LANES>, LANES>
1221 SimdI8<LANES>: LanesAtMost32,
1222 SimdU8<LANES>: LanesAtMost32,
1224 SimdI16<LANES>: LanesAtMost32,
1225 SimdU16<LANES>: LanesAtMost32,
1226 Mask16<LANES>: Mask,
1227 SimdI32<LANES>: LanesAtMost32,
1228 SimdU32<LANES>: LanesAtMost32,
1229 SimdF32<LANES>: LanesAtMost32,
1230 Mask32<LANES>: Mask,
1231 SimdI64<LANES>: LanesAtMost32,
1232 SimdU64<LANES>: LanesAtMost32,
1233 SimdF64<LANES>: LanesAtMost32,
1234 Mask64<LANES>: Mask,
1236 fn from(v: Wrapper<$prim, LANES>) -> Self {
1237 $ty::splat(v.0).into()
1243 impl_make!(Mask8, bool);
1244 impl_make!(Mask16, bool);
1245 impl_make!(Mask32, bool);
1246 impl_make!(Mask64, bool);
1247 impl_make!(SimdI8, i8);
1248 impl_make!(SimdI16, i16);
1249 impl_make!(SimdI32, i32);
1250 impl_make!(SimdI64, i64);
1251 impl_make!(SimdU8, u8);
1252 impl_make!(SimdU16, u16);
1253 impl_make!(SimdU32, u32);
1254 impl_make!(SimdU64, u64);
1255 impl_make!(SimdF16, F16);
1256 impl_make!(SimdF32, f32);
1257 impl_make!(SimdF64, f64);
1259 impl<const LANES: usize> Context for StdSimd<LANES>
1261 SimdI8<LANES>: LanesAtMost32,
1262 SimdU8<LANES>: LanesAtMost32,
1264 SimdI16<LANES>: LanesAtMost32,
1265 SimdU16<LANES>: LanesAtMost32,
1266 Mask16<LANES>: Mask,
1267 SimdI32<LANES>: LanesAtMost32,
1268 SimdU32<LANES>: LanesAtMost32,
1269 SimdF32<LANES>: LanesAtMost32,
1270 Mask32<LANES>: Mask,
1271 SimdI64<LANES>: LanesAtMost32,
1272 SimdU64<LANES>: LanesAtMost32,
1273 SimdF64<LANES>: LanesAtMost32,
1274 Mask64<LANES>: Mask,
1276 type Bool = Wrapper<bool, LANES>;
1277 type U8 = Wrapper<u8, LANES>;
1278 type I8 = Wrapper<i8, LANES>;
1279 type U16 = Wrapper<u16, LANES>;
1280 type I16 = Wrapper<i16, LANES>;
1281 type F16 = Wrapper<F16, LANES>;
1282 type U32 = Wrapper<u32, LANES>;
1283 type I32 = Wrapper<i32, LANES>;
1284 type F32 = Wrapper<f32, LANES>;
1285 type U64 = Wrapper<u64, LANES>;
1286 type I64 = Wrapper<i64, LANES>;
1287 type F64 = Wrapper<f64, LANES>;
1288 type VecBool8 = Wrapper<Mask8<LANES>, LANES>;
1289 type VecU8 = Wrapper<SimdU8<LANES>, LANES>;
1290 type VecI8 = Wrapper<SimdI8<LANES>, LANES>;
1291 type VecBool16 = Wrapper<Mask16<LANES>, LANES>;
1292 type VecU16 = Wrapper<SimdU16<LANES>, LANES>;
1293 type VecI16 = Wrapper<SimdI16<LANES>, LANES>;
1294 type VecF16 = Wrapper<SimdF16<LANES>, LANES>;
1295 type VecBool32 = Wrapper<Mask32<LANES>, LANES>;
1296 type VecU32 = Wrapper<SimdU32<LANES>, LANES>;
1297 type VecI32 = Wrapper<SimdI32<LANES>, LANES>;
1298 type VecF32 = Wrapper<SimdF32<LANES>, LANES>;
1299 type VecBool64 = Wrapper<Mask64<LANES>, LANES>;
1300 type VecU64 = Wrapper<SimdU64<LANES>, LANES>;
1301 type VecI64 = Wrapper<SimdI64<LANES>, LANES>;
1302 type VecF64 = Wrapper<SimdF64<LANES>, LANES>;
1305 pub type ScalarBool<const LANES: usize> = Wrapper<bool, LANES>;
1306 pub type ScalarU8<const LANES: usize> = Wrapper<u8, LANES>;
1307 pub type ScalarI8<const LANES: usize> = Wrapper<i8, LANES>;
1308 pub type ScalarU16<const LANES: usize> = Wrapper<u16, LANES>;
1309 pub type ScalarI16<const LANES: usize> = Wrapper<i16, LANES>;
1310 pub type ScalarF16<const LANES: usize> = Wrapper<F16, LANES>;
1311 pub type ScalarU32<const LANES: usize> = Wrapper<u32, LANES>;
1312 pub type ScalarI32<const LANES: usize> = Wrapper<i32, LANES>;
1313 pub type ScalarF32<const LANES: usize> = Wrapper<f32, LANES>;
1314 pub type ScalarU64<const LANES: usize> = Wrapper<u64, LANES>;
1315 pub type ScalarI64<const LANES: usize> = Wrapper<i64, LANES>;
1316 pub type ScalarF64<const LANES: usize> = Wrapper<f64, LANES>;
1317 pub type VecBool8<const LANES: usize> = Wrapper<Mask8<LANES>, LANES>;
1318 pub type VecU8<const LANES: usize> = Wrapper<SimdU8<LANES>, LANES>;
1319 pub type VecI8<const LANES: usize> = Wrapper<SimdI8<LANES>, LANES>;
1320 pub type VecBool16<const LANES: usize> = Wrapper<Mask16<LANES>, LANES>;
1321 pub type VecU16<const LANES: usize> = Wrapper<SimdU16<LANES>, LANES>;
1322 pub type VecI16<const LANES: usize> = Wrapper<SimdI16<LANES>, LANES>;
1323 pub type VecF16<const LANES: usize> = Wrapper<SimdF16<LANES>, LANES>;
1324 pub type VecBool32<const LANES: usize> = Wrapper<Mask32<LANES>, LANES>;
1325 pub type VecU32<const LANES: usize> = Wrapper<SimdU32<LANES>, LANES>;
1326 pub type VecI32<const LANES: usize> = Wrapper<SimdI32<LANES>, LANES>;
1327 pub type VecF32<const LANES: usize> = Wrapper<SimdF32<LANES>, LANES>;
1328 pub type VecBool64<const LANES: usize> = Wrapper<Mask64<LANES>, LANES>;
1329 pub type VecU64<const LANES: usize> = Wrapper<SimdU64<LANES>, LANES>;
1330 pub type VecI64<const LANES: usize> = Wrapper<SimdI64<LANES>, LANES>;
1331 pub type VecF64<const LANES: usize> = Wrapper<SimdF64<LANES>, LANES>;
1336 use crate::algorithms::ilogb::{
1337 ilogb_f32, ILOGB_NAN_RESULT_F32, ILOGB_OVERFLOW_RESULT_F32, ILOGB_UNDERFLOW_RESULT_F32,
1341 fn do_ilogb_f32x4(arg: VecF32<4>) -> VecI32<4> {
1342 ilogb_f32(StdSimd::default(), arg)
1346 fn test_ilogb_f32x4() {
1347 let ctx = StdSimd::<4>::default();
1349 do_ilogb_f32x4(ctx.make(0f32)),
1350 ctx.make(ILOGB_UNDERFLOW_RESULT_F32)
1352 assert_eq!(do_ilogb_f32x4(ctx.make(1f32)), ctx.make(0));
1353 assert_eq!(do_ilogb_f32x4(ctx.make(2f32)), ctx.make(1));
1354 assert_eq!(do_ilogb_f32x4(ctx.make(3f32)), ctx.make(1));
1355 assert_eq!(do_ilogb_f32x4(ctx.make(3.99999f32)), ctx.make(1));
1356 assert_eq!(do_ilogb_f32x4(ctx.make(0.5f32)), ctx.make(-1));
1357 assert_eq!(do_ilogb_f32x4(ctx.make(0.5f32.powi(130))), ctx.make(-130));
1359 do_ilogb_f32x4(ctx.make(f32::INFINITY)),
1360 ctx.make(ILOGB_OVERFLOW_RESULT_F32)
1363 do_ilogb_f32x4(ctx.make(f32::NAN)),
1364 ctx.make(ILOGB_NAN_RESULT_F32)