1 | // Shift operations uniquely typically only have a scalar on the right-hand side. |
2 | // Here, we implement shifts for scalar RHS arguments. |
3 | |
4 | use crate::simd::{LaneCount, Simd, SupportedLaneCount}; |
5 | |
6 | macro_rules! impl_splatted_shifts { |
7 | { impl $trait:ident :: $trait_fn:ident for $ty:ty } => { |
8 | impl<const N: usize> core::ops::$trait<$ty> for Simd<$ty, N> |
9 | where |
10 | LaneCount<N>: SupportedLaneCount, |
11 | { |
12 | type Output = Self; |
13 | #[inline] |
14 | fn $trait_fn(self, rhs: $ty) -> Self::Output { |
15 | self.$trait_fn(Simd::splat(rhs)) |
16 | } |
17 | } |
18 | |
19 | impl<const N: usize> core::ops::$trait<&$ty> for Simd<$ty, N> |
20 | where |
21 | LaneCount<N>: SupportedLaneCount, |
22 | { |
23 | type Output = Self; |
24 | #[inline] |
25 | fn $trait_fn(self, rhs: &$ty) -> Self::Output { |
26 | self.$trait_fn(Simd::splat(*rhs)) |
27 | } |
28 | } |
29 | |
30 | impl<'lhs, const N: usize> core::ops::$trait<$ty> for &'lhs Simd<$ty, N> |
31 | where |
32 | LaneCount<N>: SupportedLaneCount, |
33 | { |
34 | type Output = Simd<$ty, N>; |
35 | #[inline] |
36 | fn $trait_fn(self, rhs: $ty) -> Self::Output { |
37 | self.$trait_fn(Simd::splat(rhs)) |
38 | } |
39 | } |
40 | |
41 | impl<'lhs, const N: usize> core::ops::$trait<&$ty> for &'lhs Simd<$ty, N> |
42 | where |
43 | LaneCount<N>: SupportedLaneCount, |
44 | { |
45 | type Output = Simd<$ty, N>; |
46 | #[inline] |
47 | fn $trait_fn(self, rhs: &$ty) -> Self::Output { |
48 | self.$trait_fn(Simd::splat(*rhs)) |
49 | } |
50 | } |
51 | }; |
52 | { $($ty:ty),* } => { |
53 | $( |
54 | impl_splatted_shifts! { impl Shl::shl for $ty } |
55 | impl_splatted_shifts! { impl Shr::shr for $ty } |
56 | )* |
57 | } |
58 | } |
59 | |
60 | // In the past there were inference issues when generically splatting arguments. |
61 | // Enumerate them instead. |
62 | impl_splatted_shifts! { i8, i16, i32, i64, isize, u8, u16, u32, u64, usize } |
63 | |