Skip to content

Commit

Permalink
add rotate_left/right
Browse files Browse the repository at this point in the history
  • Loading branch information
TheIronBorn committed Jun 24, 2018
1 parent dda4072 commit 1271a3f
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 2 deletions.
6 changes: 6 additions & 0 deletions coresimd/ppsv/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ mod masks_select;
mod scalar_shifts;
#[macro_use]
mod shifts;
#[macro_use]
mod rotates;

/// Sealed trait used for constraining select implementations.
pub trait Lanes<A> {}
Expand Down Expand Up @@ -191,6 +193,7 @@ macro_rules! simd_i_ty {
[impl_bitwise_reductions, $id, $elem_ty],
[impl_all_scalar_shifts, $id, $elem_ty],
[impl_vector_shifts, $id, $elem_ty],
[impl_vector_rotates, $id, $elem_ty],
[impl_hex_fmt, $id, $elem_ty],
[impl_eq, $id],
[impl_partial_eq, $id],
Expand All @@ -215,6 +218,7 @@ macro_rules! simd_i_ty {
test_bitwise_reductions!($id, !(0 as $elem_ty));
test_all_scalar_shift_ops!($id, $elem_ty);
test_vector_shift_ops!($id, $elem_ty);
test_vector_rotate_ops!($id, $elem_ty);
test_hex_fmt!($id, $elem_ty);
test_partial_eq!($id, 1 as $elem_ty, 0 as $elem_ty);
test_default!($id, $elem_ty);
Expand Down Expand Up @@ -245,6 +249,7 @@ macro_rules! simd_u_ty {
[impl_bitwise_reductions, $id, $elem_ty],
[impl_all_scalar_shifts, $id, $elem_ty],
[impl_vector_shifts, $id, $elem_ty],
[impl_vector_rotates, $id, $elem_ty],
[impl_hex_fmt, $id, $elem_ty],
[impl_eq, $id],
[impl_partial_eq, $id],
Expand All @@ -268,6 +273,7 @@ macro_rules! simd_u_ty {
test_bitwise_reductions!($id, !(0 as $elem_ty));
test_all_scalar_shift_ops!($id, $elem_ty);
test_vector_shift_ops!($id, $elem_ty);
test_vector_rotate_ops!($id, $elem_ty);
test_hex_fmt!($id, $elem_ty);
test_partial_eq!($id, 1 as $elem_ty, 0 as $elem_ty);
test_default!($id, $elem_ty);
Expand Down
83 changes: 83 additions & 0 deletions coresimd/ppsv/api/rotates.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
//! Implements integer rotates.
#![allow(unused)]

macro_rules! impl_vector_rotates {
($id:ident, $elem_ty:ident) => {
impl $id {
/// Shifts the bits of each lane to the left by the specified amount in
/// the corresponding lane of `n`, wrapping the truncated bits to
/// the end of the resulting integer.
///
/// Please note this isn't the same operation as `<<`!. Also note it
/// isn't equivalent to `slice::rotate_left` (that can be implemented
/// with vector shuffles).
#[inline]
pub fn rotate_left(self, n: $id) -> $id {
const LANE_WIDTH: $elem_ty = ::mem::size_of::<$elem_ty>() as $elem_ty * 8;
// Protect against undefined behavior for over-long bit shifts
let n = n % LANE_WIDTH;
(self << n) | (self >> ((LANE_WIDTH - n) % LANE_WIDTH))
}

/// Shifts the bits of each lane to the right by the specified amount in
/// the corresponding lane of `n`, wrapping the truncated bits to
/// the beginning of the resulting integer.
///
/// Please note this isn't the same operation as `>>`!. Also note it
/// isn't similar to `slice::rotate_right`, it doesn't move the vector's
/// lanes around. (that can be implemented with vector shuffles).
#[inline]
pub fn rotate_right(self, n: $id) -> $id {
const LANE_WIDTH: $elem_ty = ::mem::size_of::<$elem_ty>() as $elem_ty * 8;
// Protect against undefined behavior for over-long bit shifts
let n = n % LANE_WIDTH;
(self >> n) | (self << ((LANE_WIDTH - n) % LANE_WIDTH))
}
}
};
}

#[cfg(test)]
macro_rules! test_vector_rotate_ops {
($id:ident, $elem_ty:ident) => {
#[test]
fn rotate_ops() {
use coresimd::simd::$id;
use std::mem;
let z = $id::splat(0 as $elem_ty);
let o = $id::splat(1 as $elem_ty);
let t = $id::splat(2 as $elem_ty);
let f = $id::splat(4 as $elem_ty);

let max =
$id::splat((mem::size_of::<$elem_ty>() * 8 - 1) as $elem_ty);

// rotate_right
assert_eq!(z.rotate_right(z), z);
assert_eq!(z.rotate_right(o), z);
assert_eq!(z.rotate_right(t), z);

assert_eq!(o.rotate_right(z), o);
assert_eq!(t.rotate_right(z), t);
assert_eq!(f.rotate_right(z), f);
assert_eq!(f.rotate_right(max), f << 1);

assert_eq!(o.rotate_right(o), o << max);
assert_eq!(t.rotate_right(o), o);
assert_eq!(t.rotate_right(t), o << max);
assert_eq!(f.rotate_right(o), t);
assert_eq!(f.rotate_right(t), o);

// rotate_left
assert_eq!(z.rotate_left(z), z);
assert_eq!(o.rotate_left(z), o);
assert_eq!(t.rotate_left(z), t);
assert_eq!(f.rotate_left(z), f);
assert_eq!(f.rotate_left(max), t);

assert_eq!(o.rotate_left(o), t);
assert_eq!(o.rotate_left(t), f);
assert_eq!(t.rotate_left(o), f);
}
};
}
2 changes: 0 additions & 2 deletions coresimd/ppsv/api/shifts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ macro_rules! test_vector_shift_ops {
assert_eq!(z >> z, z);
assert_eq!(z >> o, z);
assert_eq!(z >> t, z);
assert_eq!(z >> t, z);

assert_eq!(o >> z, o);
assert_eq!(t >> z, t);
Expand All @@ -65,7 +64,6 @@ macro_rules! test_vector_shift_ops {
assert_eq!(t >> t, z);
assert_eq!(f >> o, t);
assert_eq!(f >> t, o);
assert_eq!(f >> max, z);

// shl
assert_eq!(z << z, z);
Expand Down

0 comments on commit 1271a3f

Please sign in to comment.