Add from_bitmask (#136)

* Add from_bitmask
* Add mips workaround
This commit is contained in:
Caleb Zulawski 2021-06-21 17:05:43 -04:00 committed by GitHub
parent 57e67c905f
commit 15b4e28004
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 42 additions and 2 deletions

View file

@ -100,6 +100,15 @@ impl<T: Mask, const LANES: usize> BitMask<T, LANES> {
unsafe { core::mem::transmute_copy(&self.0) }
}
#[inline]
pub fn from_bitmask<U: Mask>(bitmask: U::BitMask) -> Self {
assert_eq!(
core::mem::size_of::<T::BitMask>(),
core::mem::size_of::<U::BitMask>()
);
unsafe { core::mem::transmute_copy(&bitmask) }
}
#[inline]
pub fn any(self) -> bool {
self != Self::splat(false)

View file

@ -126,6 +126,30 @@ macro_rules! define_mask {
bitmask
}
}
#[inline]
pub fn from_bitmask<U: crate::Mask>(mut bitmask: U::BitMask) -> Self {
unsafe {
// There is a bug where LLVM appears to implement this operation with the wrong
// bit order.
// TODO fix this in a better way
if cfg!(any(target_arch = "mips", target_arch = "mips64")) {
for x in bitmask.as_mut() {
*x = x.reverse_bits();
}
}
// TODO remove the transmute when rustc is more flexible
assert_eq!(core::mem::size_of::<U::IntBitMask>(), core::mem::size_of::<U::BitMask>());
let bitmask: U::IntBitMask = core::mem::transmute_copy(&bitmask);
Self::from_int_unchecked(crate::intrinsics::simd_select_bitmask(
bitmask,
Self::splat(true).to_int(),
Self::splat(false).to_int(),
))
}
}
}
impl<T: Mask, const LANES: usize> core::convert::From<$name<T, LANES>> for crate::$type<LANES>

View file

@ -178,6 +178,11 @@ macro_rules! define_opaque_mask {
pub fn to_bitmask(self) -> <Self as Mask>::BitMask {
self.0.to_bitmask::<Self>()
}
/// Convert a bitmask to a mask.
pub fn from_bitmask(bitmask: <Self as Mask>::BitMask) -> Self {
Self(<$inner_ty>::from_bitmask::<Self>(bitmask))
}
}
// vector/array conversion

View file

@ -67,13 +67,15 @@ macro_rules! test_mask_api {
}
#[test]
fn to_bitmask() {
fn roundtrip_bitmask_conversion() {
let values = [
true, false, false, true, false, false, true, false,
true, true, false, false, false, false, false, true,
];
let mask = core_simd::$name::<16>::from_array(values);
assert_eq!(mask.to_bitmask(), [0b01001001, 0b10000011]);
let bitmask = mask.to_bitmask();
assert_eq!(bitmask, [0b01001001, 0b10000011]);
assert_eq!(core_simd::$name::<16>::from_bitmask(bitmask), mask);
}
}
}