diff options
| author | Samuel Shepard <vfn4@cdc.gov> | 2024-09-27 15:07:28 -0400 |
|---|---|---|
| committer | Samuel Shepard <vfn4@cdc.gov> | 2024-09-27 15:07:28 -0400 |
| commit | c7d9ad8c2cae5fcc572fe2f5ed5c88fac25c4a97 (patch) | |
| tree | 34216052a9ee7b155607f52b519067627b9de7b3 | |
| parent | 5fb43ca86f09ef963fffb995c359c380d7beab2f (diff) | |
| download | rust-c7d9ad8c2cae5fcc572fe2f5ed5c88fac25c4a97.tar.gz rust-c7d9ad8c2cae5fcc572fe2f5ed5c88fac25c4a97.zip | |
Add shift_elements_{left,right} for Simd and Masks
| -rw-r--r-- | crates/core_simd/src/swizzle.rs | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/crates/core_simd/src/swizzle.rs b/crates/core_simd/src/swizzle.rs index e0edb2cf10a..9fa6a7da8d7 100644 --- a/crates/core_simd/src/swizzle.rs +++ b/crates/core_simd/src/swizzle.rs @@ -251,6 +251,56 @@ where Rotate::<OFFSET>::swizzle(self) } + /// Shifts the vector elements to the left by `OFFSET`, padding by the + /// default value (e.g., zero) to the right. + #[inline] + #[must_use = "method returns a new vector and does not mutate the original inputs"] + fn shift_elements_left<const OFFSET: usize>(self) -> Self + where + T: Default, + { + struct Shift<const OFFSET: usize>; + + impl<const OFFSET: usize, const N: usize> Swizzle<N> for Shift<OFFSET> { + const INDEX: [usize; N] = const { + let mut index = [N; N]; + let mut i = 0; + while i + OFFSET < N { + index[i] = i + OFFSET; + i += 1; + } + index + }; + } + + Shift::<OFFSET>::concat_swizzle(self, Self::default()) + } + + /// Shifts the vector elements to the right by `OFFSET`, padding by the + /// default value (e.g., zero) from the left. + #[inline] + #[must_use = "method returns a new vector and does not mutate the original inputs"] + fn shift_elements_right<const OFFSET: usize>(self) -> Self + where + T: Default, + { + struct Shift<const OFFSET: usize>; + + impl<const OFFSET: usize, const N: usize> Swizzle<N> for Shift<OFFSET> { + const INDEX: [usize; N] = const { + let mut index = [N; N]; + let mut i = OFFSET; + while i < N { + index[i] = i - OFFSET; + i += 1; + } + index + }; + } + + Shift::<OFFSET>::concat_swizzle(self, Self::default()) + } + /// Interleave two vectors. /// /// The resulting vectors contain elements taken alternatively from `self` and `other`, first @@ -451,6 +501,30 @@ where unsafe { Self::from_int_unchecked(self.to_int().rotate_elements_right::<OFFSET>()) } } + /// Shifts the mask elements to the left by `OFFSET`, padding by the + /// default value (e.g., zero) to the right. + #[inline] + #[must_use = "method returns a new vector and does not mutate the original inputs"] + pub fn shift_elements_left<const OFFSET: usize>(self) -> Self + where + T: Default, + { + // Safety: swizzles are safe for masks + unsafe { Self::from_int_unchecked(self.to_int().shift_elements_left::<OFFSET>()) } + } + + /// Shifts the mask elements to the right by `OFFSET`, padding by the + /// default value (e.g., `false`) from the left. + #[inline] + #[must_use = "method returns a new vector and does not mutate the original inputs"] + pub fn shift_elements_right<const OFFSET: usize>(self) -> Self + where + T: Default, + { + // Safety: swizzles are safe for masks + unsafe { Self::from_int_unchecked(self.to_int().shift_elements_right::<OFFSET>()) } + } + /// Interleave two masks. /// /// The resulting masks contain elements taken alternatively from `self` and `other`, first |
