1 #[cfg(not(feature = "f16"))]
2 use crate::f16::panic_f16_feature_disabled;
5 traits::{Bool, Compare, Context, ConvertTo, Float, Int, Make, SInt, Select, UInt},
10 Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div,
11 DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub,
16 LanesAtMost32, Mask, Mask16, Mask32, Mask64, Mask8, SimdF32, SimdF64, SimdI16, SimdI32,
17 SimdI64, SimdI8, SimdU16, SimdU32, SimdU64, SimdU8,
20 #[cfg(not(feature = "f16"))]
24 #[derive(Copy, Clone, Debug)]
26 pub struct SimdF16<const LANES: usize>(pub(crate) SimdU16<LANES>)
28 SimdU16<LANES>: LanesAtMost32;
30 impl<const LANES: usize> SimdF16<LANES>
32 SimdU16<LANES>: LanesAtMost32,
33 SimdI16<LANES>: LanesAtMost32,
36 pub(crate) fn splat(_v: F16) -> Self {
37 panic_f16_feature_disabled()
39 pub(crate) fn abs(self) -> Self {
40 panic_f16_feature_disabled()
42 pub(crate) fn trunc(self) -> Self {
43 panic_f16_feature_disabled()
45 pub(crate) fn floor(self) -> Self {
46 panic_f16_feature_disabled()
48 pub(crate) fn ceil(self) -> Self {
49 panic_f16_feature_disabled()
51 pub(crate) fn round(self) -> Self {
52 panic_f16_feature_disabled()
54 pub(crate) fn from_bits(_v: SimdU16<LANES>) -> Self {
55 panic_f16_feature_disabled()
57 pub(crate) fn to_bits(self) -> SimdU16<LANES> {
58 panic_f16_feature_disabled()
60 pub(crate) fn is_finite(self) -> Mask16<LANES> {
61 panic_f16_feature_disabled()
63 pub(crate) fn lanes_eq(self, _rhs: Self) -> Mask16<LANES> {
64 panic_f16_feature_disabled()
66 pub(crate) fn lanes_ne(self, _rhs: Self) -> Mask16<LANES> {
67 panic_f16_feature_disabled()
69 pub(crate) fn lanes_gt(self, _rhs: Self) -> Mask16<LANES> {
70 panic_f16_feature_disabled()
72 pub(crate) fn lanes_ge(self, _rhs: Self) -> Mask16<LANES> {
73 panic_f16_feature_disabled()
75 pub(crate) fn lanes_lt(self, _rhs: Self) -> Mask16<LANES> {
76 panic_f16_feature_disabled()
78 pub(crate) fn lanes_le(self, _rhs: Self) -> Mask16<LANES> {
79 panic_f16_feature_disabled()
83 impl<const LANES: usize> From<[F16; LANES]> for SimdF16<LANES>
85 SimdU16<LANES>: LanesAtMost32,
87 fn from(_v: [F16; LANES]) -> Self {
88 panic_f16_feature_disabled()
92 impl<const LANES: usize> From<SimdF16<LANES>> for [F16; LANES]
94 SimdU16<LANES>: LanesAtMost32,
96 fn from(_v: SimdF16<LANES>) -> Self {
97 panic_f16_feature_disabled()
101 macro_rules! impl_f16_bin_op {
102 ($trait:ident, $fn:ident) => {
103 impl<const LANES: usize> $trait for SimdF16<LANES>
105 SimdU16<LANES>: LanesAtMost32,
109 fn $fn(self, _rhs: Self) -> Self::Output {
110 panic_f16_feature_disabled()
116 impl_f16_bin_op!(Add, add);
117 impl_f16_bin_op!(Sub, sub);
118 impl_f16_bin_op!(Mul, mul);
119 impl_f16_bin_op!(Div, div);
120 impl_f16_bin_op!(Rem, rem);
122 macro_rules! impl_f16_bin_assign_op {
123 ($trait:ident, $fn:ident) => {
124 impl<const LANES: usize> $trait for SimdF16<LANES>
126 SimdU16<LANES>: LanesAtMost32,
128 fn $fn(&mut self, _rhs: Self) {
129 panic_f16_feature_disabled()
135 impl_f16_bin_assign_op!(AddAssign, add_assign);
136 impl_f16_bin_assign_op!(SubAssign, sub_assign);
137 impl_f16_bin_assign_op!(MulAssign, mul_assign);
138 impl_f16_bin_assign_op!(DivAssign, div_assign);
139 impl_f16_bin_assign_op!(RemAssign, rem_assign);
141 impl<const LANES: usize> Neg for SimdF16<LANES>
143 SimdU16<LANES>: LanesAtMost32,
147 fn neg(self) -> Self::Output {
148 panic_f16_feature_disabled()
153 #[cfg(not(feature = "f16"))]
156 #[cfg(feature = "f16")]
157 compile_error!("core_simd doesn't yet support f16");
159 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default)]
160 pub struct StdSimd<const LANES: usize>(PhantomData<[(); LANES]>);
162 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)]
164 pub struct Wrapper<T, const LANES: usize>(pub T, PhantomData<[(); LANES]>);
166 impl<T, const LANES: usize> From<T> for Wrapper<T, LANES> {
167 fn from(v: T) -> Self {
168 Wrapper(v, PhantomData)
172 macro_rules! impl_bin_op_for_wrapper {
173 ($trait:ident, $fn:ident) => {
174 impl<T: $trait<Output = T>, const LANES: usize> $trait for Wrapper<T, LANES> {
177 fn $fn(self, rhs: Self) -> Self::Output {
178 self.0.$fn(rhs.0).into()
184 impl_bin_op_for_wrapper!(Add, add);
185 impl_bin_op_for_wrapper!(Sub, sub);
186 impl_bin_op_for_wrapper!(Mul, mul);
187 impl_bin_op_for_wrapper!(Div, div);
188 impl_bin_op_for_wrapper!(Rem, rem);
189 impl_bin_op_for_wrapper!(Shl, shl);
190 impl_bin_op_for_wrapper!(Shr, shr);
191 impl_bin_op_for_wrapper!(BitAnd, bitand);
192 impl_bin_op_for_wrapper!(BitOr, bitor);
193 impl_bin_op_for_wrapper!(BitXor, bitxor);
195 macro_rules! impl_bin_op_assign_for_wrapper {
196 ($trait:ident, $fn:ident) => {
197 impl<T: $trait, const LANES: usize> $trait for Wrapper<T, LANES> {
198 fn $fn(&mut self, rhs: Self) {
205 impl_bin_op_assign_for_wrapper!(AddAssign, add_assign);
206 impl_bin_op_assign_for_wrapper!(SubAssign, sub_assign);
207 impl_bin_op_assign_for_wrapper!(MulAssign, mul_assign);
208 impl_bin_op_assign_for_wrapper!(DivAssign, div_assign);
209 impl_bin_op_assign_for_wrapper!(RemAssign, rem_assign);
210 impl_bin_op_assign_for_wrapper!(ShlAssign, shl_assign);
211 impl_bin_op_assign_for_wrapper!(ShrAssign, shr_assign);
212 impl_bin_op_assign_for_wrapper!(BitAndAssign, bitand_assign);
213 impl_bin_op_assign_for_wrapper!(BitOrAssign, bitor_assign);
214 impl_bin_op_assign_for_wrapper!(BitXorAssign, bitxor_assign);
216 macro_rules! impl_un_op_for_wrapper {
217 ($trait:ident, $fn:ident) => {
218 impl<T: $trait<Output = T>, const LANES: usize> $trait for Wrapper<T, LANES> {
221 fn $fn(self) -> Self::Output {
228 impl_un_op_for_wrapper!(Not, not);
229 impl_un_op_for_wrapper!(Neg, neg);
231 macro_rules! impl_make_for_scalar {
233 impl<const LANES: usize> Make for Wrapper<$ty, LANES>
235 SimdI8<LANES>: LanesAtMost32,
236 SimdU8<LANES>: LanesAtMost32,
238 SimdI16<LANES>: LanesAtMost32,
239 SimdU16<LANES>: LanesAtMost32,
241 SimdI32<LANES>: LanesAtMost32,
242 SimdU32<LANES>: LanesAtMost32,
243 SimdF32<LANES>: LanesAtMost32,
245 SimdI64<LANES>: LanesAtMost32,
246 SimdU64<LANES>: LanesAtMost32,
247 SimdF64<LANES>: LanesAtMost32,
252 type Context = StdSimd<LANES>;
254 fn ctx(self) -> Self::Context {
258 fn make(_ctx: Self::Context, v: Self::Prim) -> Self {
265 impl_make_for_scalar!(bool);
266 impl_make_for_scalar!(i8);
267 impl_make_for_scalar!(u8);
268 impl_make_for_scalar!(i16);
269 impl_make_for_scalar!(u16);
270 impl_make_for_scalar!(F16);
271 impl_make_for_scalar!(i32);
272 impl_make_for_scalar!(u32);
273 impl_make_for_scalar!(f32);
274 impl_make_for_scalar!(i64);
275 impl_make_for_scalar!(u64);
276 impl_make_for_scalar!(f64);
278 impl<V, const LANES: usize> Select<V> for Wrapper<bool, LANES>
280 SimdI8<LANES>: LanesAtMost32,
281 SimdU8<LANES>: LanesAtMost32,
283 SimdI16<LANES>: LanesAtMost32,
284 SimdU16<LANES>: LanesAtMost32,
286 SimdI32<LANES>: LanesAtMost32,
287 SimdU32<LANES>: LanesAtMost32,
288 SimdF32<LANES>: LanesAtMost32,
290 SimdI64<LANES>: LanesAtMost32,
291 SimdU64<LANES>: LanesAtMost32,
292 SimdF64<LANES>: LanesAtMost32,
295 fn select(self, true_v: V, false_v: V) -> V {
296 self.0.select(true_v, false_v)
300 macro_rules! impl_scalar_compare {
302 impl<const LANES: usize> Compare for Wrapper<$ty, LANES>
304 SimdI8<LANES>: LanesAtMost32,
305 SimdU8<LANES>: LanesAtMost32,
307 SimdI16<LANES>: LanesAtMost32,
308 SimdU16<LANES>: LanesAtMost32,
310 SimdI32<LANES>: LanesAtMost32,
311 SimdU32<LANES>: LanesAtMost32,
312 SimdF32<LANES>: LanesAtMost32,
314 SimdI64<LANES>: LanesAtMost32,
315 SimdU64<LANES>: LanesAtMost32,
316 SimdF64<LANES>: LanesAtMost32,
319 type Bool = Wrapper<bool, LANES>;
321 fn eq(self, rhs: Self) -> Self::Bool {
322 self.0.eq(rhs.0).into()
325 fn ne(self, rhs: Self) -> Self::Bool {
326 self.0.ne(rhs.0).into()
329 fn lt(self, rhs: Self) -> Self::Bool {
330 self.0.lt(rhs.0).into()
333 fn gt(self, rhs: Self) -> Self::Bool {
334 self.0.gt(rhs.0).into()
337 fn le(self, rhs: Self) -> Self::Bool {
338 self.0.le(rhs.0).into()
341 fn ge(self, rhs: Self) -> Self::Bool {
342 self.0.ge(rhs.0).into()
348 impl_scalar_compare!(bool);
349 impl_scalar_compare!(i8);
350 impl_scalar_compare!(u8);
351 impl_scalar_compare!(i16);
352 impl_scalar_compare!(u16);
353 impl_scalar_compare!(F16);
354 impl_scalar_compare!(i32);
355 impl_scalar_compare!(u32);
356 impl_scalar_compare!(f32);
357 impl_scalar_compare!(i64);
358 impl_scalar_compare!(u64);
359 impl_scalar_compare!(f64);
361 macro_rules! impl_vector_compare {
362 ($ty:ident, $mask:ident) => {
363 impl<const LANES: usize> Compare for Wrapper<$ty<LANES>, LANES>
365 SimdI8<LANES>: LanesAtMost32,
366 SimdU8<LANES>: LanesAtMost32,
368 SimdI16<LANES>: LanesAtMost32,
369 SimdU16<LANES>: LanesAtMost32,
371 SimdI32<LANES>: LanesAtMost32,
372 SimdU32<LANES>: LanesAtMost32,
373 SimdF32<LANES>: LanesAtMost32,
375 SimdI64<LANES>: LanesAtMost32,
376 SimdU64<LANES>: LanesAtMost32,
377 SimdF64<LANES>: LanesAtMost32,
380 type Bool = Wrapper<$mask<LANES>, LANES>;
382 fn eq(self, rhs: Self) -> Self::Bool {
383 self.0.lanes_eq(rhs.0).into()
386 fn ne(self, rhs: Self) -> Self::Bool {
387 self.0.lanes_ne(rhs.0).into()
390 fn lt(self, rhs: Self) -> Self::Bool {
391 self.0.lanes_lt(rhs.0).into()
394 fn gt(self, rhs: Self) -> Self::Bool {
395 self.0.lanes_gt(rhs.0).into()
398 fn le(self, rhs: Self) -> Self::Bool {
399 self.0.lanes_le(rhs.0).into()
402 fn ge(self, rhs: Self) -> Self::Bool {
403 self.0.lanes_ge(rhs.0).into()
409 impl_vector_compare!(SimdI8, Mask8);
410 impl_vector_compare!(SimdU8, Mask8);
411 impl_vector_compare!(SimdI16, Mask16);
412 impl_vector_compare!(SimdU16, Mask16);
413 impl_vector_compare!(SimdF16, Mask16);
414 impl_vector_compare!(SimdI32, Mask32);
415 impl_vector_compare!(SimdU32, Mask32);
416 impl_vector_compare!(SimdF32, Mask32);
417 impl_vector_compare!(SimdI64, Mask64);
418 impl_vector_compare!(SimdU64, Mask64);
419 impl_vector_compare!(SimdF64, Mask64);
421 macro_rules! impl_vector_mask_compare {
423 impl<const LANES: usize> Compare for Wrapper<$ty<LANES>, LANES>
425 SimdI8<LANES>: LanesAtMost32,
426 SimdU8<LANES>: LanesAtMost32,
428 SimdI16<LANES>: LanesAtMost32,
429 SimdU16<LANES>: LanesAtMost32,
431 SimdI32<LANES>: LanesAtMost32,
432 SimdU32<LANES>: LanesAtMost32,
433 SimdF32<LANES>: LanesAtMost32,
435 SimdI64<LANES>: LanesAtMost32,
436 SimdU64<LANES>: LanesAtMost32,
437 SimdF64<LANES>: LanesAtMost32,
442 fn eq(self, rhs: Self) -> Self::Bool {
445 fn ne(self, rhs: Self) -> Self::Bool {
448 fn lt(self, rhs: Self) -> Self::Bool {
451 fn gt(self, rhs: Self) -> Self::Bool {
454 fn le(self, rhs: Self) -> Self::Bool {
457 fn ge(self, rhs: Self) -> Self::Bool {
464 impl_vector_mask_compare!(Mask8);
465 impl_vector_mask_compare!(Mask16);
466 impl_vector_mask_compare!(Mask32);
467 impl_vector_mask_compare!(Mask64);
469 macro_rules! impl_int_scalar {
471 impl<const LANES: usize> Int for Wrapper<$ty, LANES>
473 SimdI8<LANES>: LanesAtMost32,
474 SimdU8<LANES>: LanesAtMost32,
476 SimdI16<LANES>: LanesAtMost32,
477 SimdU16<LANES>: LanesAtMost32,
479 SimdI32<LANES>: LanesAtMost32,
480 SimdU32<LANES>: LanesAtMost32,
481 SimdF32<LANES>: LanesAtMost32,
483 SimdI64<LANES>: LanesAtMost32,
484 SimdU64<LANES>: LanesAtMost32,
485 SimdF64<LANES>: LanesAtMost32,
488 fn leading_zeros(self) -> Self {
489 (self.0.leading_zeros() as $ty).into()
492 fn trailing_zeros(self) -> Self {
493 (self.0.trailing_zeros() as $ty).into()
496 fn count_ones(self) -> Self {
497 (self.0.count_ones() as $ty).into()
500 fn leading_ones(self) -> Self {
501 (self.0.leading_ones() as $ty).into()
504 fn trailing_ones(self) -> Self {
505 (self.0.trailing_ones() as $ty).into()
508 fn count_zeros(self) -> Self {
509 (self.0.count_zeros() as $ty).into()
515 macro_rules! impl_int_vector {
517 impl<const LANES: usize> Int for Wrapper<$ty<LANES>, LANES>
519 SimdI8<LANES>: LanesAtMost32,
520 SimdU8<LANES>: LanesAtMost32,
522 SimdI16<LANES>: LanesAtMost32,
523 SimdU16<LANES>: LanesAtMost32,
525 SimdI32<LANES>: LanesAtMost32,
526 SimdU32<LANES>: LanesAtMost32,
527 SimdF32<LANES>: LanesAtMost32,
529 SimdI64<LANES>: LanesAtMost32,
530 SimdU64<LANES>: LanesAtMost32,
531 SimdF64<LANES>: LanesAtMost32,
534 fn leading_zeros(self) -> Self {
538 fn trailing_zeros(self) -> Self {
542 fn count_ones(self) -> Self {
546 fn leading_ones(self) -> Self {
550 fn trailing_ones(self) -> Self {
554 fn count_zeros(self) -> Self {
561 macro_rules! impl_uint_vector {
563 impl_int_vector!($ty);
564 impl<const LANES: usize> UInt for Wrapper<$ty<LANES>, LANES>
566 SimdI8<LANES>: LanesAtMost32,
567 SimdU8<LANES>: LanesAtMost32,
569 SimdI16<LANES>: LanesAtMost32,
570 SimdU16<LANES>: LanesAtMost32,
572 SimdI32<LANES>: LanesAtMost32,
573 SimdU32<LANES>: LanesAtMost32,
574 SimdF32<LANES>: LanesAtMost32,
576 SimdI64<LANES>: LanesAtMost32,
577 SimdU64<LANES>: LanesAtMost32,
578 SimdF64<LANES>: LanesAtMost32,
585 impl_uint_vector!(SimdU8);
586 impl_uint_vector!(SimdU16);
587 impl_uint_vector!(SimdU32);
588 impl_uint_vector!(SimdU64);
590 macro_rules! impl_uint_scalar {
592 impl_int_scalar!($ty);
593 impl<const LANES: usize> UInt for Wrapper<$ty, 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,
614 impl_uint_scalar!(u8);
615 impl_uint_scalar!(u16);
616 impl_uint_scalar!(u32);
617 impl_uint_scalar!(u64);
619 macro_rules! impl_sint_vector {
621 impl_int_vector!($ty);
622 impl<const LANES: usize> SInt for Wrapper<$ty<LANES>, LANES>
624 SimdI8<LANES>: LanesAtMost32,
625 SimdU8<LANES>: LanesAtMost32,
627 SimdI16<LANES>: LanesAtMost32,
628 SimdU16<LANES>: LanesAtMost32,
630 SimdI32<LANES>: LanesAtMost32,
631 SimdU32<LANES>: LanesAtMost32,
632 SimdF32<LANES>: LanesAtMost32,
634 SimdI64<LANES>: LanesAtMost32,
635 SimdU64<LANES>: LanesAtMost32,
636 SimdF64<LANES>: LanesAtMost32,
643 impl_sint_vector!(SimdI8);
644 impl_sint_vector!(SimdI16);
645 impl_sint_vector!(SimdI32);
646 impl_sint_vector!(SimdI64);
648 macro_rules! impl_sint_scalar {
650 impl_int_scalar!($ty);
651 impl<const LANES: usize> SInt for Wrapper<$ty, LANES>
653 SimdI8<LANES>: LanesAtMost32,
654 SimdU8<LANES>: LanesAtMost32,
656 SimdI16<LANES>: LanesAtMost32,
657 SimdU16<LANES>: LanesAtMost32,
659 SimdI32<LANES>: LanesAtMost32,
660 SimdU32<LANES>: LanesAtMost32,
661 SimdF32<LANES>: LanesAtMost32,
663 SimdI64<LANES>: LanesAtMost32,
664 SimdU64<LANES>: LanesAtMost32,
665 SimdF64<LANES>: LanesAtMost32,
672 impl_sint_scalar!(i8);
673 impl_sint_scalar!(i16);
674 impl_sint_scalar!(i32);
675 impl_sint_scalar!(i64);
677 macro_rules! impl_float {
678 ($ty:ident, $prim:ident, $uint:ident, $sint:ident) => {
679 impl<const LANES: usize> Float for Wrapper<$prim, LANES>
681 SimdI8<LANES>: LanesAtMost32,
682 SimdU8<LANES>: LanesAtMost32,
684 SimdI16<LANES>: LanesAtMost32,
685 SimdU16<LANES>: LanesAtMost32,
687 SimdI32<LANES>: LanesAtMost32,
688 SimdU32<LANES>: LanesAtMost32,
689 SimdF32<LANES>: LanesAtMost32,
691 SimdI64<LANES>: LanesAtMost32,
692 SimdU64<LANES>: LanesAtMost32,
693 SimdF64<LANES>: LanesAtMost32,
696 type FloatEncoding = $prim;
698 type BitsType = Wrapper<<$prim as Float>::BitsType, LANES>;
700 type SignedBitsType = Wrapper<<$prim as Float>::SignedBitsType, LANES>;
702 fn abs(self) -> Self {
706 fn trunc(self) -> Self {
707 self.0.trunc().into()
710 fn ceil(self) -> Self {
714 fn floor(self) -> Self {
715 self.0.floor().into()
718 fn round(self) -> Self {
719 self.0.round().into()
722 #[cfg(feature = "fma")]
723 fn fma(self, a: Self, b: Self) -> Self {
724 self.0.fma(a.0, 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 FloatEncoding = $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_scalar_convert_to_helper {
810 ($src:ty => $dest:ty) => {
811 impl<const LANES: usize> ConvertTo<Wrapper<$dest, LANES>> for Wrapper<$src, 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 to(self) -> Wrapper<$dest, LANES> {
829 let v: $dest = self.0.to();
836 macro_rules! impl_scalar_convert_to {
837 ($first:ty $(, $ty:ty)*) => {
839 impl_scalar_convert_to_helper!($first => $ty);
840 impl_scalar_convert_to_helper!($ty => $first);
842 impl_scalar_convert_to![$($ty),*];
847 impl_scalar_convert_to![u8, i8, u16, i16, F16, u32, i32, u64, i64, f32, f64];
849 macro_rules! impl_vector_convert_to_helper {
850 (($(#[From = $From:ident])? $src:ident, $src_prim:ident) => ($(#[From = $From2:ident])? $dest:ident, $dest_prim:ident)) => {
851 impl<const LANES: usize> ConvertTo<Wrapper<$dest<LANES>, LANES>>
852 for Wrapper<$src<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 to(self) -> Wrapper<$dest<LANES>, LANES> {
870 // FIXME(programmerjake): workaround https://github.com/rust-lang/stdsimd/issues/116
871 let src: [$src_prim; LANES] = self.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_to {
905 ($first:tt $(, $ty:tt)*) => {
907 impl_vector_convert_to_helper!($first => $ty);
908 impl_vector_convert_to_helper!($ty => $first);
910 impl_vector_convert_to![$($ty),*];
915 impl_vector_convert_to![
929 impl_vector_convert_to![
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 {
972 <$src as ConvertTo<$dest>>::to(v)
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)