Skip to content

Commit 158e240

Browse files
Merge pull request rust-lang#441 from sammysheep/shift_elements
shift_elements_{left,right}
2 parents 5fb43ca + 9392fb1 commit 158e240

File tree

2 files changed

+92
-0
lines changed

2 files changed

+92
-0
lines changed

crates/core_simd/src/swizzle.rs

+74
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,50 @@ where
251251
Rotate::<OFFSET>::swizzle(self)
252252
}
253253

254+
/// Shifts the vector elements to the left by `OFFSET`, filling in with
255+
/// `padding` from the right.
256+
#[inline]
257+
#[must_use = "method returns a new vector and does not mutate the original inputs"]
258+
pub fn shift_elements_left<const OFFSET: usize>(self, padding: T) -> Self {
259+
struct Shift<const OFFSET: usize>;
260+
261+
impl<const OFFSET: usize, const N: usize> Swizzle<N> for Shift<OFFSET> {
262+
const INDEX: [usize; N] = const {
263+
let mut index = [N; N];
264+
let mut i = 0;
265+
while i + OFFSET < N {
266+
index[i] = i + OFFSET;
267+
i += 1;
268+
}
269+
index
270+
};
271+
}
272+
273+
Shift::<OFFSET>::concat_swizzle(self, Simd::splat(padding))
274+
}
275+
276+
/// Shifts the vector elements to the right by `OFFSET`, filling in with
277+
/// `padding` from the left.
278+
#[inline]
279+
#[must_use = "method returns a new vector and does not mutate the original inputs"]
280+
pub fn shift_elements_right<const OFFSET: usize>(self, padding: T) -> Self {
281+
struct Shift<const OFFSET: usize>;
282+
283+
impl<const OFFSET: usize, const N: usize> Swizzle<N> for Shift<OFFSET> {
284+
const INDEX: [usize; N] = const {
285+
let mut index = [N; N];
286+
let mut i = OFFSET;
287+
while i < N {
288+
index[i] = i - OFFSET;
289+
i += 1;
290+
}
291+
index
292+
};
293+
}
294+
295+
Shift::<OFFSET>::concat_swizzle(self, Simd::splat(padding))
296+
}
297+
254298
/// Interleave two vectors.
255299
///
256300
/// The resulting vectors contain elements taken alternatively from `self` and `other`, first
@@ -451,6 +495,36 @@ where
451495
unsafe { Self::from_int_unchecked(self.to_int().rotate_elements_right::<OFFSET>()) }
452496
}
453497

498+
/// Shifts the mask elements to the left by `OFFSET`, filling in with
499+
/// `padding` from the right.
500+
#[inline]
501+
#[must_use = "method returns a new mask and does not mutate the original inputs"]
502+
pub fn shift_elements_left<const OFFSET: usize>(self, padding: bool) -> Self {
503+
// Safety: swizzles are safe for masks
504+
unsafe {
505+
Self::from_int_unchecked(self.to_int().shift_elements_left::<OFFSET>(if padding {
506+
T::TRUE
507+
} else {
508+
T::FALSE
509+
}))
510+
}
511+
}
512+
513+
/// Shifts the mask elements to the right by `OFFSET`, filling in with
514+
/// `padding` from the left.
515+
#[inline]
516+
#[must_use = "method returns a new mask and does not mutate the original inputs"]
517+
pub fn shift_elements_right<const OFFSET: usize>(self, padding: bool) -> Self {
518+
// Safety: swizzles are safe for masks
519+
unsafe {
520+
Self::from_int_unchecked(self.to_int().shift_elements_right::<OFFSET>(if padding {
521+
T::TRUE
522+
} else {
523+
T::FALSE
524+
}))
525+
}
526+
}
527+
454528
/// Interleave two masks.
455529
///
456530
/// The resulting masks contain elements taken alternatively from `self` and `other`, first

crates/core_simd/tests/swizzle.rs

+18
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,24 @@ fn rotate() {
4848
assert_eq!(a.rotate_elements_right::<5>().to_array(), [4, 1, 2, 3]);
4949
}
5050

51+
#[test]
52+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
53+
fn shift() {
54+
let a = Simd::from_array([1, 2, 3, 4]);
55+
assert_eq!(a.shift_elements_left::<0>(0).to_array(), [1, 2, 3, 4]);
56+
assert_eq!(a.shift_elements_left::<1>(0).to_array(), [2, 3, 4, 0]);
57+
assert_eq!(a.shift_elements_left::<2>(9).to_array(), [3, 4, 9, 9]);
58+
assert_eq!(a.shift_elements_left::<3>(8).to_array(), [4, 8, 8, 8]);
59+
assert_eq!(a.shift_elements_left::<4>(7).to_array(), [7, 7, 7, 7]);
60+
assert_eq!(a.shift_elements_left::<5>(6).to_array(), [6, 6, 6, 6]);
61+
assert_eq!(a.shift_elements_right::<0>(0).to_array(), [1, 2, 3, 4]);
62+
assert_eq!(a.shift_elements_right::<1>(0).to_array(), [0, 1, 2, 3]);
63+
assert_eq!(a.shift_elements_right::<2>(-1).to_array(), [-1, -1, 1, 2]);
64+
assert_eq!(a.shift_elements_right::<3>(-2).to_array(), [-2, -2, -2, 1]);
65+
assert_eq!(a.shift_elements_right::<4>(-3).to_array(), [-3, -3, -3, -3]);
66+
assert_eq!(a.shift_elements_right::<5>(-4).to_array(), [-4, -4, -4, -4]);
67+
}
68+
5169
#[test]
5270
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
5371
fn interleave() {

0 commit comments

Comments
 (0)