summaryrefslogtreecommitdiffstats
path: root/vendor/packed_simd_2/src/api/bit_manip.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/packed_simd_2/src/api/bit_manip.rs')
-rw-r--r--vendor/packed_simd_2/src/api/bit_manip.rs129
1 files changed, 129 insertions, 0 deletions
diff --git a/vendor/packed_simd_2/src/api/bit_manip.rs b/vendor/packed_simd_2/src/api/bit_manip.rs
new file mode 100644
index 000000000..6d8865706
--- /dev/null
+++ b/vendor/packed_simd_2/src/api/bit_manip.rs
@@ -0,0 +1,129 @@
+//! Bit manipulations.
+
+macro_rules! impl_bit_manip {
+ ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
+ impl $id {
+ /// Returns the number of ones in the binary representation of
+ /// the lanes of `self`.
+ #[inline]
+ pub fn count_ones(self) -> Self {
+ super::codegen::bit_manip::BitManip::ctpop(self)
+ }
+
+ /// Returns the number of zeros in the binary representation of
+ /// the lanes of `self`.
+ #[inline]
+ pub fn count_zeros(self) -> Self {
+ super::codegen::bit_manip::BitManip::ctpop(!self)
+ }
+
+ /// Returns the number of leading zeros in the binary
+ /// representation of the lanes of `self`.
+ #[inline]
+ pub fn leading_zeros(self) -> Self {
+ super::codegen::bit_manip::BitManip::ctlz(self)
+ }
+
+ /// Returns the number of trailing zeros in the binary
+ /// representation of the lanes of `self`.
+ #[inline]
+ pub fn trailing_zeros(self) -> Self {
+ super::codegen::bit_manip::BitManip::cttz(self)
+ }
+ }
+
+ test_if! {
+ $test_tt:
+ paste::item_with_macros! {
+ #[allow(overflowing_literals)]
+ pub mod [<$id _bit_manip>] {
+ #![allow(const_item_mutation)]
+ use super::*;
+
+ const LANE_WIDTH: usize = mem::size_of::<$elem_ty>() * 8;
+
+ macro_rules! test_func {
+ ($x:expr, $func:ident) => {{
+ let mut actual = $x;
+ for i in 0..$id::lanes() {
+ actual = actual.replace(
+ i,
+ $x.extract(i).$func() as $elem_ty
+ );
+ }
+ let expected = $x.$func();
+ assert_eq!(actual, expected);
+ }};
+ }
+
+ const BYTES: [u8; 64] = [
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63,
+ ];
+
+ fn load_bytes() -> $id {
+ let elems: &mut [$elem_ty] = unsafe {
+ slice::from_raw_parts_mut(
+ BYTES.as_mut_ptr() as *mut $elem_ty,
+ $id::lanes(),
+ )
+ };
+ $id::from_slice_unaligned(elems)
+ }
+
+ #[cfg_attr(not(target_arch = "wasm32"), test)]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn count_ones() {
+ test_func!($id::splat(0), count_ones);
+ test_func!($id::splat(!0), count_ones);
+ test_func!(load_bytes(), count_ones);
+ }
+
+ #[cfg_attr(not(target_arch = "wasm32"), test)]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn count_zeros() {
+ test_func!($id::splat(0), count_zeros);
+ test_func!($id::splat(!0), count_zeros);
+ test_func!(load_bytes(), count_zeros);
+ }
+
+ #[cfg_attr(not(target_arch = "wasm32"), test)]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn leading_zeros() {
+ test_func!($id::splat(0), leading_zeros);
+ test_func!($id::splat(1), leading_zeros);
+ // some implementations use `pshufb` which has unique
+ // behavior when the 8th bit is set.
+ test_func!($id::splat(0b1000_0010), leading_zeros);
+ test_func!($id::splat(!0), leading_zeros);
+ test_func!(
+ $id::splat(1 << (LANE_WIDTH - 1)),
+ leading_zeros
+ );
+ test_func!(load_bytes(), leading_zeros);
+ }
+
+ #[cfg_attr(not(target_arch = "wasm32"), test)]
+ #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+ fn trailing_zeros() {
+ test_func!($id::splat(0), trailing_zeros);
+ test_func!($id::splat(1), trailing_zeros);
+ test_func!($id::splat(0b1000_0010), trailing_zeros);
+ test_func!($id::splat(!0), trailing_zeros);
+ test_func!(
+ $id::splat(1 << (LANE_WIDTH - 1)),
+ trailing_zeros
+ );
+ test_func!(load_bytes(), trailing_zeros);
+ }
+ }
+ }
+ }
+ };
+}