Skip to content

Commit 0711e11

Browse files
#267: fix big-endian bitmasks smaller than a byte
2 parents 35e16a1 + 60555b5 commit 0711e11

File tree

2 files changed

+35
-4
lines changed

2 files changed

+35
-4
lines changed

crates/core_simd/src/masks/full_masks.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,26 @@ where
6868

6969
// Used for bitmask bit order workaround
7070
pub(crate) trait ReverseBits {
71-
fn reverse_bits(self) -> Self;
71+
// Reverse the least significant `n` bits of `self`.
72+
// (Remaining bits must be 0.)
73+
fn reverse_bits(self, n: usize) -> Self;
7274
}
7375

7476
macro_rules! impl_reverse_bits {
7577
{ $($int:ty),* } => {
7678
$(
7779
impl ReverseBits for $int {
78-
fn reverse_bits(self) -> Self { <$int>::reverse_bits(self) }
80+
#[inline(always)]
81+
fn reverse_bits(self, n: usize) -> Self {
82+
let rev = <$int>::reverse_bits(self);
83+
let bitsize = core::mem::size_of::<$int>() * 8;
84+
if n < bitsize {
85+
// Shift things back to the right
86+
rev >> (bitsize - n)
87+
} else {
88+
rev
89+
}
90+
}
7991
}
8092
)*
8193
}
@@ -137,7 +149,7 @@ where
137149

138150
// LLVM assumes bit order should match endianness
139151
if cfg!(target_endian = "big") {
140-
bitmask.reverse_bits()
152+
bitmask.reverse_bits(LANES)
141153
} else {
142154
bitmask
143155
}
@@ -150,7 +162,7 @@ where
150162
{
151163
// LLVM assumes bit order should match endianness
152164
let bitmask = if cfg!(target_endian = "big") {
153-
bitmask.reverse_bits()
165+
bitmask.reverse_bits(LANES)
154166
} else {
155167
bitmask
156168
};

crates/core_simd/tests/masks.rs

+19
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,25 @@ macro_rules! test_mask_api {
8080
assert_eq!(bitmask, 0b1000001101001001);
8181
assert_eq!(core_simd::Mask::<$type, 16>::from_bitmask(bitmask), mask);
8282
}
83+
84+
#[test]
85+
fn roundtrip_bitmask_conversion_short() {
86+
use core_simd::ToBitMask;
87+
88+
let values = [
89+
false, false, false, true,
90+
];
91+
let mask = core_simd::Mask::<$type, 4>::from_array(values);
92+
let bitmask = mask.to_bitmask();
93+
assert_eq!(bitmask, 0b1000);
94+
assert_eq!(core_simd::Mask::<$type, 4>::from_bitmask(bitmask), mask);
95+
96+
let values = [true, false];
97+
let mask = core_simd::Mask::<$type, 2>::from_array(values);
98+
let bitmask = mask.to_bitmask();
99+
assert_eq!(bitmask, 0b01);
100+
assert_eq!(core_simd::Mask::<$type, 2>::from_bitmask(bitmask), mask);
101+
}
83102
}
84103
}
85104
}

0 commit comments

Comments
 (0)