)]
mod mask_impl;
+use crate::simd::intrinsics;
use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount};
use core::cmp::Ordering;
-use core::fmt;
+use core::{fmt, mem};
mod sealed {
use super::*;
Self(mask_impl::Mask::splat(value))
}
- /// Converts an array to a SIMD vector.
+ /// Converts an array of bools to a SIMD mask.
pub fn from_array(array: [bool; LANES]) -> Self {
- let mut vector = Self::splat(false);
- for (i, v) in array.iter().enumerate() {
- vector.set(i, *v);
+ // SAFETY: Rust's bool has a layout of 1 byte (u8) with a value of
+ // true: 0b_0000_0001
+ // false: 0b_0000_0000
+ // Thus, an array of bools is also a valid array of bytes: [u8; N]
+ // This would be hypothetically valid as an "in-place" transmute,
+ // but these are "dependently-sized" types, so copy elision it is!
+ unsafe {
+ let bytes: [u8; LANES] = mem::transmute_copy(&array);
+ let bools: Simd<i8, LANES> =
+ intrinsics::simd_ne(Simd::from_array(bytes), Simd::splat(0u8));
+ Mask::from_int_unchecked(intrinsics::simd_cast(bools))
}
- vector
}
- /// Converts a SIMD vector to an array.
+ /// Converts a SIMD mask to an array of bools.
pub fn to_array(self) -> [bool; LANES] {
- let mut array = [false; LANES];
- for (i, v) in array.iter_mut().enumerate() {
- *v = self.test(i);
+ // This follows mostly the same logic as from_array.
+ // SAFETY: Rust's bool has a layout of 1 byte (u8) with a value of
+ // true: 0b_0000_0001
+ // false: 0b_0000_0000
+ // Thus, an array of bools is also a valid array of bytes: [u8; N]
+ // Since our masks are equal to integers where all bits are set,
+ // we can simply convert them to i8s, and then bitand them by the
+ // bitpattern for Rust's "true" bool.
+ // This would be hypothetically valid as an "in-place" transmute,
+ // but these are "dependently-sized" types, so copy elision it is!
+ unsafe {
+ let mut bytes: Simd<i8, LANES> = intrinsics::simd_cast(self.to_int());
+ bytes &= Simd::splat(1i8);
+ mem::transmute_copy(&bytes)
}
- array
}
/// Converts a vector of integers to a mask, where 0 represents `false` and -1
pub type mask16x16 = Mask<i16, 16>;
/// Vector of 32 16-bit masks
-pub type mask16x32 = Mask<i32, 32>;
+pub type mask16x32 = Mask<i16, 32>;
/// Vector of two 32-bit masks
pub type mask32x2 = Mask<i32, 2>;