Skip to content

Commit 1271a3f

Browse files
author
TheIronBorn
committed
add rotate_left/right
1 parent dda4072 commit 1271a3f

File tree

3 files changed

+89
-2
lines changed

3 files changed

+89
-2
lines changed

coresimd/ppsv/api/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ mod masks_select;
124124
mod scalar_shifts;
125125
#[macro_use]
126126
mod shifts;
127+
#[macro_use]
128+
mod rotates;
127129

128130
/// Sealed trait used for constraining select implementations.
129131
pub trait Lanes<A> {}
@@ -191,6 +193,7 @@ macro_rules! simd_i_ty {
191193
[impl_bitwise_reductions, $id, $elem_ty],
192194
[impl_all_scalar_shifts, $id, $elem_ty],
193195
[impl_vector_shifts, $id, $elem_ty],
196+
[impl_vector_rotates, $id, $elem_ty],
194197
[impl_hex_fmt, $id, $elem_ty],
195198
[impl_eq, $id],
196199
[impl_partial_eq, $id],
@@ -215,6 +218,7 @@ macro_rules! simd_i_ty {
215218
test_bitwise_reductions!($id, !(0 as $elem_ty));
216219
test_all_scalar_shift_ops!($id, $elem_ty);
217220
test_vector_shift_ops!($id, $elem_ty);
221+
test_vector_rotate_ops!($id, $elem_ty);
218222
test_hex_fmt!($id, $elem_ty);
219223
test_partial_eq!($id, 1 as $elem_ty, 0 as $elem_ty);
220224
test_default!($id, $elem_ty);
@@ -245,6 +249,7 @@ macro_rules! simd_u_ty {
245249
[impl_bitwise_reductions, $id, $elem_ty],
246250
[impl_all_scalar_shifts, $id, $elem_ty],
247251
[impl_vector_shifts, $id, $elem_ty],
252+
[impl_vector_rotates, $id, $elem_ty],
248253
[impl_hex_fmt, $id, $elem_ty],
249254
[impl_eq, $id],
250255
[impl_partial_eq, $id],
@@ -268,6 +273,7 @@ macro_rules! simd_u_ty {
268273
test_bitwise_reductions!($id, !(0 as $elem_ty));
269274
test_all_scalar_shift_ops!($id, $elem_ty);
270275
test_vector_shift_ops!($id, $elem_ty);
276+
test_vector_rotate_ops!($id, $elem_ty);
271277
test_hex_fmt!($id, $elem_ty);
272278
test_partial_eq!($id, 1 as $elem_ty, 0 as $elem_ty);
273279
test_default!($id, $elem_ty);

coresimd/ppsv/api/rotates.rs

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
//! Implements integer rotates.
2+
#![allow(unused)]
3+
4+
macro_rules! impl_vector_rotates {
5+
($id:ident, $elem_ty:ident) => {
6+
impl $id {
7+
/// Shifts the bits of each lane to the left by the specified amount in
8+
/// the corresponding lane of `n`, wrapping the truncated bits to
9+
/// the end of the resulting integer.
10+
///
11+
/// Please note this isn't the same operation as `<<`!. Also note it
12+
/// isn't equivalent to `slice::rotate_left` (that can be implemented
13+
/// with vector shuffles).
14+
#[inline]
15+
pub fn rotate_left(self, n: $id) -> $id {
16+
const LANE_WIDTH: $elem_ty = ::mem::size_of::<$elem_ty>() as $elem_ty * 8;
17+
// Protect against undefined behavior for over-long bit shifts
18+
let n = n % LANE_WIDTH;
19+
(self << n) | (self >> ((LANE_WIDTH - n) % LANE_WIDTH))
20+
}
21+
22+
/// Shifts the bits of each lane to the right by the specified amount in
23+
/// the corresponding lane of `n`, wrapping the truncated bits to
24+
/// the beginning of the resulting integer.
25+
///
26+
/// Please note this isn't the same operation as `>>`!. Also note it
27+
/// isn't similar to `slice::rotate_right`, it doesn't move the vector's
28+
/// lanes around. (that can be implemented with vector shuffles).
29+
#[inline]
30+
pub fn rotate_right(self, n: $id) -> $id {
31+
const LANE_WIDTH: $elem_ty = ::mem::size_of::<$elem_ty>() as $elem_ty * 8;
32+
// Protect against undefined behavior for over-long bit shifts
33+
let n = n % LANE_WIDTH;
34+
(self >> n) | (self << ((LANE_WIDTH - n) % LANE_WIDTH))
35+
}
36+
}
37+
};
38+
}
39+
40+
#[cfg(test)]
41+
macro_rules! test_vector_rotate_ops {
42+
($id:ident, $elem_ty:ident) => {
43+
#[test]
44+
fn rotate_ops() {
45+
use coresimd::simd::$id;
46+
use std::mem;
47+
let z = $id::splat(0 as $elem_ty);
48+
let o = $id::splat(1 as $elem_ty);
49+
let t = $id::splat(2 as $elem_ty);
50+
let f = $id::splat(4 as $elem_ty);
51+
52+
let max =
53+
$id::splat((mem::size_of::<$elem_ty>() * 8 - 1) as $elem_ty);
54+
55+
// rotate_right
56+
assert_eq!(z.rotate_right(z), z);
57+
assert_eq!(z.rotate_right(o), z);
58+
assert_eq!(z.rotate_right(t), z);
59+
60+
assert_eq!(o.rotate_right(z), o);
61+
assert_eq!(t.rotate_right(z), t);
62+
assert_eq!(f.rotate_right(z), f);
63+
assert_eq!(f.rotate_right(max), f << 1);
64+
65+
assert_eq!(o.rotate_right(o), o << max);
66+
assert_eq!(t.rotate_right(o), o);
67+
assert_eq!(t.rotate_right(t), o << max);
68+
assert_eq!(f.rotate_right(o), t);
69+
assert_eq!(f.rotate_right(t), o);
70+
71+
// rotate_left
72+
assert_eq!(z.rotate_left(z), z);
73+
assert_eq!(o.rotate_left(z), o);
74+
assert_eq!(t.rotate_left(z), t);
75+
assert_eq!(f.rotate_left(z), f);
76+
assert_eq!(f.rotate_left(max), t);
77+
78+
assert_eq!(o.rotate_left(o), t);
79+
assert_eq!(o.rotate_left(t), f);
80+
assert_eq!(t.rotate_left(o), f);
81+
}
82+
};
83+
}

coresimd/ppsv/api/shifts.rs

-2
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ macro_rules! test_vector_shift_ops {
5353
assert_eq!(z >> z, z);
5454
assert_eq!(z >> o, z);
5555
assert_eq!(z >> t, z);
56-
assert_eq!(z >> t, z);
5756

5857
assert_eq!(o >> z, o);
5958
assert_eq!(t >> z, t);
@@ -65,7 +64,6 @@ macro_rules! test_vector_shift_ops {
6564
assert_eq!(t >> t, z);
6665
assert_eq!(f >> o, t);
6766
assert_eq!(f >> t, o);
68-
assert_eq!(f >> max, z);
6967

7068
// shl
7169
assert_eq!(z << z, z);

0 commit comments

Comments
 (0)