diff --git a/coresimd/ppsv/api/arithmetic_scalar_ops.rs b/coresimd/ppsv/api/arithmetic_scalar_ops.rs new file mode 100644 index 0000000000..8688de5447 --- /dev/null +++ b/coresimd/ppsv/api/arithmetic_scalar_ops.rs @@ -0,0 +1,202 @@ +//! Lane-wise arithmetic operations. +#![allow(unused)] + +macro_rules! impl_arithmetic_scalar_ops { + ($id:ident, $elem_ty:ident) => { + impl ::ops::Add<$elem_ty> for $id { + type Output = Self; + #[inline] + fn add(self, other: $elem_ty) -> Self { + self + $id::splat(other) + } + } + impl ::ops::Add<$id> for $elem_ty { + type Output = $id; + #[inline] + fn add(self, other: $id) -> $id { + $id::splat(self) + other + } + } + + impl ::ops::Sub<$elem_ty> for $id { + type Output = Self; + #[inline] + fn sub(self, other: $elem_ty) -> Self { + self - $id::splat(other) + } + } + impl ::ops::Sub<$id> for $elem_ty { + type Output = $id; + #[inline] + fn sub(self, other: $id) -> $id { + $id::splat(self) - other + } + } + + impl ::ops::Mul<$elem_ty> for $id { + type Output = Self; + #[inline] + fn mul(self, other: $elem_ty) -> Self { + self * $id::splat(other) + } + } + impl ::ops::Mul<$id> for $elem_ty { + type Output = $id; + #[inline] + fn mul(self, other: $id) -> $id { + $id::splat(self) * other + } + } + + impl ::ops::Div<$elem_ty> for $id { + type Output = Self; + #[inline] + fn div(self, other: $elem_ty) -> Self { + self / $id::splat(other) + } + } + impl ::ops::Div<$id> for $elem_ty { + type Output = $id; + #[inline] + fn div(self, other: $id) -> $id { + $id::splat(self) / other + } + } + + impl ::ops::Rem<$elem_ty> for $id { + type Output = Self; + #[inline] + fn rem(self, other: $elem_ty) -> Self { + self % $id::splat(other) + } + } + impl ::ops::Rem<$id> for $elem_ty { + type Output = $id; + #[inline] + fn rem(self, other: $id) -> $id { + $id::splat(self) % other + } + } + + impl ::ops::AddAssign<$elem_ty> for $id { + #[inline] + fn add_assign(&mut self, other: $elem_ty) { + *self = *self + other; + } + } + + impl ::ops::SubAssign<$elem_ty> for $id { + #[inline] + fn sub_assign(&mut self, other: $elem_ty) { + *self = *self - other; + } + } + + impl ::ops::MulAssign<$elem_ty> for $id { + #[inline] + fn mul_assign(&mut self, other: $elem_ty) { + *self = *self * other; + } + } + + impl ::ops::DivAssign<$elem_ty> for $id { + #[inline] + fn div_assign(&mut self, other: $elem_ty) { + *self = *self / other; + } + } + + impl ::ops::RemAssign<$elem_ty> for $id { + #[inline] + fn rem_assign(&mut self, other: $elem_ty) { + *self = *self % other; + } + } + } +} + +#[cfg(test)] +macro_rules! test_arithmetic_scalar_ops { + ($id:ident, $elem_ty:ident) => { + #[test] + fn arithmetic_scalar() { + use ::coresimd::simd::$id; + let zi = 0 as $elem_ty; + let oi = 1 as $elem_ty; + let ti = 2 as $elem_ty; + let fi = 4 as $elem_ty; + let z = $id::splat(zi); + let o = $id::splat(oi); + let t = $id::splat(ti); + let f = $id::splat(fi); + + // add + assert_eq!(zi + z, z); + assert_eq!(z + zi, z); + assert_eq!(oi + z, o); + assert_eq!(o + zi, o); + assert_eq!(ti + z, t); + assert_eq!(t + zi, t); + assert_eq!(ti + t, f); + assert_eq!(t + ti, f); + // sub + assert_eq!(zi - z, z); + assert_eq!(z - zi, z); + assert_eq!(oi - z, o); + assert_eq!(o - zi, o); + assert_eq!(ti - z, t); + assert_eq!(t - zi, t); + assert_eq!(fi - t, t); + assert_eq!(f - ti, t); + assert_eq!(f - o - o, t); + assert_eq!(f - oi - oi, t); + // mul + assert_eq!(zi * z, z); + assert_eq!(z * zi, z); + assert_eq!(zi * o, z); + assert_eq!(z * oi, z); + assert_eq!(zi * t, z); + assert_eq!(z * ti, z); + assert_eq!(oi * t, t); + assert_eq!(o * ti, t); + assert_eq!(ti * t, f); + assert_eq!(t * ti, f); + // div + assert_eq!(zi / o, z); + assert_eq!(z / oi, z); + assert_eq!(ti / o, t); + assert_eq!(t / oi, t); + assert_eq!(fi / o, f); + assert_eq!(f / oi, f); + assert_eq!(ti / t, o); + assert_eq!(t / ti, o); + assert_eq!(fi / t, t); + assert_eq!(f / ti, t); + // rem + assert_eq!(oi % o, z); + assert_eq!(o % oi, z); + assert_eq!(fi % t, z); + assert_eq!(f % ti, z); + + { + let mut v = z; + assert_eq!(v, z); + v += oi; // add_assign + assert_eq!(v, o); + v -= oi; // sub_assign + assert_eq!(v, z); + v = t; + v *= oi; // mul_assign + assert_eq!(v, t); + v *= ti; + assert_eq!(v, f); + v /= oi; // div_assign + assert_eq!(v, f); + v /= ti; + assert_eq!(v, t); + v %= ti; // rem_assign + assert_eq!(v, z); + } + } + }; +} diff --git a/coresimd/ppsv/api/bitwise_ops.rs b/coresimd/ppsv/api/bitwise_ops.rs index d6b8a6c01b..46699e9bfe 100644 --- a/coresimd/ppsv/api/bitwise_ops.rs +++ b/coresimd/ppsv/api/bitwise_ops.rs @@ -2,15 +2,15 @@ #![allow(unused)] macro_rules! impl_bitwise_ops { - ($ty:ident, $true_val:expr) => { - impl ::ops::Not for $ty { + ($id:ident, $true_val:expr) => { + impl ::ops::Not for $id { type Output = Self; #[inline] fn not(self) -> Self { Self::splat($true_val) ^ self } } - impl ::ops::BitXor for $ty { + impl ::ops::BitXor for $id { type Output = Self; #[inline] fn bitxor(self, other: Self) -> Self { @@ -18,7 +18,7 @@ macro_rules! impl_bitwise_ops { unsafe { simd_xor(self, other) } } } - impl ::ops::BitAnd for $ty { + impl ::ops::BitAnd for $id { type Output = Self; #[inline] fn bitand(self, other: Self) -> Self { @@ -26,7 +26,7 @@ macro_rules! impl_bitwise_ops { unsafe { simd_and(self, other) } } } - impl ::ops::BitOr for $ty { + impl ::ops::BitOr for $id { type Output = Self; #[inline] fn bitor(self, other: Self) -> Self { @@ -34,19 +34,19 @@ macro_rules! impl_bitwise_ops { unsafe { simd_or(self, other) } } } - impl ::ops::BitAndAssign for $ty { + impl ::ops::BitAndAssign for $id { #[inline] fn bitand_assign(&mut self, other: Self) { *self = *self & other; } } - impl ::ops::BitOrAssign for $ty { + impl ::ops::BitOrAssign for $id { #[inline] fn bitor_assign(&mut self, other: Self) { *self = *self | other; } } - impl ::ops::BitXorAssign for $ty { + impl ::ops::BitXorAssign for $id { #[inline] fn bitxor_assign(&mut self, other: Self) { *self = *self ^ other; diff --git a/coresimd/ppsv/api/bitwise_scalar_ops.rs b/coresimd/ppsv/api/bitwise_scalar_ops.rs new file mode 100644 index 0000000000..22feb40adb --- /dev/null +++ b/coresimd/ppsv/api/bitwise_scalar_ops.rs @@ -0,0 +1,217 @@ +//! Lane-wise bitwise operations for integer and boolean vectors. +#![allow(unused)] + +macro_rules! impl_bitwise_scalar_ops { + ($id:ident, $elem_ty:ident) => { + impl ::ops::BitXor<$elem_ty> for $id { + type Output = Self; + #[inline] + fn bitxor(self, other: $elem_ty) -> Self { + self ^ $id::splat(other) + } + } + impl ::ops::BitXor<$id> for $elem_ty { + type Output = $id; + #[inline] + fn bitxor(self, other: $id) -> $id { + $id::splat(self) ^ other + } + } + + impl ::ops::BitAnd<$elem_ty> for $id { + type Output = Self; + #[inline] + fn bitand(self, other: $elem_ty) -> Self { + self & $id::splat(other) + } + } + impl ::ops::BitAnd<$id> for $elem_ty { + type Output = $id; + #[inline] + fn bitand(self, other: $id) -> $id { + $id::splat(self) & other + } + } + + impl ::ops::BitOr<$elem_ty> for $id { + type Output = Self; + #[inline] + fn bitor(self, other: $elem_ty) -> Self { + self | $id::splat(other) + } + } + impl ::ops::BitOr<$id> for $elem_ty { + type Output = $id; + #[inline] + fn bitor(self, other: $id) -> $id { + $id::splat(self) | other + } + } + + impl ::ops::BitAndAssign<$elem_ty> for $id { + #[inline] + fn bitand_assign(&mut self, other: $elem_ty) { + *self = *self & other; + } + } + impl ::ops::BitOrAssign<$elem_ty> for $id { + #[inline] + fn bitor_assign(&mut self, other: $elem_ty) { + *self = *self | other; + } + } + impl ::ops::BitXorAssign<$elem_ty> for $id { + #[inline] + fn bitxor_assign(&mut self, other: $elem_ty) { + *self = *self ^ other; + } + } + }; +} + +#[cfg(test)] +macro_rules! test_int_bitwise_scalar_ops { + ($id:ident, $elem_ty:ident) => { + #[test] + fn bitwise_scalar_ops() { + use ::coresimd::simd::$id; + let zi = 0 as $elem_ty; + let oi = 1 as $elem_ty; + let ti = 2 as $elem_ty; + let z = $id::splat(zi); + let o = $id::splat(oi); + let t = $id::splat(ti); + + // BitAnd: + assert_eq!(oi & o, o); + assert_eq!(o & oi, o); + assert_eq!(oi & z, z); + assert_eq!(o & zi, z); + assert_eq!(zi & o, z); + assert_eq!(z & oi, z); + assert_eq!(zi & z, z); + assert_eq!(z & zi, z); + + assert_eq!(ti & t, t); + assert_eq!(t & ti, t); + assert_eq!(ti & o, z); + assert_eq!(t & oi, z); + assert_eq!(oi & t, z); + assert_eq!(o & ti, z); + + // BitOr: + assert_eq!(oi | o, o); + assert_eq!(o | oi, o); + assert_eq!(oi | z, o); + assert_eq!(o | zi, o); + assert_eq!(zi | o, o); + assert_eq!(z | oi, o); + assert_eq!(zi | z, z); + assert_eq!(z | zi, z); + + assert_eq!(ti | t, t); + assert_eq!(t | ti, t); + assert_eq!(zi | t, t); + assert_eq!(z | ti, t); + assert_eq!(ti | z, t); + assert_eq!(t | zi, t); + + // BitXOR: + assert_eq!(oi ^ o, z); + assert_eq!(o ^ oi, z); + assert_eq!(zi ^ z, z); + assert_eq!(z ^ zi, z); + assert_eq!(zi ^ o, o); + assert_eq!(z ^ oi, o); + assert_eq!(oi ^ z, o); + assert_eq!(o ^ zi, o); + + assert_eq!(ti ^ t, z); + assert_eq!(t ^ ti, z); + assert_eq!(ti ^ z, t); + assert_eq!(t ^ zi, t); + assert_eq!(zi ^ t, t); + assert_eq!(z ^ ti, t); + + { // AndAssign: + let mut v = o; + v &= ti; + assert_eq!(v, z); + } + { // OrAssign: + let mut v = z; + v |= oi; + assert_eq!(v, o); + } + { // XORAssign: + let mut v = z; + v ^= oi; + assert_eq!(v, o); + } + } + } +} + +#[cfg(test)] +macro_rules! test_bool_bitwise_scalar_ops { + ($id:ident) => { + #[test] + fn bool_scalar_arithmetic() { + use ::coresimd::simd::*; + + let ti = true; + let fi = false; + let t = $id::splat(ti); + let f = $id::splat(fi); + assert!(t != f); + assert!(!(t == f)); + + + // BitAnd: + assert_eq!(ti & f, f); + assert_eq!(t & fi, f); + assert_eq!(fi & t, f); + assert_eq!(f & ti, f); + assert_eq!(ti & t, t); + assert_eq!(t & ti, t); + assert_eq!(fi & f, f); + assert_eq!(f & fi, f); + + // BitOr: + assert_eq!(ti | f, t); + assert_eq!(t | fi, t); + assert_eq!(fi | t, t); + assert_eq!(f | ti, t); + assert_eq!(ti | t, t); + assert_eq!(t | ti, t); + assert_eq!(fi | f, f); + assert_eq!(f | fi, f); + + // BitXOR: + assert_eq!(ti ^ f, t); + assert_eq!(t ^ fi, t); + assert_eq!(fi ^ t, t); + assert_eq!(f ^ ti, t); + assert_eq!(ti ^ t, f); + assert_eq!(t ^ ti, f); + assert_eq!(fi ^ f, f); + assert_eq!(f ^ fi, f); + + { // AndAssign: + let mut v = f; + v &= ti; + assert_eq!(v, f); + } + { // OrAssign: + let mut v = f; + v |= ti; + assert_eq!(v, t); + } + { // XORAssign: + let mut v = f; + v ^= ti; + assert_eq!(v, t); + } + } + } +} diff --git a/coresimd/ppsv/api/mod.rs b/coresimd/ppsv/api/mod.rs index 732c1c0b93..1ddf30a1a9 100644 --- a/coresimd/ppsv/api/mod.rs +++ b/coresimd/ppsv/api/mod.rs @@ -69,10 +69,14 @@ macro_rules! define_ty { #[macro_use] mod arithmetic_ops; #[macro_use] +mod arithmetic_scalar_ops; +#[macro_use] mod arithmetic_reductions; #[macro_use] mod bitwise_ops; #[macro_use] +mod bitwise_scalar_ops; +#[macro_use] mod bitwise_reductions; #[macro_use] mod boolean_reductions; @@ -112,6 +116,8 @@ mod partial_eq; //#[macro_use] //mod gather_scatter; #[macro_use] +mod scalar_shifts; +#[macro_use] mod shifts; /// Defines a portable packed SIMD floating-point vector type. @@ -124,6 +130,7 @@ macro_rules! simd_f_ty { [impl_load_store, $id, $elem_ty, $elem_count], [impl_cmp, $id, $bool_ty], [impl_arithmetic_ops, $id], + [impl_arithmetic_scalar_ops, $id, $elem_ty], [impl_arithmetic_reductions, $id, $elem_ty], [impl_minmax_reductions, $id, $elem_ty], [impl_neg_op, $id, $elem_ty], @@ -138,6 +145,7 @@ macro_rules! simd_f_ty { test_load_store!($id, $elem_ty); test_cmp!($id, $elem_ty, $bool_ty, 1. as $elem_ty, 0. as $elem_ty); test_arithmetic_ops!($id, $elem_ty); + test_arithmetic_scalar_ops!($id, $elem_ty); test_arithmetic_reductions!($id, $elem_ty); test_minmax_reductions!($id, $elem_ty); test_neg_op!($id, $elem_ty); @@ -159,12 +167,15 @@ macro_rules! simd_i_ty { [impl_cmp, $id, $bool_ty], [impl_hash, $id, $elem_ty], [impl_arithmetic_ops, $id], + [impl_arithmetic_scalar_ops, $id, $elem_ty], [impl_arithmetic_reductions, $id, $elem_ty], [impl_minmax_reductions, $id, $elem_ty], [impl_neg_op, $id, $elem_ty], [impl_bitwise_ops, $id, !(0 as $elem_ty)], + [impl_bitwise_scalar_ops, $id, $elem_ty], [impl_bitwise_reductions, $id, $elem_ty], - [impl_all_shifts, $id, $elem_ty], + [impl_all_scalar_shifts, $id, $elem_ty], + [impl_vector_shifts, $id, $elem_ty], [impl_hex_fmt, $id, $elem_ty], [impl_eq, $id], [impl_partial_eq, $id], @@ -179,12 +190,15 @@ macro_rules! simd_i_ty { test_cmp!($id, $elem_ty, $bool_ty, 1 as $elem_ty, 0 as $elem_ty); test_hash!($id, $elem_ty); test_arithmetic_ops!($id, $elem_ty); + test_arithmetic_scalar_ops!($id, $elem_ty); test_arithmetic_reductions!($id, $elem_ty); test_minmax_reductions!($id, $elem_ty); test_neg_op!($id, $elem_ty); test_int_bitwise_ops!($id, $elem_ty); + test_int_bitwise_scalar_ops!($id, $elem_ty); test_bitwise_reductions!($id, !(0 as $elem_ty)); - test_all_shift_ops!($id, $elem_ty); + test_all_scalar_shift_ops!($id, $elem_ty); + test_vector_shift_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); @@ -204,11 +218,14 @@ macro_rules! simd_u_ty { [impl_cmp, $id, $bool_ty], [impl_hash, $id, $elem_ty], [impl_arithmetic_ops, $id], + [impl_arithmetic_scalar_ops, $id, $elem_ty], [impl_arithmetic_reductions, $id, $elem_ty], [impl_minmax_reductions, $id, $elem_ty], + [impl_bitwise_scalar_ops, $id, $elem_ty], [impl_bitwise_ops, $id, !(0 as $elem_ty)], [impl_bitwise_reductions, $id, $elem_ty], - [impl_all_shifts, $id, $elem_ty], + [impl_all_scalar_shifts, $id, $elem_ty], + [impl_vector_shifts, $id, $elem_ty], [impl_hex_fmt, $id, $elem_ty], [impl_eq, $id], [impl_partial_eq, $id], @@ -223,11 +240,14 @@ macro_rules! simd_u_ty { test_cmp!($id, $elem_ty, $bool_ty, 1 as $elem_ty, 0 as $elem_ty); test_hash!($id, $elem_ty); test_arithmetic_ops!($id, $elem_ty); + test_arithmetic_scalar_ops!($id, $elem_ty); test_arithmetic_reductions!($id, $elem_ty); test_minmax_reductions!($id, $elem_ty); test_int_bitwise_ops!($id, $elem_ty); + test_int_bitwise_scalar_ops!($id, $elem_ty); test_bitwise_reductions!($id, !(0 as $elem_ty)); - test_all_shift_ops!($id, $elem_ty); + test_all_scalar_shift_ops!($id, $elem_ty); + test_vector_shift_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); @@ -244,6 +264,7 @@ macro_rules! simd_b_ty { [define_ty, $id, $($elem_tys),+ | $(#[$doc])*], [impl_bool_minimal, $id, $elem_ty, $elem_count, $($elem_name),*], [impl_bitwise_ops, $id, true], + [impl_bitwise_scalar_ops, $id, bool], [impl_bool_bitwise_reductions, $id, bool, $elem_ty], [impl_bool_reductions, $id], [impl_bool_cmp, $id, $id], @@ -257,6 +278,7 @@ macro_rules! simd_b_ty { mod $test_mod { test_bool_minimal!($id, $elem_count); test_bool_bitwise_ops!($id); + test_bool_bitwise_scalar_ops!($id); test_bool_reductions!($id); test_bitwise_reductions!($id, true); test_cmp!($id, $elem_ty, $id, true, false); diff --git a/coresimd/ppsv/api/scalar_shifts.rs b/coresimd/ppsv/api/scalar_shifts.rs new file mode 100644 index 0000000000..42354e9edf --- /dev/null +++ b/coresimd/ppsv/api/scalar_shifts.rs @@ -0,0 +1,123 @@ +//! Implements integer shifts. +#![allow(unused)] + +macro_rules! impl_shifts { + ($id:ident, $elem_ty:ident, $($by:ident),+) => { + $( + impl ::ops::Shl<$by> for $id { + type Output = Self; + #[inline] + fn shl(self, other: $by) -> Self { + use coresimd::simd_llvm::simd_shl; + unsafe { simd_shl(self, $id::splat(other as $elem_ty)) } + } + } + impl ::ops::Shr<$by> for $id { + type Output = Self; + #[inline] + fn shr(self, other: $by) -> Self { + use coresimd::simd_llvm::simd_shr; + unsafe { simd_shr(self, $id::splat(other as $elem_ty)) } + } + } + + impl ::ops::ShlAssign<$by> for $id { + #[inline] + fn shl_assign(&mut self, other: $by) { + *self = *self << other; + } + } + impl ::ops::ShrAssign<$by> for $id { + #[inline] + fn shr_assign(&mut self, other: $by) { + *self = *self >> other; + } + } + + )+ + } +} + +macro_rules! impl_all_scalar_shifts { + ($id:ident, $elem_ty:ident) => { + impl_shifts!( + $id, $elem_ty, + u8, u16, u32, u64, usize, + i8, i16, i32, i64, isize); + + } +} + +#[cfg(test)] +macro_rules! test_shift_ops { + ($id:ident, $elem_ty:ident, $($index_ty:ident),+) => { + #[test] + fn scalar_shift_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 zi = 0 as $index_ty; + let oi = 1 as $index_ty; + let ti = 2 as $index_ty; + let maxi = (mem::size_of::<$elem_ty>() * 8 - 1) as $index_ty; + + // shr + assert_eq!(z >> zi, z); + assert_eq!(z >> oi, z); + assert_eq!(z >> ti, z); + assert_eq!(z >> ti, z); + + assert_eq!(o >> zi, o); + assert_eq!(t >> zi, t); + assert_eq!(f >> zi, f); + assert_eq!(f >> maxi, z); + + assert_eq!(o >> oi, z); + assert_eq!(t >> oi, o); + assert_eq!(t >> ti, z); + assert_eq!(f >> oi, t); + assert_eq!(f >> ti, o); + assert_eq!(f >> maxi, z); + + // shl + assert_eq!(z << zi, z); + assert_eq!(o << zi, o); + assert_eq!(t << zi, t); + assert_eq!(f << zi, f); + assert_eq!(f << maxi, z); + + assert_eq!(o << oi, t); + assert_eq!(o << ti, f); + assert_eq!(t << oi, f); + + { // shr_assign + let mut v = o; + v >>= oi; + assert_eq!(v, z); + } + { // shl_assign + let mut v = o; + v <<= oi; + assert_eq!(v, t); + } + } + )+ + } + }; +} + +#[cfg(test)] +macro_rules! test_all_scalar_shift_ops { + ($id:ident, $elem_ty:ident) => { + test_shift_ops!( + $id, $elem_ty, + u8, u16, u32, u64, usize, + i8, i16, i32, i64, isize); + } +} diff --git a/coresimd/ppsv/api/shifts.rs b/coresimd/ppsv/api/shifts.rs index 397f10646a..551bcd3469 100644 --- a/coresimd/ppsv/api/shifts.rs +++ b/coresimd/ppsv/api/shifts.rs @@ -1,56 +1,42 @@ //! Implements integer shifts. #![allow(unused)] -macro_rules! impl_shifts { - ($id:ident, $elem_ty:ident, $($by:ident),+) => { - $( - impl ::ops::Shl<$by> for $id { - type Output = Self; - #[inline] - fn shl(self, other: $by) -> Self { - use coresimd::simd_llvm::simd_shl; - unsafe { simd_shl(self, $id::splat(other as $elem_ty)) } - } - } - impl ::ops::Shr<$by> for $id { - type Output = Self; - #[inline] - fn shr(self, other: $by) -> Self { - use coresimd::simd_llvm::simd_shr; - unsafe { simd_shr(self, $id::splat(other as $elem_ty)) } +macro_rules! impl_vector_shifts { + ($id:ident, $elem_ty:ident) => { + impl ::ops::Shl<$id> for $id { + type Output = Self; + #[inline] + fn shl(self, other: Self) -> Self { + use coresimd::simd_llvm::simd_shl; + unsafe { simd_shl(self, other) } } + } + impl ::ops::Shr<$id> for $id { + type Output = Self; + #[inline] + fn shr(self, other: Self) -> Self { + use coresimd::simd_llvm::simd_shr; + unsafe { simd_shr(self, other) } } - - impl ::ops::ShlAssign<$by> for $id { - #[inline] - fn shl_assign(&mut self, other: $by) { - *self = *self << other; - } + } + impl ::ops::ShlAssign<$id> for $id { + #[inline] + fn shl_assign(&mut self, other: Self) { + *self = *self << other; } - impl ::ops::ShrAssign<$by> for $id { - #[inline] - fn shr_assign(&mut self, other: $by) { - *self = *self >> other; - } + } + impl ::ops::ShrAssign<$id> for $id { + #[inline] + fn shr_assign(&mut self, other: Self) { + *self = *self >> other; } - - )+ - } -} - -macro_rules! impl_all_shifts { - ($id:ident, $elem_ty:ident) => { - impl_shifts!( - $id, $elem_ty, - u8, u16, u32, u64, usize, - i8, i16, i32, i64, isize); - + } } } #[cfg(test)] -macro_rules! test_shift_ops { - ($id:ident, $elem_ty:ident, $($index_ty:ident),+) => { +macro_rules! test_vector_shift_ops { + ($id:ident, $elem_ty:ident) => { #[test] fn shift_ops() { use ::coresimd::simd::$id; @@ -60,64 +46,47 @@ macro_rules! test_shift_ops { let t = $id::splat(2 as $elem_ty); let f = $id::splat(4 as $elem_ty); - $( - { - let zi = 0 as $index_ty; - let oi = 1 as $index_ty; - let ti = 2 as $index_ty; - let maxi = (mem::size_of::<$elem_ty>() * 8 - 1) as $index_ty; + let max = $id::splat((mem::size_of::<$elem_ty>() * 8 - 1) as $elem_ty); - // shr - assert_eq!(z >> zi, z); - assert_eq!(z >> oi, z); - assert_eq!(z >> ti, z); - assert_eq!(z >> ti, z); + // shr + assert_eq!(z >> z, z); + assert_eq!(z >> o, z); + assert_eq!(z >> t, z); + assert_eq!(z >> t, z); - assert_eq!(o >> zi, o); - assert_eq!(t >> zi, t); - assert_eq!(f >> zi, f); - assert_eq!(f >> maxi, z); + assert_eq!(o >> z, o); + assert_eq!(t >> z, t); + assert_eq!(f >> z, f); + assert_eq!(f >> max, z); - assert_eq!(o >> oi, z); - assert_eq!(t >> oi, o); - assert_eq!(t >> ti, z); - assert_eq!(f >> oi, t); - assert_eq!(f >> ti, o); - assert_eq!(f >> maxi, z); + assert_eq!(o >> o, z); + assert_eq!(t >> o, o); + assert_eq!(t >> t, z); + assert_eq!(f >> o, t); + assert_eq!(f >> t, o); + assert_eq!(f >> max, z); - // shl - assert_eq!(z << zi, z); - assert_eq!(o << zi, o); - assert_eq!(t << zi, t); - assert_eq!(f << zi, f); - assert_eq!(f << maxi, z); + // shl + assert_eq!(z << z, z); + assert_eq!(o << z, o); + assert_eq!(t << z, t); + assert_eq!(f << z, f); + assert_eq!(f << max, z); - assert_eq!(o << oi, t); - assert_eq!(o << ti, f); - assert_eq!(t << oi, f); + assert_eq!(o << o, t); + assert_eq!(o << t, f); + assert_eq!(t << o, f); - { // shr_assign - let mut v = o; - v >>= oi; - assert_eq!(v, z); - } - { // shl_assign - let mut v = o; - v <<= oi; - assert_eq!(v, t); - } - } - )+ + { // shr_assign + let mut v = o; + v >>= o; + assert_eq!(v, z); + } + { // shl_assign + let mut v = o; + v <<= o; + assert_eq!(v, t); + } } }; } - -#[cfg(test)] -macro_rules! test_all_shift_ops { - ($id:ident, $elem_ty:ident) => { - test_shift_ops!( - $id, $elem_ty, - u8, u16, u32, u64, usize, - i8, i16, i32, i64, isize); - } -}