1 #[cfg(not(feature = "f16"))]
2 use crate::f16::panic_f16_feature_disabled;
5 ieee754::FloatEncoding,
8 Bool, Compare, Context, ConvertFrom, ConvertTo, Float, Int, Make, SInt, Select, UInt,
14 Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div,
15 DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub,
20 LanesAtMost32, Mask, Mask16, Mask32, Mask64, Mask8, SimdF32, SimdF64, SimdI16, SimdI32,
21 SimdI64, SimdI8, SimdU16, SimdU32, SimdU64, SimdU8,
24 #[cfg(not(feature = "f16"))]
28 #[derive(Copy, Clone, Debug)]
30 pub struct SimdF16<const LANES: usize>(pub(crate) SimdU16<LANES>)
32 SimdU16<LANES>: LanesAtMost32;
34 impl<const LANES: usize> SimdF16<LANES>
36 SimdU16<LANES>: LanesAtMost32,
37 SimdI16<LANES>: LanesAtMost32,
40 pub(crate) fn splat(_v: F16) -> Self {
41 panic_f16_feature_disabled()
43 pub(crate) fn abs(self) -> Self {
44 panic_f16_feature_disabled()
46 pub(crate) fn trunc(self) -> Self {
47 panic_f16_feature_disabled()
49 pub(crate) fn floor(self) -> Self {
50 panic_f16_feature_disabled()
52 pub(crate) fn ceil(self) -> Self {
53 panic_f16_feature_disabled()
55 pub(crate) fn round(self) -> Self {
56 panic_f16_feature_disabled()
58 pub(crate) fn from_bits(_v: SimdU16<LANES>) -> Self {
59 panic_f16_feature_disabled()
61 pub(crate) fn to_bits(self) -> SimdU16<LANES> {
62 panic_f16_feature_disabled()
64 pub(crate) fn is_finite(self) -> Mask16<LANES> {
65 panic_f16_feature_disabled()
67 pub(crate) fn lanes_eq(self, _rhs: Self) -> Mask16<LANES> {
68 panic_f16_feature_disabled()
70 pub(crate) fn lanes_ne(self, _rhs: Self) -> Mask16<LANES> {
71 panic_f16_feature_disabled()
73 pub(crate) fn lanes_gt(self, _rhs: Self) -> Mask16<LANES> {
74 panic_f16_feature_disabled()
76 pub(crate) fn lanes_ge(self, _rhs: Self) -> Mask16<LANES> {
77 panic_f16_feature_disabled()
79 pub(crate) fn lanes_lt(self, _rhs: Self) -> Mask16<LANES> {
80 panic_f16_feature_disabled()
82 pub(crate) fn lanes_le(self, _rhs: Self) -> Mask16<LANES> {
83 panic_f16_feature_disabled()
87 impl<const LANES: usize> From<[F16; LANES]> for SimdF16<LANES>
89 SimdU16<LANES>: LanesAtMost32,
91 fn from(_v: [F16; LANES]) -> Self {
92 panic_f16_feature_disabled()
96 impl<const LANES: usize> From<SimdF16<LANES>> for [F16; LANES]
98 SimdU16<LANES>: LanesAtMost32,
100 fn from(_v: SimdF16<LANES>) -> Self {
101 panic_f16_feature_disabled()
105 macro_rules! impl_f16_bin_op {
106 ($trait:ident, $fn:ident) => {
107 impl<const LANES: usize> $trait for SimdF16<LANES>
109 SimdU16<LANES>: LanesAtMost32,
113 fn $fn(self, _rhs: Self) -> Self::Output {
114 panic_f16_feature_disabled()
120 impl_f16_bin_op!(Add, add);
121 impl_f16_bin_op!(Sub, sub);
122 impl_f16_bin_op!(Mul, mul);
123 impl_f16_bin_op!(Div, div);
124 impl_f16_bin_op!(Rem, rem);
126 macro_rules! impl_f16_bin_assign_op {
127 ($trait:ident, $fn:ident) => {
128 impl<const LANES: usize> $trait for SimdF16<LANES>
130 SimdU16<LANES>: LanesAtMost32,
132 fn $fn(&mut self, _rhs: Self) {
133 panic_f16_feature_disabled()
139 impl_f16_bin_assign_op!(AddAssign, add_assign);
140 impl_f16_bin_assign_op!(SubAssign, sub_assign);
141 impl_f16_bin_assign_op!(MulAssign, mul_assign);
142 impl_f16_bin_assign_op!(DivAssign, div_assign);
143 impl_f16_bin_assign_op!(RemAssign, rem_assign);
145 impl<const LANES: usize> Neg for SimdF16<LANES>
147 SimdU16<LANES>: LanesAtMost32,
151 fn neg(self) -> Self::Output {
152 panic_f16_feature_disabled()
157 #[cfg(not(feature = "f16"))]
160 #[cfg(feature = "f16")]
161 compile_error!("core_simd doesn't yet support f16");
163 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default)]
164 pub struct StdSimd<const LANES: usize>(PhantomData<[(); LANES]>);
166 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)]
168 pub struct Wrapper<T, const LANES: usize>(pub T, PhantomData<[(); LANES]>);
170 impl<T, const LANES: usize> From<T> for Wrapper<T, LANES> {
171 fn from(v: T) -> Self {
172 Wrapper(v, PhantomData)
176 macro_rules! impl_bin_op_for_wrapper {
177 ($trait:ident, $fn:ident) => {
178 impl<T: $trait<Output = T>, const LANES: usize> $trait for Wrapper<T, LANES> {
181 fn $fn(self, rhs: Self) -> Self::Output {
182 self.0.$fn(rhs.0).into()
188 impl_bin_op_for_wrapper!(Add, add);
189 impl_bin_op_for_wrapper!(Sub, sub);
190 impl_bin_op_for_wrapper!(Mul, mul);
191 impl_bin_op_for_wrapper!(Div, div);
192 impl_bin_op_for_wrapper!(Rem, rem);
193 impl_bin_op_for_wrapper!(Shl, shl);
194 impl_bin_op_for_wrapper!(Shr, shr);
195 impl_bin_op_for_wrapper!(BitAnd, bitand);
196 impl_bin_op_for_wrapper!(BitOr, bitor);
197 impl_bin_op_for_wrapper!(BitXor, bitxor);
199 macro_rules! impl_bin_op_assign_for_wrapper {
200 ($trait:ident, $fn:ident) => {
201 impl<T: $trait, const LANES: usize> $trait for Wrapper<T, LANES> {
202 fn $fn(&mut self, rhs: Self) {
209 impl_bin_op_assign_for_wrapper!(AddAssign, add_assign);
210 impl_bin_op_assign_for_wrapper!(SubAssign, sub_assign);
211 impl_bin_op_assign_for_wrapper!(MulAssign, mul_assign);
212 impl_bin_op_assign_for_wrapper!(DivAssign, div_assign);
213 impl_bin_op_assign_for_wrapper!(RemAssign, rem_assign);
214 impl_bin_op_assign_for_wrapper!(ShlAssign, shl_assign);
215 impl_bin_op_assign_for_wrapper!(ShrAssign, shr_assign);
216 impl_bin_op_assign_for_wrapper!(BitAndAssign, bitand_assign);
217 impl_bin_op_assign_for_wrapper!(BitOrAssign, bitor_assign);
218 impl_bin_op_assign_for_wrapper!(BitXorAssign, bitxor_assign);
220 macro_rules! impl_un_op_for_wrapper {
221 ($trait:ident, $fn:ident) => {
222 impl<T: $trait<Output = T>, const LANES: usize> $trait for Wrapper<T, LANES> {
225 fn $fn(self) -> Self::Output {
232 impl_un_op_for_wrapper!(Not, not);
233 impl_un_op_for_wrapper!(Neg, neg);
235 macro_rules! impl_make_for_scalar {
237 impl<const LANES: usize> Make for Wrapper<$ty, LANES>
239 SimdI8<LANES>: LanesAtMost32,
240 SimdU8<LANES>: LanesAtMost32,
242 SimdI16<LANES>: LanesAtMost32,
243 SimdU16<LANES>: LanesAtMost32,
245 SimdI32<LANES>: LanesAtMost32,
246 SimdU32<LANES>: LanesAtMost32,
247 SimdF32<LANES>: LanesAtMost32,
249 SimdI64<LANES>: LanesAtMost32,
250 SimdU64<LANES>: LanesAtMost32,
251 SimdF64<LANES>: LanesAtMost32,
256 type Context = StdSimd<LANES>;
258 fn ctx(self) -> Self::Context {
262 fn make(_ctx: Self::Context, v: Self::Prim) -> Self {
269 impl_make_for_scalar!(bool);
270 impl_make_for_scalar!(i8);
271 impl_make_for_scalar!(u8);
272 impl_make_for_scalar!(i16);
273 impl_make_for_scalar!(u16);
274 impl_make_for_scalar!(F16);
275 impl_make_for_scalar!(i32);
276 impl_make_for_scalar!(u32);
277 impl_make_for_scalar!(f32);
278 impl_make_for_scalar!(i64);
279 impl_make_for_scalar!(u64);
280 impl_make_for_scalar!(f64);
282 impl<V, const LANES: usize> Select<V> for Wrapper<bool, LANES>
284 SimdI8<LANES>: LanesAtMost32,
285 SimdU8<LANES>: LanesAtMost32,
287 SimdI16<LANES>: LanesAtMost32,
288 SimdU16<LANES>: LanesAtMost32,
290 SimdI32<LANES>: LanesAtMost32,
291 SimdU32<LANES>: LanesAtMost32,
292 SimdF32<LANES>: LanesAtMost32,
294 SimdI64<LANES>: LanesAtMost32,
295 SimdU64<LANES>: LanesAtMost32,
296 SimdF64<LANES>: LanesAtMost32,
299 fn select(self, true_v: V, false_v: V) -> V {
308 macro_rules! impl_scalar_compare {
310 impl<const LANES: usize> Compare for Wrapper<$ty, LANES>
312 SimdI8<LANES>: LanesAtMost32,
313 SimdU8<LANES>: LanesAtMost32,
315 SimdI16<LANES>: LanesAtMost32,
316 SimdU16<LANES>: LanesAtMost32,
318 SimdI32<LANES>: LanesAtMost32,
319 SimdU32<LANES>: LanesAtMost32,
320 SimdF32<LANES>: LanesAtMost32,
322 SimdI64<LANES>: LanesAtMost32,
323 SimdU64<LANES>: LanesAtMost32,
324 SimdF64<LANES>: LanesAtMost32,
327 type Bool = Wrapper<bool, LANES>;
329 fn eq(self, rhs: Self) -> Self::Bool {
330 self.0.eq(&rhs.0).into()
333 fn ne(self, rhs: Self) -> Self::Bool {
334 self.0.ne(&rhs.0).into()
337 fn lt(self, rhs: Self) -> Self::Bool {
338 self.0.lt(&rhs.0).into()
341 fn gt(self, rhs: Self) -> Self::Bool {
342 self.0.gt(&rhs.0).into()
345 fn le(self, rhs: Self) -> Self::Bool {
346 self.0.le(&rhs.0).into()
349 fn ge(self, rhs: Self) -> Self::Bool {
350 self.0.ge(&rhs.0).into()
356 impl_scalar_compare!(bool);
357 impl_scalar_compare!(i8);
358 impl_scalar_compare!(u8);
359 impl_scalar_compare!(i16);
360 impl_scalar_compare!(u16);
361 impl_scalar_compare!(F16);
362 impl_scalar_compare!(i32);
363 impl_scalar_compare!(u32);
364 impl_scalar_compare!(f32);
365 impl_scalar_compare!(i64);
366 impl_scalar_compare!(u64);
367 impl_scalar_compare!(f64);
369 macro_rules! impl_vector_compare {
370 ($ty:ident, $mask:ident) => {
371 impl<const LANES: usize> Compare for Wrapper<$ty<LANES>, LANES>
373 SimdI8<LANES>: LanesAtMost32,
374 SimdU8<LANES>: LanesAtMost32,
376 SimdI16<LANES>: LanesAtMost32,
377 SimdU16<LANES>: LanesAtMost32,
379 SimdI32<LANES>: LanesAtMost32,
380 SimdU32<LANES>: LanesAtMost32,
381 SimdF32<LANES>: LanesAtMost32,
383 SimdI64<LANES>: LanesAtMost32,
384 SimdU64<LANES>: LanesAtMost32,
385 SimdF64<LANES>: LanesAtMost32,
388 type Bool = Wrapper<$mask<LANES>, LANES>;
390 fn eq(self, rhs: Self) -> Self::Bool {
391 self.0.lanes_eq(rhs.0).into()
394 fn ne(self, rhs: Self) -> Self::Bool {
395 self.0.lanes_ne(rhs.0).into()
398 fn lt(self, rhs: Self) -> Self::Bool {
399 self.0.lanes_lt(rhs.0).into()
402 fn gt(self, rhs: Self) -> Self::Bool {
403 self.0.lanes_gt(rhs.0).into()
406 fn le(self, rhs: Self) -> Self::Bool {
407 self.0.lanes_le(rhs.0).into()
410 fn ge(self, rhs: Self) -> Self::Bool {
411 self.0.lanes_ge(rhs.0).into()
417 impl_vector_compare!(SimdI8, Mask8);
418 impl_vector_compare!(SimdU8, Mask8);
419 impl_vector_compare!(SimdI16, Mask16);
420 impl_vector_compare!(SimdU16, Mask16);
421 impl_vector_compare!(SimdF16, Mask16);
422 impl_vector_compare!(SimdI32, Mask32);
423 impl_vector_compare!(SimdU32, Mask32);
424 impl_vector_compare!(SimdF32, Mask32);
425 impl_vector_compare!(SimdI64, Mask64);
426 impl_vector_compare!(SimdU64, Mask64);
427 impl_vector_compare!(SimdF64, Mask64);
429 macro_rules! impl_vector_mask_compare {
431 impl<const LANES: usize> Compare for Wrapper<$ty<LANES>, LANES>
433 SimdI8<LANES>: LanesAtMost32,
434 SimdU8<LANES>: LanesAtMost32,
436 SimdI16<LANES>: LanesAtMost32,
437 SimdU16<LANES>: LanesAtMost32,
439 SimdI32<LANES>: LanesAtMost32,
440 SimdU32<LANES>: LanesAtMost32,
441 SimdF32<LANES>: LanesAtMost32,
443 SimdI64<LANES>: LanesAtMost32,
444 SimdU64<LANES>: LanesAtMost32,
445 SimdF64<LANES>: LanesAtMost32,
450 fn eq(self, rhs: Self) -> Self::Bool {
453 fn ne(self, rhs: Self) -> Self::Bool {
456 fn lt(self, rhs: Self) -> Self::Bool {
459 fn gt(self, rhs: Self) -> Self::Bool {
462 fn le(self, rhs: Self) -> Self::Bool {
465 fn ge(self, rhs: Self) -> Self::Bool {
472 impl_vector_mask_compare!(Mask8);
473 impl_vector_mask_compare!(Mask16);
474 impl_vector_mask_compare!(Mask32);
475 impl_vector_mask_compare!(Mask64);
477 macro_rules! impl_int_scalar {
479 impl<const LANES: usize> Int for Wrapper<$ty, LANES>
481 SimdI8<LANES>: LanesAtMost32,
482 SimdU8<LANES>: LanesAtMost32,
484 SimdI16<LANES>: LanesAtMost32,
485 SimdU16<LANES>: LanesAtMost32,
487 SimdI32<LANES>: LanesAtMost32,
488 SimdU32<LANES>: LanesAtMost32,
489 SimdF32<LANES>: LanesAtMost32,
491 SimdI64<LANES>: LanesAtMost32,
492 SimdU64<LANES>: LanesAtMost32,
493 SimdF64<LANES>: LanesAtMost32,
496 fn leading_zeros(self) -> Self {
497 (self.0.leading_zeros() as $ty).into()
500 fn trailing_zeros(self) -> Self {
501 (self.0.trailing_zeros() as $ty).into()
504 fn count_ones(self) -> Self {
505 (self.0.count_ones() as $ty).into()
508 fn leading_ones(self) -> Self {
509 (self.0.leading_ones() as $ty).into()
512 fn trailing_ones(self) -> Self {
513 (self.0.trailing_ones() as $ty).into()
516 fn count_zeros(self) -> Self {
517 (self.0.count_zeros() as $ty).into()
523 macro_rules! impl_int_vector {
525 impl<const LANES: usize> Int for Wrapper<$ty<LANES>, LANES>
527 SimdI8<LANES>: LanesAtMost32,
528 SimdU8<LANES>: LanesAtMost32,
530 SimdI16<LANES>: LanesAtMost32,
531 SimdU16<LANES>: LanesAtMost32,
533 SimdI32<LANES>: LanesAtMost32,
534 SimdU32<LANES>: LanesAtMost32,
535 SimdF32<LANES>: LanesAtMost32,
537 SimdI64<LANES>: LanesAtMost32,
538 SimdU64<LANES>: LanesAtMost32,
539 SimdF64<LANES>: LanesAtMost32,
542 fn leading_zeros(self) -> Self {
546 fn trailing_zeros(self) -> Self {
550 fn count_ones(self) -> Self {
554 fn leading_ones(self) -> Self {
558 fn trailing_ones(self) -> Self {
562 fn count_zeros(self) -> Self {
569 macro_rules! impl_uint_vector {
571 impl_int_vector!($ty);
572 impl<const LANES: usize> UInt for Wrapper<$ty<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,
593 impl_uint_vector!(SimdU8);
594 impl_uint_vector!(SimdU16);
595 impl_uint_vector!(SimdU32);
596 impl_uint_vector!(SimdU64);
598 macro_rules! impl_uint_scalar {
600 impl_int_scalar!($ty);
601 impl<const LANES: usize> UInt for Wrapper<$ty, LANES>
603 SimdI8<LANES>: LanesAtMost32,
604 SimdU8<LANES>: LanesAtMost32,
606 SimdI16<LANES>: LanesAtMost32,
607 SimdU16<LANES>: LanesAtMost32,
609 SimdI32<LANES>: LanesAtMost32,
610 SimdU32<LANES>: LanesAtMost32,
611 SimdF32<LANES>: LanesAtMost32,
613 SimdI64<LANES>: LanesAtMost32,
614 SimdU64<LANES>: LanesAtMost32,
615 SimdF64<LANES>: LanesAtMost32,
622 impl_uint_scalar!(u8);
623 impl_uint_scalar!(u16);
624 impl_uint_scalar!(u32);
625 impl_uint_scalar!(u64);
627 macro_rules! impl_sint_vector {
629 impl_int_vector!($ty);
630 impl<const LANES: usize> SInt for Wrapper<$ty<LANES>, LANES>
632 SimdI8<LANES>: LanesAtMost32,
633 SimdU8<LANES>: LanesAtMost32,
635 SimdI16<LANES>: LanesAtMost32,
636 SimdU16<LANES>: LanesAtMost32,
638 SimdI32<LANES>: LanesAtMost32,
639 SimdU32<LANES>: LanesAtMost32,
640 SimdF32<LANES>: LanesAtMost32,
642 SimdI64<LANES>: LanesAtMost32,
643 SimdU64<LANES>: LanesAtMost32,
644 SimdF64<LANES>: LanesAtMost32,
651 impl_sint_vector!(SimdI8);
652 impl_sint_vector!(SimdI16);
653 impl_sint_vector!(SimdI32);
654 impl_sint_vector!(SimdI64);
656 macro_rules! impl_sint_scalar {
658 impl_int_scalar!($ty);
659 impl<const LANES: usize> SInt for Wrapper<$ty, LANES>
661 SimdI8<LANES>: LanesAtMost32,
662 SimdU8<LANES>: LanesAtMost32,
664 SimdI16<LANES>: LanesAtMost32,
665 SimdU16<LANES>: LanesAtMost32,
667 SimdI32<LANES>: LanesAtMost32,
668 SimdU32<LANES>: LanesAtMost32,
669 SimdF32<LANES>: LanesAtMost32,
671 SimdI64<LANES>: LanesAtMost32,
672 SimdU64<LANES>: LanesAtMost32,
673 SimdF64<LANES>: LanesAtMost32,
680 impl_sint_scalar!(i8);
681 impl_sint_scalar!(i16);
682 impl_sint_scalar!(i32);
683 impl_sint_scalar!(i64);
685 macro_rules! impl_float {
686 ($ty:ident, $prim:ident, $uint:ident, $sint:ident) => {
687 impl<const LANES: usize> Float for Wrapper<$prim, LANES>
689 SimdI8<LANES>: LanesAtMost32,
690 SimdU8<LANES>: LanesAtMost32,
692 SimdI16<LANES>: LanesAtMost32,
693 SimdU16<LANES>: LanesAtMost32,
695 SimdI32<LANES>: LanesAtMost32,
696 SimdU32<LANES>: LanesAtMost32,
697 SimdF32<LANES>: LanesAtMost32,
699 SimdI64<LANES>: LanesAtMost32,
700 SimdU64<LANES>: LanesAtMost32,
701 SimdF64<LANES>: LanesAtMost32,
704 type FloatEncoding = $prim;
706 type BitsType = Wrapper<<$prim as FloatEncoding>::BitsType, LANES>;
708 type SignedBitsType = Wrapper<<$prim as FloatEncoding>::SignedBitsType, LANES>;
710 fn abs(self) -> Self {
714 fn trunc(self) -> Self {
715 self.0.trunc().into()
718 fn ceil(self) -> Self {
722 fn floor(self) -> Self {
723 self.0.floor().into()
726 fn round(self) -> Self {
727 self.0.round().into()
730 #[cfg(feature = "fma")]
731 fn fma(self, a: Self, b: Self) -> Self {
732 let a = scalar::Value(a.0);
733 let b = scalar::Value(b.0);
734 scalar::Value(self.0).fma(a, b).0.into()
737 fn is_finite(self) -> Self::Bool {
738 self.0.is_finite().into()
741 fn from_bits(v: Self::BitsType) -> Self {
742 $prim::from_bits(v.0).into()
745 fn to_bits(self) -> Self::BitsType {
746 self.0.to_bits().into()
750 impl<const LANES: usize> Float for Wrapper<$ty<LANES>, LANES>
752 SimdI8<LANES>: LanesAtMost32,
753 SimdU8<LANES>: LanesAtMost32,
755 SimdI16<LANES>: LanesAtMost32,
756 SimdU16<LANES>: LanesAtMost32,
758 SimdI32<LANES>: LanesAtMost32,
759 SimdU32<LANES>: LanesAtMost32,
760 SimdF32<LANES>: LanesAtMost32,
762 SimdI64<LANES>: LanesAtMost32,
763 SimdU64<LANES>: LanesAtMost32,
764 SimdF64<LANES>: LanesAtMost32,
767 type FloatEncoding = $prim;
769 type BitsType = Wrapper<$uint<LANES>, LANES>;
771 type SignedBitsType = Wrapper<$sint<LANES>, LANES>;
773 fn abs(self) -> Self {
777 fn trunc(self) -> Self {
778 self.0.trunc().into()
781 fn ceil(self) -> Self {
785 fn floor(self) -> Self {
786 self.0.floor().into()
789 fn round(self) -> Self {
790 self.0.round().into()
793 #[cfg(feature = "fma")]
794 fn fma(self, _a: Self, _b: Self) -> Self {
795 // FIXME(programmerjake): implement once core_simd gains support:
796 // https://github.com/rust-lang/stdsimd/issues/102
800 fn is_finite(self) -> Self::Bool {
801 self.0.is_finite().into()
804 fn from_bits(v: Self::BitsType) -> Self {
805 $ty::<LANES>::from_bits(v.0).into()
808 fn to_bits(self) -> Self::BitsType {
809 self.0.to_bits().into()
815 impl_float!(SimdF16, F16, SimdU16, SimdI16);
816 impl_float!(SimdF32, f32, SimdU32, SimdI32);
817 impl_float!(SimdF64, f64, SimdU64, SimdI64);
819 macro_rules! impl_vector_convert_from_helper {
820 ($src:ty => $dest:ty) => {
821 impl<const LANES: usize> ConvertFrom<Wrapper<$src, LANES>> for Wrapper<$dest, LANES>
823 SimdI8<LANES>: LanesAtMost32,
824 SimdU8<LANES>: LanesAtMost32,
826 SimdI16<LANES>: LanesAtMost32,
827 SimdU16<LANES>: LanesAtMost32,
829 SimdI32<LANES>: LanesAtMost32,
830 SimdU32<LANES>: LanesAtMost32,
831 SimdF32<LANES>: LanesAtMost32,
833 SimdI64<LANES>: LanesAtMost32,
834 SimdU64<LANES>: LanesAtMost32,
835 SimdF64<LANES>: LanesAtMost32,
838 fn cvt_from(v: Wrapper<$src, LANES>) -> Self {
839 let v: $dest = v.0.to();
846 macro_rules! impl_vector_convert_from {
847 ($first:ty $(, $ty:ty)*) => {
849 impl_vector_convert_from_helper!($first => $ty);
850 impl_vector_convert_from_helper!($ty => $first);
852 impl_vector_convert_from![$($ty),*];
857 impl_vector_convert_from![u8, i8, u16, i16, F16, u32, i32, u64, i64, f32, f64];
859 macro_rules! impl_vector_convert_from_helper {
860 (($(#[From = $From:ident])? $src:ident, $src_prim:ident) => ($(#[From = $From2:ident])? $dest:ident, $dest_prim:ident)) => {
861 impl<const LANES: usize> ConvertFrom<Wrapper<$src<LANES>, LANES>>
862 for Wrapper<$dest<LANES>, LANES>
864 SimdI8<LANES>: LanesAtMost32,
865 SimdU8<LANES>: LanesAtMost32,
867 SimdI16<LANES>: LanesAtMost32,
868 SimdU16<LANES>: LanesAtMost32,
870 SimdI32<LANES>: LanesAtMost32,
871 SimdU32<LANES>: LanesAtMost32,
872 SimdF32<LANES>: LanesAtMost32,
874 SimdI64<LANES>: LanesAtMost32,
875 SimdU64<LANES>: LanesAtMost32,
876 SimdF64<LANES>: LanesAtMost32,
879 fn cvt_from(v: Wrapper<$src<LANES>, LANES>) -> Self {
880 // FIXME(programmerjake): workaround https://github.com/rust-lang/stdsimd/issues/116
881 let src: [$src_prim; LANES] = v.0.into();
882 let mut dest: [$dest_prim; LANES] = [Default::default(); LANES];
884 dest[i] = src[i].to();
886 $dest::<LANES>::from(dest).into()
890 $(impl<const LANES: usize> $From<Wrapper<$src<LANES>, LANES>> for Wrapper<$dest<LANES>, LANES>
892 SimdI8<LANES>: LanesAtMost32,
893 SimdU8<LANES>: LanesAtMost32,
895 SimdI16<LANES>: LanesAtMost32,
896 SimdU16<LANES>: LanesAtMost32,
898 SimdI32<LANES>: LanesAtMost32,
899 SimdU32<LANES>: LanesAtMost32,
900 SimdF32<LANES>: LanesAtMost32,
902 SimdI64<LANES>: LanesAtMost32,
903 SimdU64<LANES>: LanesAtMost32,
904 SimdF64<LANES>: LanesAtMost32,
907 fn from(v: Wrapper<$src<LANES>, LANES>) -> Self {
914 macro_rules! impl_vector_convert_from {
915 ($first:tt $(, $ty:tt)*) => {
917 impl_vector_convert_from_helper!($first => $ty);
918 impl_vector_convert_from_helper!($ty => $first);
920 impl_vector_convert_from![$($ty),*];
925 impl_vector_convert_from![
939 impl_vector_convert_from![
962 macro_rules! impl_from_helper {
963 (#[lanes = $LANES:ident] $src:ty => $dest:ty) => {
964 impl<const $LANES: usize> From<$src> for $dest
966 SimdI8<LANES>: LanesAtMost32,
967 SimdU8<LANES>: LanesAtMost32,
969 SimdI16<LANES>: LanesAtMost32,
970 SimdU16<LANES>: LanesAtMost32,
972 SimdI32<LANES>: LanesAtMost32,
973 SimdU32<LANES>: LanesAtMost32,
974 SimdF32<LANES>: LanesAtMost32,
976 SimdI64<LANES>: LanesAtMost32,
977 SimdU64<LANES>: LanesAtMost32,
978 SimdF64<LANES>: LanesAtMost32,
981 fn from(v: $src) -> Self {
988 macro_rules! impl_from {
989 (#[lanes = $LANES:ident] $src:ty => [$($dest:ty),*]) => {
990 $(impl_from_helper!(#[lanes = $LANES] $src => $dest);)*
994 macro_rules! impl_froms {
996 #[lanes = $LANES:ident]
1009 impl_from!(#[lanes = $LANES] $u8 => [$u16, $i16, $f16, $u32, $i32, $f32, $u64, $i64, $f64]);
1010 impl_from!(#[lanes = $LANES] $u16 => [$u32, $i32, $f32, $u64, $i64, $f64]);
1011 impl_from!(#[lanes = $LANES] $u32 => [$u64, $i64, $f64]);
1012 impl_from!(#[lanes = $LANES] $i8 => [$i16, $f16, $i32, $f32, $i64, $f64]);
1013 impl_from!(#[lanes = $LANES] $i16 => [$i32, $f32, $i64, $f64]);
1014 impl_from!(#[lanes = $LANES] $i32 => [$i64, $f64]);
1015 impl_from!(#[lanes = $LANES] $f16 => [$f32, $f64]);
1016 impl_from!(#[lanes = $LANES] $f32 => [$f64]);
1022 #[u8] Wrapper<u8, LANES>;
1023 #[i8] Wrapper<i8, LANES>;
1024 #[u16] Wrapper<u16, LANES>;
1025 #[i16] Wrapper<i16, LANES>;
1026 #[f16] Wrapper<F16, LANES>;
1027 #[u32] Wrapper<u32, LANES>;
1028 #[i32] Wrapper<i32, LANES>;
1029 #[f32] Wrapper<f32, LANES>;
1030 #[u64] Wrapper<u64, LANES>;
1031 #[i64] Wrapper<i64, LANES>;
1032 #[f64] Wrapper<f64, LANES>;
1037 #[u8] Wrapper<SimdU8<LANES>, LANES>;
1038 #[i8] Wrapper<SimdI8<LANES>, LANES>;
1039 #[u16] Wrapper<SimdU16<LANES>, LANES>;
1040 #[i16] Wrapper<SimdI16<LANES>, LANES>;
1041 #[f16] Wrapper<SimdF16<LANES>, LANES>;
1042 #[u32] Wrapper<SimdU32<LANES>, LANES>;
1043 #[i32] Wrapper<SimdI32<LANES>, LANES>;
1044 #[f32] Wrapper<SimdF32<LANES>, LANES>;
1045 #[u64] Wrapper<SimdU64<LANES>, LANES>;
1046 #[i64] Wrapper<SimdI64<LANES>, LANES>;
1047 #[f64] Wrapper<SimdF64<LANES>, LANES>;
1050 macro_rules! impl_select {
1051 ($mask:ident, $ty:ident) => {
1052 impl<const LANES: usize> Select<Wrapper<$ty<LANES>, LANES>> for Wrapper<$mask<LANES>, LANES>
1054 SimdI8<LANES>: LanesAtMost32,
1055 SimdU8<LANES>: LanesAtMost32,
1057 SimdI16<LANES>: LanesAtMost32,
1058 SimdU16<LANES>: LanesAtMost32,
1059 Mask16<LANES>: Mask,
1060 SimdI32<LANES>: LanesAtMost32,
1061 SimdU32<LANES>: LanesAtMost32,
1062 SimdF32<LANES>: LanesAtMost32,
1063 Mask32<LANES>: Mask,
1064 SimdI64<LANES>: LanesAtMost32,
1065 SimdU64<LANES>: LanesAtMost32,
1066 SimdF64<LANES>: LanesAtMost32,
1067 Mask64<LANES>: Mask,
1071 true_v: Wrapper<$ty<LANES>, LANES>,
1072 false_v: Wrapper<$ty<LANES>, LANES>,
1073 ) -> Wrapper<$ty<LANES>, LANES> {
1074 self.0.select(true_v.0, false_v.0).into()
1080 impl_select!(Mask8, SimdU8);
1081 impl_select!(Mask8, SimdI8);
1082 impl_select!(Mask16, SimdU16);
1083 impl_select!(Mask16, SimdI16);
1084 impl_select!(Mask32, SimdU32);
1085 impl_select!(Mask32, SimdI32);
1086 impl_select!(Mask32, SimdF32);
1087 impl_select!(Mask64, SimdU64);
1088 impl_select!(Mask64, SimdI64);
1089 impl_select!(Mask64, SimdF64);
1091 #[cfg(not(feature = "f16"))]
1092 impl<const LANES: usize> Select<Wrapper<SimdF16<LANES>, LANES>> for Wrapper<Mask16<LANES>, LANES>
1094 SimdI8<LANES>: LanesAtMost32,
1095 SimdU8<LANES>: LanesAtMost32,
1097 SimdI16<LANES>: LanesAtMost32,
1098 SimdU16<LANES>: LanesAtMost32,
1099 Mask16<LANES>: Mask,
1100 SimdI32<LANES>: LanesAtMost32,
1101 SimdU32<LANES>: LanesAtMost32,
1102 SimdF32<LANES>: LanesAtMost32,
1103 Mask32<LANES>: Mask,
1104 SimdI64<LANES>: LanesAtMost32,
1105 SimdU64<LANES>: LanesAtMost32,
1106 SimdF64<LANES>: LanesAtMost32,
1107 Mask64<LANES>: Mask,
1111 _true_v: Wrapper<SimdF16<LANES>, LANES>,
1112 _false_v: Wrapper<SimdF16<LANES>, LANES>,
1113 ) -> Wrapper<SimdF16<LANES>, LANES> {
1114 panic_f16_feature_disabled()
1118 macro_rules! impl_select_mask {
1120 impl<const LANES: usize> Select<Self> for Wrapper<$ty<LANES>, LANES>
1122 SimdI8<LANES>: LanesAtMost32,
1123 SimdU8<LANES>: LanesAtMost32,
1125 SimdI16<LANES>: LanesAtMost32,
1126 SimdU16<LANES>: LanesAtMost32,
1127 Mask16<LANES>: Mask,
1128 SimdI32<LANES>: LanesAtMost32,
1129 SimdU32<LANES>: LanesAtMost32,
1130 SimdF32<LANES>: LanesAtMost32,
1131 Mask32<LANES>: Mask,
1132 SimdI64<LANES>: LanesAtMost32,
1133 SimdU64<LANES>: LanesAtMost32,
1134 SimdF64<LANES>: LanesAtMost32,
1135 Mask64<LANES>: Mask,
1137 fn select(self, true_v: Self, false_v: Self) -> Self {
1138 // FIXME(programmerjake): work around https://github.com/rust-lang/stdsimd/issues/114
1139 (self & true_v) | (!self & false_v)
1145 impl_select_mask!(Mask8);
1146 impl_select_mask!(Mask16);
1147 impl_select_mask!(Mask32);
1148 impl_select_mask!(Mask64);
1150 macro_rules! impl_mask {
1152 impl<const LANES: usize> Bool for Wrapper<$mask<LANES>, LANES>
1154 SimdI8<LANES>: LanesAtMost32,
1155 SimdU8<LANES>: LanesAtMost32,
1157 SimdI16<LANES>: LanesAtMost32,
1158 SimdU16<LANES>: LanesAtMost32,
1159 Mask16<LANES>: Mask,
1160 SimdI32<LANES>: LanesAtMost32,
1161 SimdU32<LANES>: LanesAtMost32,
1162 SimdF32<LANES>: LanesAtMost32,
1163 Mask32<LANES>: Mask,
1164 SimdI64<LANES>: LanesAtMost32,
1165 SimdU64<LANES>: LanesAtMost32,
1166 SimdF64<LANES>: LanesAtMost32,
1167 Mask64<LANES>: Mask,
1178 impl<const LANES: usize> Bool for Wrapper<bool, LANES>
1180 SimdI8<LANES>: LanesAtMost32,
1181 SimdU8<LANES>: LanesAtMost32,
1183 SimdI16<LANES>: LanesAtMost32,
1184 SimdU16<LANES>: LanesAtMost32,
1185 Mask16<LANES>: Mask,
1186 SimdI32<LANES>: LanesAtMost32,
1187 SimdU32<LANES>: LanesAtMost32,
1188 SimdF32<LANES>: LanesAtMost32,
1189 Mask32<LANES>: Mask,
1190 SimdI64<LANES>: LanesAtMost32,
1191 SimdU64<LANES>: LanesAtMost32,
1192 SimdF64<LANES>: LanesAtMost32,
1193 Mask64<LANES>: Mask,
1197 macro_rules! impl_make {
1198 ($ty:ident, $prim:ident) => {
1199 impl<const LANES: usize> Make for Wrapper<$ty<LANES>, LANES>
1201 SimdI8<LANES>: LanesAtMost32,
1202 SimdU8<LANES>: LanesAtMost32,
1204 SimdI16<LANES>: LanesAtMost32,
1205 SimdU16<LANES>: LanesAtMost32,
1206 Mask16<LANES>: Mask,
1207 SimdI32<LANES>: LanesAtMost32,
1208 SimdU32<LANES>: LanesAtMost32,
1209 SimdF32<LANES>: LanesAtMost32,
1210 Mask32<LANES>: Mask,
1211 SimdI64<LANES>: LanesAtMost32,
1212 SimdU64<LANES>: LanesAtMost32,
1213 SimdF64<LANES>: LanesAtMost32,
1214 Mask64<LANES>: Mask,
1218 type Context = StdSimd<LANES>;
1220 fn ctx(self) -> Self::Context {
1224 fn make(_ctx: Self::Context, v: Self::Prim) -> Self {
1225 $ty::splat(v).into()
1229 impl<const LANES: usize> From<Wrapper<$prim, LANES>> for Wrapper<$ty<LANES>, LANES>
1231 SimdI8<LANES>: LanesAtMost32,
1232 SimdU8<LANES>: LanesAtMost32,
1234 SimdI16<LANES>: LanesAtMost32,
1235 SimdU16<LANES>: LanesAtMost32,
1236 Mask16<LANES>: Mask,
1237 SimdI32<LANES>: LanesAtMost32,
1238 SimdU32<LANES>: LanesAtMost32,
1239 SimdF32<LANES>: LanesAtMost32,
1240 Mask32<LANES>: Mask,
1241 SimdI64<LANES>: LanesAtMost32,
1242 SimdU64<LANES>: LanesAtMost32,
1243 SimdF64<LANES>: LanesAtMost32,
1244 Mask64<LANES>: Mask,
1246 fn from(v: Wrapper<$prim, LANES>) -> Self {
1247 $ty::splat(v.0).into()
1253 impl_make!(Mask8, bool);
1254 impl_make!(Mask16, bool);
1255 impl_make!(Mask32, bool);
1256 impl_make!(Mask64, bool);
1257 impl_make!(SimdI8, i8);
1258 impl_make!(SimdI16, i16);
1259 impl_make!(SimdI32, i32);
1260 impl_make!(SimdI64, i64);
1261 impl_make!(SimdU8, u8);
1262 impl_make!(SimdU16, u16);
1263 impl_make!(SimdU32, u32);
1264 impl_make!(SimdU64, u64);
1265 impl_make!(SimdF16, F16);
1266 impl_make!(SimdF32, f32);
1267 impl_make!(SimdF64, f64);
1269 impl<const LANES: usize> Context for StdSimd<LANES>
1271 SimdI8<LANES>: LanesAtMost32,
1272 SimdU8<LANES>: LanesAtMost32,
1274 SimdI16<LANES>: LanesAtMost32,
1275 SimdU16<LANES>: LanesAtMost32,
1276 Mask16<LANES>: Mask,
1277 SimdI32<LANES>: LanesAtMost32,
1278 SimdU32<LANES>: LanesAtMost32,
1279 SimdF32<LANES>: LanesAtMost32,
1280 Mask32<LANES>: Mask,
1281 SimdI64<LANES>: LanesAtMost32,
1282 SimdU64<LANES>: LanesAtMost32,
1283 SimdF64<LANES>: LanesAtMost32,
1284 Mask64<LANES>: Mask,
1286 type Bool = Wrapper<bool, LANES>;
1287 type U8 = Wrapper<u8, LANES>;
1288 type I8 = Wrapper<i8, LANES>;
1289 type U16 = Wrapper<u16, LANES>;
1290 type I16 = Wrapper<i16, LANES>;
1291 type F16 = Wrapper<F16, LANES>;
1292 type U32 = Wrapper<u32, LANES>;
1293 type I32 = Wrapper<i32, LANES>;
1294 type F32 = Wrapper<f32, LANES>;
1295 type U64 = Wrapper<u64, LANES>;
1296 type I64 = Wrapper<i64, LANES>;
1297 type F64 = Wrapper<f64, LANES>;
1298 type VecBool8 = Wrapper<Mask8<LANES>, LANES>;
1299 type VecU8 = Wrapper<SimdU8<LANES>, LANES>;
1300 type VecI8 = Wrapper<SimdI8<LANES>, LANES>;
1301 type VecBool16 = Wrapper<Mask16<LANES>, LANES>;
1302 type VecU16 = Wrapper<SimdU16<LANES>, LANES>;
1303 type VecI16 = Wrapper<SimdI16<LANES>, LANES>;
1304 type VecF16 = Wrapper<SimdF16<LANES>, LANES>;
1305 type VecBool32 = Wrapper<Mask32<LANES>, LANES>;
1306 type VecU32 = Wrapper<SimdU32<LANES>, LANES>;
1307 type VecI32 = Wrapper<SimdI32<LANES>, LANES>;
1308 type VecF32 = Wrapper<SimdF32<LANES>, LANES>;
1309 type VecBool64 = Wrapper<Mask64<LANES>, LANES>;
1310 type VecU64 = Wrapper<SimdU64<LANES>, LANES>;
1311 type VecI64 = Wrapper<SimdI64<LANES>, LANES>;
1312 type VecF64 = Wrapper<SimdF64<LANES>, LANES>;
1315 pub type ScalarBool<const LANES: usize> = Wrapper<bool, LANES>;
1316 pub type ScalarU8<const LANES: usize> = Wrapper<u8, LANES>;
1317 pub type ScalarI8<const LANES: usize> = Wrapper<i8, LANES>;
1318 pub type ScalarU16<const LANES: usize> = Wrapper<u16, LANES>;
1319 pub type ScalarI16<const LANES: usize> = Wrapper<i16, LANES>;
1320 pub type ScalarF16<const LANES: usize> = Wrapper<F16, LANES>;
1321 pub type ScalarU32<const LANES: usize> = Wrapper<u32, LANES>;
1322 pub type ScalarI32<const LANES: usize> = Wrapper<i32, LANES>;
1323 pub type ScalarF32<const LANES: usize> = Wrapper<f32, LANES>;
1324 pub type ScalarU64<const LANES: usize> = Wrapper<u64, LANES>;
1325 pub type ScalarI64<const LANES: usize> = Wrapper<i64, LANES>;
1326 pub type ScalarF64<const LANES: usize> = Wrapper<f64, LANES>;
1327 pub type VecBool8<const LANES: usize> = Wrapper<Mask8<LANES>, LANES>;
1328 pub type VecU8<const LANES: usize> = Wrapper<SimdU8<LANES>, LANES>;
1329 pub type VecI8<const LANES: usize> = Wrapper<SimdI8<LANES>, LANES>;
1330 pub type VecBool16<const LANES: usize> = Wrapper<Mask16<LANES>, LANES>;
1331 pub type VecU16<const LANES: usize> = Wrapper<SimdU16<LANES>, LANES>;
1332 pub type VecI16<const LANES: usize> = Wrapper<SimdI16<LANES>, LANES>;
1333 pub type VecF16<const LANES: usize> = Wrapper<SimdF16<LANES>, LANES>;
1334 pub type VecBool32<const LANES: usize> = Wrapper<Mask32<LANES>, LANES>;
1335 pub type VecU32<const LANES: usize> = Wrapper<SimdU32<LANES>, LANES>;
1336 pub type VecI32<const LANES: usize> = Wrapper<SimdI32<LANES>, LANES>;
1337 pub type VecF32<const LANES: usize> = Wrapper<SimdF32<LANES>, LANES>;
1338 pub type VecBool64<const LANES: usize> = Wrapper<Mask64<LANES>, LANES>;
1339 pub type VecU64<const LANES: usize> = Wrapper<SimdU64<LANES>, LANES>;
1340 pub type VecI64<const LANES: usize> = Wrapper<SimdI64<LANES>, LANES>;
1341 pub type VecF64<const LANES: usize> = Wrapper<SimdF64<LANES>, LANES>;
1346 use crate::algorithms::ilogb::{
1347 ilogb_f32, ILOGB_NAN_RESULT_F32, ILOGB_OVERFLOW_RESULT_F32, ILOGB_UNDERFLOW_RESULT_F32,
1351 fn do_ilogb_f32x4(arg: VecF32<4>) -> VecI32<4> {
1352 ilogb_f32(StdSimd::default(), arg)
1356 fn test_ilogb_f32x4() {
1357 let ctx = StdSimd::<4>::default();
1359 do_ilogb_f32x4(ctx.make(0f32)),
1360 ctx.make(ILOGB_UNDERFLOW_RESULT_F32)
1362 assert_eq!(do_ilogb_f32x4(ctx.make(1f32)), ctx.make(0));
1363 assert_eq!(do_ilogb_f32x4(ctx.make(2f32)), ctx.make(1));
1364 assert_eq!(do_ilogb_f32x4(ctx.make(3f32)), ctx.make(1));
1365 assert_eq!(do_ilogb_f32x4(ctx.make(3.99999f32)), ctx.make(1));
1366 assert_eq!(do_ilogb_f32x4(ctx.make(0.5f32)), ctx.make(-1));
1367 assert_eq!(do_ilogb_f32x4(ctx.make(0.5f32.powi(130))), ctx.make(-130));
1369 do_ilogb_f32x4(ctx.make(f32::INFINITY)),
1370 ctx.make(ILOGB_OVERFLOW_RESULT_F32)
1373 do_ilogb_f32x4(ctx.make(f32::NAN)),
1374 ctx.make(ILOGB_NAN_RESULT_F32)