about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSamuel Shepard <vfn4@cdc.gov>2024-09-27 15:07:28 -0400
committerSamuel Shepard <vfn4@cdc.gov>2024-09-27 15:07:28 -0400
commitc7d9ad8c2cae5fcc572fe2f5ed5c88fac25c4a97 (patch)
tree34216052a9ee7b155607f52b519067627b9de7b3
parent5fb43ca86f09ef963fffb995c359c380d7beab2f (diff)
downloadrust-c7d9ad8c2cae5fcc572fe2f5ed5c88fac25c4a97.tar.gz
rust-c7d9ad8c2cae5fcc572fe2f5ed5c88fac25c4a97.zip
Add shift_elements_{left,right} for Simd and Masks
-rw-r--r--crates/core_simd/src/swizzle.rs74
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