summaryrefslogtreecommitdiffstats
path: root/third_party/rust/packed_simd/src/api/ops/vector_rotates.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/packed_simd/src/api/ops/vector_rotates.rs')
-rw-r--r--third_party/rust/packed_simd/src/api/ops/vector_rotates.rs92
1 files changed, 92 insertions, 0 deletions
diff --git a/third_party/rust/packed_simd/src/api/ops/vector_rotates.rs b/third_party/rust/packed_simd/src/api/ops/vector_rotates.rs
new file mode 100644
index 0000000000..6c4bed72a2
--- /dev/null
+++ b/third_party/rust/packed_simd/src/api/ops/vector_rotates.rs
@@ -0,0 +1,92 @@
+//! Vertical (lane-wise) vector rotates operations.
+#![allow(unused)]
+
+macro_rules! impl_ops_vector_rotates {
+ ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
+ 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.
+ ///
+ /// Note: this is neither the same operation as `<<` nor equivalent
+ /// to `slice::rotate_left`.
+ #[inline]
+ pub fn rotate_left(self, n: $id) -> $id {
+ const LANE_WIDTH: $elem_ty =
+ crate::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.
+ ///
+ /// Note: this is neither the same operation as `>>` nor equivalent
+ /// to `slice::rotate_right`.
+ #[inline]
+ pub fn rotate_right(self, n: $id) -> $id {
+ const LANE_WIDTH: $elem_ty =
+ crate::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))
+ }
+ }
+
+ test_if!{
+ $test_tt:
+ paste::item! {
+ // FIXME:
+ // https://github.com/rust-lang-nursery/packed_simd/issues/75
+ #[cfg(not(any(
+ target_arch = "s390x",
+ target_arch = "sparc64",
+ )))]
+ pub mod [<$id _ops_vector_rotate>] {
+ use super::*;
+ #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ #[cfg(not(target_arch = "aarch64"))]
+ //~^ FIXME: https://github.com/rust-lang/packed_simd/issues/317
+ fn rotate_ops() {
+ 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);
+ }
+ }
+ }
+ }
+ };
+}