Finish refactoring vector types
This commit is contained in:
parent
25c7640fb3
commit
9cc3deaa92
27 changed files with 615 additions and 732 deletions
|
@ -1,7 +1,7 @@
|
|||
//! This module contains the LLVM intrinsics bindings that provide the functionality for this
|
||||
//! crate.
|
||||
//!
|
||||
//! The LLVM assembly language is documented here: https://llvm.org/docs/LangRef.html
|
||||
//! The LLVM assembly language is documented here: <https://llvm.org/docs/LangRef.html>
|
||||
|
||||
/// These intrinsics aren't linked directly from LLVM and are mostly undocumented, however they are
|
||||
/// simply lowered to the matching LLVM instructions by the compiler. The associated instruction
|
||||
|
|
|
@ -11,8 +11,8 @@ mod intrinsics;
|
|||
mod ops;
|
||||
//mod round;
|
||||
|
||||
//pub mod masks;
|
||||
//pub use masks::opaque::*;
|
||||
mod masks;
|
||||
pub use masks::*;
|
||||
|
||||
mod vectors_u8;
|
||||
pub use vectors_u8::*;
|
||||
|
|
199
crates/core_simd/src/masks/full_masks/mod.rs
Normal file
199
crates/core_simd/src/masks/full_masks/mod.rs
Normal file
|
@ -0,0 +1,199 @@
|
|||
//! Masks that take up full SIMD vector registers.
|
||||
|
||||
/// The error type returned when converting an integer to a mask fails.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct TryFromMaskError(());
|
||||
|
||||
impl core::fmt::Display for TryFromMaskError {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
write!(f, "mask vector must have all bits set or unset in each lane")
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! define_mask {
|
||||
{ $(#[$attr:meta])* struct $name:ident<const $lanes:ident: usize>($type:ty); } => {
|
||||
$(#[$attr])*
|
||||
#[derive(Copy, Clone, Default, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||
#[repr(transparent)]
|
||||
pub struct $name<const $lanes: usize>($type);
|
||||
|
||||
delegate_ops_to_inner! { $name }
|
||||
|
||||
impl<const $lanes: usize> $name<$lanes> {
|
||||
/// Construct a mask by setting all lanes to the given value.
|
||||
pub fn splat(value: bool) -> Self {
|
||||
Self(<$type>::splat(value.into()))
|
||||
}
|
||||
|
||||
/// Tests the value of the specified lane.
|
||||
///
|
||||
/// # Panics
|
||||
/// Panics if `lane` is greater than or equal to the number of lanes in the vector.
|
||||
#[inline]
|
||||
pub fn test(&self, lane: usize) -> bool {
|
||||
self.0[lane] > 0
|
||||
}
|
||||
|
||||
/// Sets the value of the specified lane.
|
||||
///
|
||||
/// # Panics
|
||||
/// Panics if `lane` is greater than or equal to the number of lanes in the vector.
|
||||
#[inline]
|
||||
pub fn set(&mut self, lane: usize, value: bool) {
|
||||
self.0[lane] = if value {
|
||||
!0
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<const $lanes: usize> core::convert::From<bool> for $name<$lanes> {
|
||||
fn from(value: bool) -> Self {
|
||||
Self::splat(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const $lanes: usize> core::convert::TryFrom<$type> for $name<$lanes> {
|
||||
type Error = TryFromMaskError;
|
||||
fn try_from(value: $type) -> Result<Self, Self::Error> {
|
||||
if value.as_slice().iter().all(|x| *x == 0 || !*x == 0) {
|
||||
Ok(Self(value))
|
||||
} else {
|
||||
Err(TryFromMaskError(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<const $lanes: usize> core::convert::From<$name<$lanes>> for $type {
|
||||
fn from(value: $name<$lanes>) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<const $lanes: usize> core::fmt::Debug for $name<$lanes> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
f.debug_list()
|
||||
.entries((0..LANES).map(|lane| self.test(lane)))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<const $lanes: usize> core::fmt::Binary for $name<$lanes> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
core::fmt::Binary::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const $lanes: usize> core::fmt::Octal for $name<$lanes> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
core::fmt::Octal::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const $lanes: usize> core::fmt::LowerHex for $name<$lanes> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
core::fmt::LowerHex::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const $lanes: usize> core::fmt::UpperHex for $name<$lanes> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
core::fmt::UpperHex::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
define_mask! {
|
||||
/// A mask equivalent to [SimdI8](crate::SimdI8), where all bits in the lane must be either set
|
||||
/// or unset.
|
||||
struct SimdI8Mask<const LANES: usize>(crate::SimdI8<LANES>);
|
||||
}
|
||||
|
||||
define_mask! {
|
||||
/// A mask equivalent to [SimdI16](crate::SimdI16), where all bits in the lane must be either set
|
||||
/// or unset.
|
||||
struct SimdI16Mask<const LANES: usize>(crate::SimdI16<LANES>);
|
||||
}
|
||||
|
||||
define_mask! {
|
||||
/// A mask equivalent to [SimdI32](crate::SimdI32), where all bits in the lane must be either set
|
||||
/// or unset.
|
||||
struct SimdI32Mask<const LANES: usize>(crate::SimdI32<LANES>);
|
||||
}
|
||||
|
||||
define_mask! {
|
||||
/// A mask equivalent to [SimdI64](crate::SimdI64), where all bits in the lane must be either set
|
||||
/// or unset.
|
||||
struct SimdI64Mask<const LANES: usize>(crate::SimdI64<LANES>);
|
||||
}
|
||||
|
||||
define_mask! {
|
||||
/// A mask equivalent to [SimdI128](crate::SimdI128), where all bits in the lane must be either set
|
||||
/// or unset.
|
||||
struct SimdI128Mask<const LANES: usize>(crate::SimdI64<LANES>);
|
||||
}
|
||||
|
||||
define_mask! {
|
||||
/// A mask equivalent to [SimdIsize](crate::SimdIsize), where all bits in the lane must be either set
|
||||
/// or unset.
|
||||
struct SimdIsizeMask<const LANES: usize>(crate::SimdI64<LANES>);
|
||||
}
|
||||
|
||||
macro_rules! implement_mask_ext {
|
||||
{ $($vector:ident => $mask:ident,)* } => {
|
||||
$(
|
||||
impl<const LANES: usize> crate::masks::MaskExt<$mask<LANES>> for crate::$vector<LANES> {
|
||||
#[inline]
|
||||
fn lanes_eq(&self, other: &Self) -> $mask<LANES> {
|
||||
unsafe { crate::intrinsics::simd_eq(self, other) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn lanes_ne(&self, other: &Self) -> $mask<LANES> {
|
||||
unsafe { crate::intrinsics::simd_ne(self, other) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn lanes_lt(&self, other: &Self) -> $mask<LANES> {
|
||||
unsafe { crate::intrinsics::simd_lt(self, other) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn lanes_gt(&self, other: &Self) -> $mask<LANES> {
|
||||
unsafe { crate::intrinsics::simd_gt(self, other) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn lanes_le(&self, other: &Self) -> $mask<LANES> {
|
||||
unsafe { crate::intrinsics::simd_le(self, other) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn lanes_ge(&self, other: &Self) -> $mask<LANES> {
|
||||
unsafe { crate::intrinsics::simd_ge(self, other) }
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
implement_mask_ext! {
|
||||
SimdI8 => SimdI8Mask,
|
||||
SimdI16 => SimdI16Mask,
|
||||
SimdI32 => SimdI32Mask,
|
||||
SimdI64 => SimdI64Mask,
|
||||
SimdI128 => SimdI128Mask,
|
||||
SimdIsize => SimdIsizeMask,
|
||||
|
||||
SimdU8 => SimdI8Mask,
|
||||
SimdU16 => SimdI16Mask,
|
||||
SimdU32 => SimdI32Mask,
|
||||
SimdU64 => SimdI64Mask,
|
||||
SimdU128 => SimdI128Mask,
|
||||
SimdUsize => SimdIsizeMask,
|
||||
|
||||
SimdF32 => SimdI32Mask,
|
||||
SimdF64 => SimdI64Mask,
|
||||
}
|
|
@ -19,3 +19,6 @@ define_mask_vector! {
|
|||
/// Vector of 64 `m8` values
|
||||
struct m8x64([i8 as m8; 64]);
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
struct VectorMask8<const LANES: usize>(crate::SimdI8<LANES>);
|
|
@ -1,115 +1,151 @@
|
|||
//! Types and traits associated with masking lanes of vectors.
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
pub mod wide;
|
||||
macro_rules! delegate_ops_to_inner {
|
||||
{ $name:ident } => {
|
||||
impl<const LANES: usize> core::ops::BitAnd for $name<LANES> {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn bitand(self, rhs: Self) -> Self {
|
||||
Self(self.0 & rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
mod ops;
|
||||
pub use ops::*;
|
||||
impl<const LANES: usize> core::ops::BitAnd<bool> for $name<LANES> {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn bitand(self, rhs: bool) -> Self {
|
||||
self & Self::splat(rhs)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait MaskImpl {
|
||||
type Mask;
|
||||
impl<const LANES: usize> core::ops::BitAnd<$name<LANES>> for bool {
|
||||
type Output = $name<LANES>;
|
||||
#[inline]
|
||||
fn bitand(self, rhs: $name<LANES>) -> $name<LANES> {
|
||||
$name::<LANES>::splat(self) & rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LANES: usize> core::ops::BitOr for $name<LANES> {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn bitor(self, rhs: Self) -> Self {
|
||||
Self(self.0 | rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LANES: usize> core::ops::BitOr<bool> for $name<LANES> {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn bitor(self, rhs: bool) -> Self {
|
||||
self | Self::splat(rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LANES: usize> core::ops::BitOr<$name<LANES>> for bool {
|
||||
type Output = $name<LANES>;
|
||||
#[inline]
|
||||
fn bitor(self, rhs: $name<LANES>) -> $name<LANES> {
|
||||
$name::<LANES>::splat(self) | rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LANES: usize> core::ops::BitXor for $name<LANES> {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn bitxor(self, rhs: Self) -> Self::Output {
|
||||
Self(self.0 ^ rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LANES: usize> core::ops::BitXor<bool> for $name<LANES> {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn bitxor(self, rhs: bool) -> Self::Output {
|
||||
self ^ Self::splat(rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LANES: usize> core::ops::BitXor<$name<LANES>> for bool {
|
||||
type Output = $name<LANES>;
|
||||
#[inline]
|
||||
fn bitxor(self, rhs: $name<LANES>) -> Self::Output {
|
||||
$name::<LANES>::splat(self) ^ rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LANES: usize> core::ops::Not for $name<LANES> {
|
||||
type Output = $name<LANES>;
|
||||
#[inline]
|
||||
fn not(self) -> Self::Output {
|
||||
Self(!self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LANES: usize> core::ops::BitAndAssign for $name<LANES> {
|
||||
#[inline]
|
||||
fn bitand_assign(&mut self, rhs: Self) {
|
||||
self.0 &= rhs.0;
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LANES: usize> core::ops::BitAndAssign<bool> for $name<LANES> {
|
||||
#[inline]
|
||||
fn bitand_assign(&mut self, rhs: bool) {
|
||||
*self &= Self::splat(rhs);
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LANES: usize> core::ops::BitOrAssign for $name<LANES> {
|
||||
#[inline]
|
||||
fn bitor_assign(&mut self, rhs: Self) {
|
||||
self.0 |= rhs.0;
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LANES: usize> core::ops::BitOrAssign<bool> for $name<LANES> {
|
||||
#[inline]
|
||||
fn bitor_assign(&mut self, rhs: bool) {
|
||||
*self |= Self::splat(rhs);
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LANES: usize> core::ops::BitXorAssign for $name<LANES> {
|
||||
#[inline]
|
||||
fn bitxor_assign(&mut self, rhs: Self) {
|
||||
self.0 ^= rhs.0;
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LANES: usize> core::ops::BitXorAssign<bool> for $name<LANES> {
|
||||
#[inline]
|
||||
fn bitxor_assign(&mut self, rhs: bool) {
|
||||
*self ^= Self::splat(rhs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MaskImpl for [u8; 8] {
|
||||
type Mask = wide::m8x8;
|
||||
}
|
||||
|
||||
impl MaskImpl for [u8; 16] {
|
||||
type Mask = wide::m8x16;
|
||||
}
|
||||
|
||||
impl MaskImpl for [u8; 32] {
|
||||
type Mask = wide::m8x32;
|
||||
}
|
||||
|
||||
impl MaskImpl for [u8; 64] {
|
||||
type Mask = wide::m8x64;
|
||||
}
|
||||
|
||||
impl MaskImpl for [u16; 4] {
|
||||
type Mask = wide::m16x4;
|
||||
}
|
||||
|
||||
impl MaskImpl for [u16; 8] {
|
||||
type Mask = wide::m16x8;
|
||||
}
|
||||
|
||||
impl MaskImpl for [u16; 16] {
|
||||
type Mask = wide::m16x16;
|
||||
}
|
||||
|
||||
impl MaskImpl for [u16; 32] {
|
||||
type Mask = wide::m16x32;
|
||||
}
|
||||
|
||||
impl MaskImpl for [u32; 2] {
|
||||
type Mask = wide::m32x2;
|
||||
}
|
||||
|
||||
impl MaskImpl for [u32; 4] {
|
||||
type Mask = wide::m32x4;
|
||||
}
|
||||
|
||||
impl MaskImpl for [u32; 8] {
|
||||
type Mask = wide::m32x8;
|
||||
}
|
||||
|
||||
impl MaskImpl for [u32; 16] {
|
||||
type Mask = wide::m32x16;
|
||||
}
|
||||
|
||||
impl MaskImpl for [u64; 2] {
|
||||
type Mask = wide::m64x2;
|
||||
}
|
||||
|
||||
impl MaskImpl for [u64; 4] {
|
||||
type Mask = wide::m64x4;
|
||||
}
|
||||
|
||||
impl MaskImpl for [u64; 8] {
|
||||
type Mask = wide::m64x8;
|
||||
}
|
||||
|
||||
impl MaskImpl for [u128; 2] {
|
||||
type Mask = wide::m128x2;
|
||||
}
|
||||
|
||||
impl MaskImpl for [u128; 4] {
|
||||
type Mask = wide::m128x4;
|
||||
}
|
||||
|
||||
impl MaskImpl for [usize; 2] {
|
||||
type Mask = wide::msizex2;
|
||||
}
|
||||
|
||||
impl MaskImpl for [usize; 4] {
|
||||
type Mask = wide::msizex4;
|
||||
}
|
||||
|
||||
impl MaskImpl for [usize; 8] {
|
||||
type Mask = wide::msizex8;
|
||||
}
|
||||
pub mod full_masks;
|
||||
|
||||
macro_rules! define_opaque_mask {
|
||||
{
|
||||
$(#[$attr:meta])*
|
||||
struct $name:ident([$width:ty; $lanes:tt]);
|
||||
struct $name:ident<const $lanes:ident: usize>($inner_ty:ty);
|
||||
} => {
|
||||
$(#[$attr])*
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct $name(<[$width; $lanes] as crate::masks::MaskImpl>::Mask);
|
||||
pub struct $name<const $lanes: usize>($inner_ty);
|
||||
|
||||
impl $name {
|
||||
pub(crate) fn new_from_inner(inner: <[$width; $lanes] as crate::masks::MaskImpl>::Mask) -> Self {
|
||||
Self(inner)
|
||||
}
|
||||
delegate_ops_to_inner! { $name }
|
||||
|
||||
impl<const $lanes: usize> $name<$lanes> {
|
||||
/// Construct a mask by setting all lanes to the given value.
|
||||
pub fn splat(value: bool) -> Self {
|
||||
Self(<[$width; $lanes] as crate::masks::MaskImpl>::Mask::splat(value.into()))
|
||||
Self(<$inner_ty>::splat(value))
|
||||
}
|
||||
|
||||
call_counting_args! { $lanes => define_opaque_mask => new [$width; $lanes] }
|
||||
|
||||
/// Tests the value of the specified lane.
|
||||
///
|
||||
/// # Panics
|
||||
|
@ -129,312 +165,226 @@ macro_rules! define_opaque_mask {
|
|||
}
|
||||
}
|
||||
|
||||
impl Copy for $name {}
|
||||
impl<const $lanes: usize> Copy for $name<$lanes> {}
|
||||
|
||||
impl Clone for $name {
|
||||
impl<const $lanes: usize> Clone for $name<$lanes> {
|
||||
#[inline]
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for $name {
|
||||
impl<const $lanes: usize> Default for $name<$lanes> {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Self::splat(false)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for $name {
|
||||
impl<const $lanes: usize> PartialEq for $name<$lanes> {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.0 == other.0
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for $name {
|
||||
impl<const $lanes: usize> PartialOrd for $name<$lanes> {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
|
||||
self.0.partial_cmp(&other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for $name {
|
||||
impl<const $lanes: usize> core::fmt::Debug for $name<$lanes> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
core::fmt::Debug::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::BitAnd for $name {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn bitand(self, rhs: Self) -> Self {
|
||||
Self(self.0 & rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::BitAnd<bool> for $name {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn bitand(self, rhs: bool) -> Self {
|
||||
self & Self::splat(rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::BitAnd<$name> for bool {
|
||||
type Output = $name;
|
||||
#[inline]
|
||||
fn bitand(self, rhs: $name) -> $name {
|
||||
$name::splat(self) & rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::BitOr for $name {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn bitor(self, rhs: Self) -> Self {
|
||||
Self(self.0 | rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::BitOr<bool> for $name {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn bitor(self, rhs: bool) -> Self {
|
||||
self | Self::splat(rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::BitOr<$name> for bool {
|
||||
type Output = $name;
|
||||
#[inline]
|
||||
fn bitor(self, rhs: $name) -> $name {
|
||||
$name::splat(self) | rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::BitXor for $name {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn bitxor(self, rhs: Self) -> Self::Output {
|
||||
Self(self.0 ^ rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::BitXor<bool> for $name {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn bitxor(self, rhs: bool) -> Self::Output {
|
||||
self ^ Self::splat(rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::BitXor<$name> for bool {
|
||||
type Output = $name;
|
||||
#[inline]
|
||||
fn bitxor(self, rhs: $name) -> Self::Output {
|
||||
$name::splat(self) ^ rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::Not for $name {
|
||||
type Output = $name;
|
||||
#[inline]
|
||||
fn not(self) -> Self::Output {
|
||||
Self(!self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::BitAndAssign for $name {
|
||||
#[inline]
|
||||
fn bitand_assign(&mut self, rhs: Self) {
|
||||
self.0 &= rhs.0;
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::BitAndAssign<bool> for $name {
|
||||
#[inline]
|
||||
fn bitand_assign(&mut self, rhs: bool) {
|
||||
*self &= Self::splat(rhs);
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::BitOrAssign for $name {
|
||||
#[inline]
|
||||
fn bitor_assign(&mut self, rhs: Self) {
|
||||
self.0 |= rhs.0;
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::BitOrAssign<bool> for $name {
|
||||
#[inline]
|
||||
fn bitor_assign(&mut self, rhs: bool) {
|
||||
*self |= Self::splat(rhs);
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::BitXorAssign for $name {
|
||||
#[inline]
|
||||
fn bitxor_assign(&mut self, rhs: Self) {
|
||||
self.0 ^= rhs.0;
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::BitXorAssign<bool> for $name {
|
||||
#[inline]
|
||||
fn bitxor_assign(&mut self, rhs: bool) {
|
||||
*self ^= Self::splat(rhs);
|
||||
}
|
||||
}
|
||||
};
|
||||
{ new [$width:ty; $lanes:tt] $($var:ident)* } => {
|
||||
/// Construct a vector by setting each lane to the given values.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[inline]
|
||||
pub const fn new($($var: bool),*) -> Self {
|
||||
Self(<[$width; $lanes] as crate::masks::MaskImpl>::Mask::new_from_bool($($var),*))
|
||||
}
|
||||
}
|
||||
|
||||
define_opaque_mask! {
|
||||
/// Mask for vectors with `LANES` 8-bit elements.
|
||||
///
|
||||
/// The layout of this type is unspecified.
|
||||
struct Mask8<const LANES: usize>(full_masks::SimdI8Mask<LANES>);
|
||||
}
|
||||
|
||||
define_opaque_mask! {
|
||||
/// Mask for vectors with `LANES` 16-bit elements.
|
||||
///
|
||||
/// The layout of this type is unspecified.
|
||||
struct Mask16<const LANES: usize>(full_masks::SimdI16Mask<LANES>);
|
||||
}
|
||||
|
||||
define_opaque_mask! {
|
||||
/// Mask for vectors with `LANES` 32-bit elements.
|
||||
///
|
||||
/// The layout of this type is unspecified.
|
||||
struct Mask32<const LANES: usize>(full_masks::SimdI32Mask<LANES>);
|
||||
}
|
||||
|
||||
define_opaque_mask! {
|
||||
/// Mask for vectors with `LANES` 64-bit elements.
|
||||
///
|
||||
/// The layout of this type is unspecified.
|
||||
struct Mask64<const LANES: usize>(full_masks::SimdI64Mask<LANES>);
|
||||
}
|
||||
|
||||
define_opaque_mask! {
|
||||
/// Mask for vectors with `LANES` 128-bit elements.
|
||||
///
|
||||
/// The layout of this type is unspecified.
|
||||
struct Mask128<const LANES: usize>(full_masks::SimdI128Mask<LANES>);
|
||||
}
|
||||
|
||||
define_opaque_mask! {
|
||||
/// Mask for vectors with `LANES` pointer-width elements.
|
||||
///
|
||||
/// The layout of this type is unspecified.
|
||||
struct MaskSize<const LANES: usize>(full_masks::SimdIsizeMask<LANES>);
|
||||
}
|
||||
|
||||
/// Mask-related operations using a particular mask layout.
|
||||
pub trait MaskExt<Mask> {
|
||||
/// Test if each lane is equal to the corresponding lane in `other`.
|
||||
fn lanes_eq(&self, other: &Self) -> Mask;
|
||||
|
||||
/// Test if each lane is not equal to the corresponding lane in `other`.
|
||||
fn lanes_ne(&self, other: &Self) -> Mask;
|
||||
|
||||
/// Test if each lane is less than the corresponding lane in `other`.
|
||||
fn lanes_lt(&self, other: &Self) -> Mask;
|
||||
|
||||
/// Test if each lane is greater than the corresponding lane in `other`.
|
||||
fn lanes_gt(&self, other: &Self) -> Mask;
|
||||
|
||||
/// Test if each lane is less than or equal to the corresponding lane in `other`.
|
||||
fn lanes_le(&self, other: &Self) -> Mask;
|
||||
|
||||
/// Test if each lane is greater than or equal to the corresponding lane in `other`.
|
||||
fn lanes_ge(&self, other: &Self) -> Mask;
|
||||
}
|
||||
|
||||
macro_rules! implement_mask_ops {
|
||||
{ $($vector:ident => $mask:ident,)* } => {
|
||||
$(
|
||||
impl<const LANES: usize> crate::$vector<LANES> {
|
||||
/// Test if each lane is equal to the corresponding lane in `other`.
|
||||
#[inline]
|
||||
pub fn lanes_eq(&self, other: &Self) -> $mask<LANES> {
|
||||
$mask(MaskExt::lanes_eq(self, other))
|
||||
}
|
||||
|
||||
/// Test if each lane is not equal to the corresponding lane in `other`.
|
||||
#[inline]
|
||||
pub fn lanes_ne(&self, other: &Self) -> $mask<LANES> {
|
||||
$mask(MaskExt::lanes_ne(self, other))
|
||||
}
|
||||
|
||||
/// Test if each lane is less than the corresponding lane in `other`.
|
||||
#[inline]
|
||||
pub fn lanes_lt(&self, other: &Self) -> $mask<LANES> {
|
||||
$mask(MaskExt::lanes_lt(self, other))
|
||||
}
|
||||
|
||||
/// Test if each lane is greater than the corresponding lane in `other`.
|
||||
#[inline]
|
||||
pub fn lanes_gt(&self, other: &Self) -> $mask<LANES> {
|
||||
$mask(MaskExt::lanes_gt(self, other))
|
||||
}
|
||||
|
||||
/// Test if each lane is less than or equal to the corresponding lane in `other`.
|
||||
#[inline]
|
||||
pub fn lanes_le(&self, other: &Self) -> $mask<LANES> {
|
||||
$mask(MaskExt::lanes_le(self, other))
|
||||
}
|
||||
|
||||
/// Test if each lane is greater than or equal to the corresponding lane in `other`.
|
||||
#[inline]
|
||||
pub fn lanes_ge(&self, other: &Self) -> $mask<LANES> {
|
||||
$mask(MaskExt::lanes_ge(self, other))
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) mod opaque {
|
||||
define_opaque_mask! {
|
||||
/// Mask for 8 8-bit lanes.
|
||||
///
|
||||
/// The layout of this type is unspecified.
|
||||
struct mask8x8([u8; 8]);
|
||||
}
|
||||
implement_mask_ops! {
|
||||
SimdI8 => Mask8,
|
||||
SimdI16 => Mask16,
|
||||
SimdI32 => Mask32,
|
||||
SimdI64 => Mask64,
|
||||
SimdI128 => Mask128,
|
||||
SimdIsize => MaskSize,
|
||||
|
||||
define_opaque_mask! {
|
||||
/// Mask for 16 8-bit lanes.
|
||||
///
|
||||
/// The layout of this type is unspecified.
|
||||
struct mask8x16([u8; 16]);
|
||||
}
|
||||
SimdU8 => Mask8,
|
||||
SimdU16 => Mask16,
|
||||
SimdU32 => Mask32,
|
||||
SimdU64 => Mask64,
|
||||
SimdU128 => Mask128,
|
||||
SimdUsize => MaskSize,
|
||||
|
||||
define_opaque_mask! {
|
||||
/// Mask for 32 8-bit lanes.
|
||||
///
|
||||
/// The layout of this type is unspecified.
|
||||
struct mask8x32([u8; 32]);
|
||||
}
|
||||
|
||||
define_opaque_mask! {
|
||||
/// Mask for 64 8-bit lanes.
|
||||
///
|
||||
/// The layout of this type is unspecified.
|
||||
struct mask8x64([u8; 64]);
|
||||
}
|
||||
|
||||
define_opaque_mask! {
|
||||
/// Mask for 4 16-bit lanes.
|
||||
///
|
||||
/// The layout of this type is unspecified.
|
||||
struct mask16x4([u16; 4]);
|
||||
}
|
||||
|
||||
define_opaque_mask! {
|
||||
/// Mask for 8 16-bit lanes.
|
||||
///
|
||||
/// The layout of this type is unspecified.
|
||||
struct mask16x8([u16; 8]);
|
||||
}
|
||||
|
||||
define_opaque_mask! {
|
||||
/// Mask for 16 16-bit lanes.
|
||||
///
|
||||
/// The layout of this type is unspecified.
|
||||
struct mask16x16([u16; 16]);
|
||||
}
|
||||
|
||||
define_opaque_mask! {
|
||||
/// Mask for 32 16-bit lanes.
|
||||
///
|
||||
/// The layout of this type is unspecified.
|
||||
struct mask16x32([u16; 32]);
|
||||
}
|
||||
|
||||
define_opaque_mask! {
|
||||
/// Mask for 2 32-bit lanes.
|
||||
///
|
||||
/// The layout of this type is unspecified.
|
||||
struct mask32x2([u32; 2]);
|
||||
}
|
||||
|
||||
define_opaque_mask! {
|
||||
/// Mask for 4 32-bit lanes.
|
||||
///
|
||||
/// The layout of this type is unspecified.
|
||||
struct mask32x4([u32; 4]);
|
||||
}
|
||||
|
||||
define_opaque_mask! {
|
||||
/// Mask for 8 32-bit lanes.
|
||||
///
|
||||
/// The layout of this type is unspecified.
|
||||
struct mask32x8([u32; 8]);
|
||||
}
|
||||
|
||||
define_opaque_mask! {
|
||||
/// Mask for 16 32-bit lanes.
|
||||
///
|
||||
/// The layout of this type is unspecified.
|
||||
struct mask32x16([u32; 16]);
|
||||
}
|
||||
|
||||
define_opaque_mask! {
|
||||
/// Mask for 2 64-bit lanes.
|
||||
///
|
||||
/// The layout of this type is unspecified.
|
||||
struct mask64x2([u64; 2]);
|
||||
}
|
||||
|
||||
define_opaque_mask! {
|
||||
/// Mask for 4 64-bit lanes.
|
||||
///
|
||||
/// The layout of this type is unspecified.
|
||||
struct mask64x4([u64; 4]);
|
||||
}
|
||||
|
||||
define_opaque_mask! {
|
||||
/// Mask for 8 64-bit lanes.
|
||||
///
|
||||
/// The layout of this type is unspecified.
|
||||
struct mask64x8([u64; 8]);
|
||||
}
|
||||
|
||||
define_opaque_mask! {
|
||||
/// Mask for 2 128-bit lanes.
|
||||
///
|
||||
/// The layout of this type is unspecified.
|
||||
struct mask128x2([u128; 2]);
|
||||
}
|
||||
|
||||
define_opaque_mask! {
|
||||
/// Mask for 4 128-bit lanes.
|
||||
///
|
||||
/// The layout of this type is unspecified.
|
||||
struct mask128x4([u128; 4]);
|
||||
}
|
||||
|
||||
define_opaque_mask! {
|
||||
/// Mask for 2 `isize`-wide lanes.
|
||||
///
|
||||
/// The layout of this type is unspecified.
|
||||
struct masksizex2([usize; 2]);
|
||||
}
|
||||
|
||||
define_opaque_mask! {
|
||||
/// Mask for 4 `isize`-wide lanes.
|
||||
///
|
||||
/// The layout of this type is unspecified.
|
||||
struct masksizex4([usize; 4]);
|
||||
}
|
||||
|
||||
define_opaque_mask! {
|
||||
/// Mask for 8 `isize`-wide lanes.
|
||||
///
|
||||
/// The layout of this type is unspecified.
|
||||
struct masksizex8([usize; 8]);
|
||||
}
|
||||
SimdF32 => Mask32,
|
||||
SimdF64 => Mask64,
|
||||
}
|
||||
|
||||
/// Vector of eight 8-bit masks
|
||||
pub type mask8x8 = Mask8<8>;
|
||||
|
||||
/// Vector of 16 8-bit masks
|
||||
pub type mask8x16 = Mask8<16>;
|
||||
|
||||
/// Vector of 32 8-bit masks
|
||||
pub type mask8x32 = Mask8<32>;
|
||||
|
||||
/// Vector of 16 8-bit masks
|
||||
pub type mask8x64 = Mask8<64>;
|
||||
|
||||
/// Vector of four 16-bit masks
|
||||
pub type mask16x4 = Mask16<4>;
|
||||
|
||||
/// Vector of eight 16-bit masks
|
||||
pub type mask16x8 = Mask16<8>;
|
||||
|
||||
/// Vector of 16 16-bit masks
|
||||
pub type mask16x16 = Mask16<16>;
|
||||
|
||||
/// Vector of 32 16-bit masks
|
||||
pub type mask16x32 = Mask32<32>;
|
||||
|
||||
/// Vector of two 32-bit masks
|
||||
pub type mask32x2 = Mask32<2>;
|
||||
|
||||
/// Vector of four 32-bit masks
|
||||
pub type mask32x4 = Mask32<4>;
|
||||
|
||||
/// Vector of eight 32-bit masks
|
||||
pub type mask32x8 = Mask32<8>;
|
||||
|
||||
/// Vector of 16 32-bit masks
|
||||
pub type mask32x16 = Mask32<16>;
|
||||
|
||||
/// Vector of two 64-bit masks
|
||||
pub type mask64x2 = Mask64<2>;
|
||||
|
||||
/// Vector of four 64-bit masks
|
||||
pub type mask64x4 = Mask64<4>;
|
||||
|
||||
/// Vector of eight 64-bit masks
|
||||
pub type mask64x8 = Mask64<8>;
|
||||
|
||||
/// Vector of two 128-bit masks
|
||||
pub type mask128x2 = Mask128<2>;
|
||||
|
||||
/// Vector of four 128-bit masks
|
||||
pub type mask128x4 = Mask128<4>;
|
||||
|
||||
/// Vector of two pointer-width masks
|
||||
pub type masksizex2 = MaskSize<2>;
|
||||
|
||||
/// Vector of four pointer-width masks
|
||||
pub type masksizex4 = MaskSize<4>;
|
||||
|
||||
/// Vector of eight pointer-width masks
|
||||
pub type masksizex8 = MaskSize<8>;
|
||||
|
|
|
@ -1,208 +0,0 @@
|
|||
/// Mask-related operations using a particular mask layout.
|
||||
pub trait MaskExt<Mask> {
|
||||
/// Test if each lane is equal to the corresponding lane in `other`.
|
||||
fn lanes_eq(self, other: Self) -> Mask;
|
||||
|
||||
/// Test if each lane is not equal to the corresponding lane in `other`.
|
||||
fn lanes_ne(self, other: Self) -> Mask;
|
||||
|
||||
/// Test if each lane is less than the corresponding lane in `other`.
|
||||
fn lanes_lt(self, other: Self) -> Mask;
|
||||
|
||||
/// Test if each lane is greater than the corresponding lane in `other`.
|
||||
fn lanes_gt(self, other: Self) -> Mask;
|
||||
|
||||
/// Test if each lane is less than or equal to the corresponding lane in `other`.
|
||||
fn lanes_le(self, other: Self) -> Mask;
|
||||
|
||||
/// Test if each lane is greater than or equal to the corresponding lane in `other`.
|
||||
fn lanes_ge(self, other: Self) -> Mask;
|
||||
}
|
||||
|
||||
macro_rules! implement_mask_ext {
|
||||
{ $($vector:ty => $($mask:ty),*;)* } => {
|
||||
$( // vector
|
||||
$( // mask
|
||||
impl MaskExt<$mask> for $vector {
|
||||
#[inline]
|
||||
fn lanes_eq(self, other: Self) -> $mask {
|
||||
unsafe { crate::intrinsics::simd_eq(self, other) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn lanes_ne(self, other: Self) -> $mask {
|
||||
unsafe { crate::intrinsics::simd_ne(self, other) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn lanes_lt(self, other: Self) -> $mask {
|
||||
unsafe { crate::intrinsics::simd_lt(self, other) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn lanes_gt(self, other: Self) -> $mask {
|
||||
unsafe { crate::intrinsics::simd_gt(self, other) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn lanes_le(self, other: Self) -> $mask {
|
||||
unsafe { crate::intrinsics::simd_le(self, other) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn lanes_ge(self, other: Self) -> $mask {
|
||||
unsafe { crate::intrinsics::simd_ge(self, other) }
|
||||
}
|
||||
}
|
||||
)*
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
implement_mask_ext! {
|
||||
crate::u8x8 => crate::masks::wide::m8x8;
|
||||
crate::u8x16 => crate::masks::wide::m8x16;
|
||||
crate::u8x32 => crate::masks::wide::m8x32;
|
||||
crate::u8x64 => crate::masks::wide::m8x64;
|
||||
crate::u16x4 => crate::masks::wide::m16x4;
|
||||
crate::u16x8 => crate::masks::wide::m16x8;
|
||||
crate::u16x16 => crate::masks::wide::m16x16;
|
||||
crate::u16x32 => crate::masks::wide::m16x32;
|
||||
crate::u32x2 => crate::masks::wide::m32x2;
|
||||
crate::u32x4 => crate::masks::wide::m32x4;
|
||||
crate::u32x8 => crate::masks::wide::m32x8;
|
||||
crate::u32x16 => crate::masks::wide::m32x16;
|
||||
crate::u64x2 => crate::masks::wide::m64x2;
|
||||
crate::u64x4 => crate::masks::wide::m64x4;
|
||||
crate::u64x8 => crate::masks::wide::m64x8;
|
||||
crate::u128x2 => crate::masks::wide::m128x2;
|
||||
crate::u128x4 => crate::masks::wide::m128x4;
|
||||
crate::usizex2 => crate::masks::wide::msizex2;
|
||||
crate::usizex4 => crate::masks::wide::msizex4;
|
||||
crate::usizex8 => crate::masks::wide::msizex8;
|
||||
|
||||
crate::i8x8 => crate::masks::wide::m8x8;
|
||||
crate::i8x16 => crate::masks::wide::m8x16;
|
||||
crate::i8x32 => crate::masks::wide::m8x32;
|
||||
crate::i8x64 => crate::masks::wide::m8x64;
|
||||
crate::i16x4 => crate::masks::wide::m16x4;
|
||||
crate::i16x8 => crate::masks::wide::m16x8;
|
||||
crate::i16x16 => crate::masks::wide::m16x16;
|
||||
crate::i16x32 => crate::masks::wide::m16x32;
|
||||
crate::i32x2 => crate::masks::wide::m32x2;
|
||||
crate::i32x4 => crate::masks::wide::m32x4;
|
||||
crate::i32x8 => crate::masks::wide::m32x8;
|
||||
crate::i32x16 => crate::masks::wide::m32x16;
|
||||
crate::i64x2 => crate::masks::wide::m64x2;
|
||||
crate::i64x4 => crate::masks::wide::m64x4;
|
||||
crate::i64x8 => crate::masks::wide::m64x8;
|
||||
crate::i128x2 => crate::masks::wide::m128x2;
|
||||
crate::i128x4 => crate::masks::wide::m128x4;
|
||||
crate::isizex2 => crate::masks::wide::msizex2;
|
||||
crate::isizex4 => crate::masks::wide::msizex4;
|
||||
crate::isizex8 => crate::masks::wide::msizex8;
|
||||
|
||||
crate::f32x2 => crate::masks::wide::m32x2;
|
||||
crate::f32x4 => crate::masks::wide::m32x4;
|
||||
crate::f32x8 => crate::masks::wide::m32x8;
|
||||
crate::f32x16 => crate::masks::wide::m32x16;
|
||||
crate::f64x2 => crate::masks::wide::m64x2;
|
||||
crate::f64x4 => crate::masks::wide::m64x4;
|
||||
crate::f64x8 => crate::masks::wide::m64x8;
|
||||
}
|
||||
|
||||
macro_rules! implement_mask_ops {
|
||||
{ $($vector:ty => $mask:ty,)* } => {
|
||||
$( // vector
|
||||
impl $vector {
|
||||
/// Test if each lane is equal to the corresponding lane in `other`.
|
||||
#[inline]
|
||||
pub fn lanes_eq(self, other: Self) -> $mask {
|
||||
<$mask>::new_from_inner(MaskExt::lanes_eq(self, other))
|
||||
}
|
||||
|
||||
/// Test if each lane is not equal to the corresponding lane in `other`.
|
||||
#[inline]
|
||||
pub fn lanes_ne(self, other: Self) -> $mask {
|
||||
<$mask>::new_from_inner(MaskExt::lanes_ne(self, other))
|
||||
}
|
||||
|
||||
/// Test if each lane is less than the corresponding lane in `other`.
|
||||
#[inline]
|
||||
pub fn lanes_lt(self, other: Self) -> $mask {
|
||||
<$mask>::new_from_inner(MaskExt::lanes_lt(self, other))
|
||||
}
|
||||
|
||||
/// Test if each lane is greater than the corresponding lane in `other`.
|
||||
#[inline]
|
||||
pub fn lanes_gt(self, other: Self) -> $mask {
|
||||
<$mask>::new_from_inner(MaskExt::lanes_gt(self, other))
|
||||
}
|
||||
|
||||
/// Test if each lane is less than or equal to the corresponding lane in `other`.
|
||||
#[inline]
|
||||
pub fn lanes_le(self, other: Self) -> $mask {
|
||||
<$mask>::new_from_inner(MaskExt::lanes_le(self, other))
|
||||
}
|
||||
|
||||
/// Test if each lane is greater than or equal to the corresponding lane in `other`.
|
||||
#[inline]
|
||||
pub fn lanes_ge(self, other: Self) -> $mask {
|
||||
<$mask>::new_from_inner(MaskExt::lanes_ge(self, other))
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
implement_mask_ops! {
|
||||
crate::u8x8 => crate::mask8x8,
|
||||
crate::u8x16 => crate::mask8x16,
|
||||
crate::u8x32 => crate::mask8x32,
|
||||
crate::u8x64 => crate::mask8x64,
|
||||
crate::u16x4 => crate::mask16x4,
|
||||
crate::u16x8 => crate::mask16x8,
|
||||
crate::u16x16 => crate::mask16x16,
|
||||
crate::u16x32 => crate::mask16x32,
|
||||
crate::u32x2 => crate::mask32x2,
|
||||
crate::u32x4 => crate::mask32x4,
|
||||
crate::u32x8 => crate::mask32x8,
|
||||
crate::u32x16 => crate::mask32x16,
|
||||
crate::u64x2 => crate::mask64x2,
|
||||
crate::u64x4 => crate::mask64x4,
|
||||
crate::u64x8 => crate::mask64x8,
|
||||
crate::u128x2 => crate::mask128x2,
|
||||
crate::u128x4 => crate::mask128x4,
|
||||
crate::usizex2 => crate::masksizex2,
|
||||
crate::usizex4 => crate::masksizex4,
|
||||
crate::usizex8 => crate::masksizex8,
|
||||
|
||||
crate::i8x8 => crate::mask8x8,
|
||||
crate::i8x16 => crate::mask8x16,
|
||||
crate::i8x32 => crate::mask8x32,
|
||||
crate::i8x64 => crate::mask8x64,
|
||||
crate::i16x4 => crate::mask16x4,
|
||||
crate::i16x8 => crate::mask16x8,
|
||||
crate::i16x16 => crate::mask16x16,
|
||||
crate::i16x32 => crate::mask16x32,
|
||||
crate::i32x2 => crate::mask32x2,
|
||||
crate::i32x4 => crate::mask32x4,
|
||||
crate::i32x8 => crate::mask32x8,
|
||||
crate::i32x16 => crate::mask32x16,
|
||||
crate::i64x2 => crate::mask64x2,
|
||||
crate::i64x4 => crate::mask64x4,
|
||||
crate::i64x8 => crate::mask64x8,
|
||||
crate::i128x2 => crate::mask128x2,
|
||||
crate::i128x4 => crate::mask128x4,
|
||||
crate::isizex2 => crate::masksizex2,
|
||||
crate::isizex4 => crate::masksizex4,
|
||||
crate::isizex8 => crate::masksizex8,
|
||||
|
||||
crate::f32x2 => crate::mask32x2,
|
||||
crate::f32x4 => crate::mask32x4,
|
||||
crate::f32x8 => crate::mask32x8,
|
||||
crate::f32x16 => crate::mask32x16,
|
||||
crate::f64x2 => crate::mask64x2,
|
||||
crate::f64x4 => crate::mask64x4,
|
||||
crate::f64x8 => crate::mask64x8,
|
||||
}
|
|
@ -1,139 +0,0 @@
|
|||
//! Masks that take up full vector registers.
|
||||
|
||||
mod vectors_m8;
|
||||
pub use vectors_m8::*;
|
||||
mod vectors_m16;
|
||||
pub use vectors_m16::*;
|
||||
mod vectors_m32;
|
||||
pub use vectors_m32::*;
|
||||
mod vectors_m64;
|
||||
pub use vectors_m64::*;
|
||||
mod vectors_m128;
|
||||
pub use vectors_m128::*;
|
||||
mod vectors_msize;
|
||||
pub use vectors_msize::*;
|
||||
|
||||
/// The error type returned when converting an integer to a mask fails.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct TryFromMaskError(());
|
||||
|
||||
impl core::fmt::Display for TryFromMaskError {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
write!(f, "mask must have all bits set or unset")
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! define_mask {
|
||||
{ $(#[$attr:meta])* struct $name:ident($type:ty); } => {
|
||||
$(#[$attr])*
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Copy, Clone, Default, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||
#[repr(transparent)]
|
||||
pub struct $name(pub(crate) $type);
|
||||
|
||||
impl $name {
|
||||
/// Construct a mask from the given value.
|
||||
pub const fn new(value: bool) -> Self {
|
||||
if value {
|
||||
Self(!0)
|
||||
} else {
|
||||
Self(0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Test if the mask is set.
|
||||
pub const fn test(&self) -> bool {
|
||||
self.0 != 0
|
||||
}
|
||||
}
|
||||
|
||||
impl core::convert::From<bool> for $name {
|
||||
fn from(value: bool) -> Self {
|
||||
Self::new(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::convert::From<$name> for bool {
|
||||
fn from(mask: $name) -> Self {
|
||||
mask.test()
|
||||
}
|
||||
}
|
||||
|
||||
impl core::convert::TryFrom<$type> for $name {
|
||||
type Error = TryFromMaskError;
|
||||
fn try_from(value: $type) -> Result<Self, Self::Error> {
|
||||
if value == 0 || !value == 0 {
|
||||
Ok(Self(value))
|
||||
} else {
|
||||
Err(TryFromMaskError(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl core::convert::From<$name> for $type {
|
||||
fn from(value: $name) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for $name {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
self.test().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Binary for $name {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
core::fmt::Binary::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Octal for $name {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
core::fmt::Octal::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::LowerHex for $name {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
core::fmt::LowerHex::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::UpperHex for $name {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
core::fmt::UpperHex::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
define_mask! {
|
||||
/// 8-bit mask
|
||||
struct m8(i8);
|
||||
}
|
||||
|
||||
define_mask! {
|
||||
/// 16-bit mask
|
||||
struct m16(i16);
|
||||
}
|
||||
|
||||
define_mask! {
|
||||
/// 32-bit mask
|
||||
struct m32(i32);
|
||||
}
|
||||
|
||||
define_mask! {
|
||||
/// 64-bit mask
|
||||
struct m64(i64);
|
||||
}
|
||||
|
||||
define_mask! {
|
||||
/// 128-bit mask
|
||||
struct m128(i128);
|
||||
}
|
||||
|
||||
define_mask! {
|
||||
/// `isize`-wide mask
|
||||
struct msize(isize);
|
||||
}
|
|
@ -1,14 +1,21 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
|
||||
/// A SIMD vector of containing `LANES` lanes of `f32`.
|
||||
/// A SIMD vector of containing `LANES` `f32` values.
|
||||
#[repr(simd)]
|
||||
pub struct SimdF32<const LANES: usize>([f32; LANES]);
|
||||
|
||||
impl_float_vector! { SimdF32, f32, SimdU32 }
|
||||
|
||||
/// Vector of two `f32` values
|
||||
pub type f32x2 = SimdF32<2>;
|
||||
|
||||
/// Vector of four `f32` values
|
||||
pub type f32x4 = SimdF32<4>;
|
||||
|
||||
/// Vector of eight `f32` values
|
||||
pub type f32x8 = SimdF32<8>;
|
||||
|
||||
/// Vector of 16 `f32` values
|
||||
pub type f32x16 = SimdF32<16>;
|
||||
|
||||
from_transmute_x86! { unsafe f32x4 => __m128 }
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
|
||||
/// A SIMD vector of containing `LANES` lanes of `f64`.
|
||||
/// A SIMD vector of containing `LANES` `f64` values.
|
||||
#[repr(simd)]
|
||||
pub struct SimdF64<const LANES: usize>([f64; LANES]);
|
||||
|
||||
impl_float_vector! { SimdF64, f64, SimdU64 }
|
||||
|
||||
/// Vector of two `f64` values
|
||||
pub type f64x2 = SimdF64<2>;
|
||||
|
||||
/// Vector of four `f64` values
|
||||
pub type f64x4 = SimdF64<4>;
|
||||
|
||||
/// Vector of eight `f64` values
|
||||
pub type f64x8 = SimdF64<8>;
|
||||
|
||||
from_transmute_x86! { unsafe f64x2 => __m128d }
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
|
||||
/// A SIMD vector of containing `LANES` lanes of `i128`.
|
||||
/// A SIMD vector of containing `LANES` `i128` values.
|
||||
#[repr(simd)]
|
||||
pub struct SimdI128<const LANES: usize>([i128; LANES]);
|
||||
|
||||
impl_integer_vector! { SimdI128, i128 }
|
||||
|
||||
/// Vector of two `i128` values
|
||||
pub type i128x2 = SimdI128<2>;
|
||||
|
||||
/// Vector of four `i128` values
|
||||
pub type i128x4 = SimdI128<4>;
|
||||
|
||||
from_transmute_x86! { unsafe i128x2 => __m256i }
|
||||
|
|
|
@ -1,14 +1,21 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
|
||||
/// A SIMD vector of containing `LANES` lanes of `i16`.
|
||||
/// A SIMD vector of containing `LANES` `i16` values.
|
||||
#[repr(simd)]
|
||||
pub struct SimdI16<const LANES: usize>([i16; LANES]);
|
||||
|
||||
impl_integer_vector! { SimdI16, i16 }
|
||||
|
||||
/// Vector of four `i16` values
|
||||
pub type i16x4 = SimdI16<4>;
|
||||
|
||||
/// Vector of eight `i16` values
|
||||
pub type i16x8 = SimdI16<8>;
|
||||
|
||||
/// Vector of 16 `i16` values
|
||||
pub type i16x16 = SimdI16<16>;
|
||||
|
||||
/// Vector of 32 `i16` values
|
||||
pub type i16x32 = SimdI16<32>;
|
||||
|
||||
from_transmute_x86! { unsafe i16x8 => __m128i }
|
||||
|
|
|
@ -1,14 +1,21 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
|
||||
/// A SIMD vector of containing `LANES` lanes of `i32`.
|
||||
/// A SIMD vector of containing `LANES` `i32` values.
|
||||
#[repr(simd)]
|
||||
pub struct SimdI32<const LANES: usize>([i32; LANES]);
|
||||
|
||||
impl_integer_vector! { SimdI32, i32 }
|
||||
|
||||
/// Vector of two `i32` values
|
||||
pub type i32x2 = SimdI32<2>;
|
||||
|
||||
/// Vector of four `i32` values
|
||||
pub type i32x4 = SimdI32<4>;
|
||||
|
||||
/// Vector of eight `i32` values
|
||||
pub type i32x8 = SimdI32<8>;
|
||||
|
||||
/// Vector of 16 `i32` values
|
||||
pub type i32x16 = SimdI32<16>;
|
||||
|
||||
from_transmute_x86! { unsafe i32x4 => __m128i }
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
|
||||
/// A SIMD vector of containing `LANES` lanes of `i64`.
|
||||
/// A SIMD vector of containing `LANES` `i64` values.
|
||||
#[repr(simd)]
|
||||
pub struct SimdI64<const LANES: usize>([i64; LANES]);
|
||||
|
||||
impl_integer_vector! { SimdI64, i64 }
|
||||
|
||||
/// Vector of two `i64` values
|
||||
pub type i64x2 = SimdI64<2>;
|
||||
|
||||
/// Vector of four `i64` values
|
||||
pub type i64x4 = SimdI64<4>;
|
||||
|
||||
/// Vector of eight `i64` values
|
||||
pub type i64x8 = SimdI64<8>;
|
||||
|
||||
from_transmute_x86! { unsafe i64x2 => __m128i }
|
||||
|
|
|
@ -1,14 +1,21 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
|
||||
/// A SIMD vector of containing `LANES` lanes of `i8`.
|
||||
/// A SIMD vector of containing `LANES` `i8` values.
|
||||
#[repr(simd)]
|
||||
pub struct SimdI8<const LANES: usize>([i8; LANES]);
|
||||
|
||||
impl_integer_vector! { SimdI8, i8 }
|
||||
|
||||
/// Vector of eight `i8` values
|
||||
pub type i8x8 = SimdI8<8>;
|
||||
|
||||
/// Vector of 16 `i8` values
|
||||
pub type i8x16 = SimdI8<16>;
|
||||
|
||||
/// Vector of 32 `i8` values
|
||||
pub type i8x32 = SimdI8<32>;
|
||||
|
||||
/// Vector of 64 `i8` values
|
||||
pub type i8x64 = SimdI8<64>;
|
||||
|
||||
from_transmute_x86! { unsafe i8x16 => __m128i }
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
|
||||
/// A SIMD vector of containing `LANES` lanes of `isize`.
|
||||
/// A SIMD vector of containing `LANES` `isize` values.
|
||||
#[repr(simd)]
|
||||
pub struct SimdIsize<const LANES: usize>([isize; LANES]);
|
||||
|
||||
impl_integer_vector! { SimdIsize, isize }
|
||||
|
||||
/// Vector of two `isize` values
|
||||
pub type isizex2 = SimdIsize<2>;
|
||||
|
||||
/// Vector of four `isize` values
|
||||
pub type isizex4 = SimdIsize<4>;
|
||||
|
||||
/// Vector of eight `isize` values
|
||||
pub type isizex8 = SimdIsize<8>;
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
|
||||
/// A SIMD vector of containing `LANES` lanes of `u128`.
|
||||
/// A SIMD vector of containing `LANES` `u128` values.
|
||||
#[repr(simd)]
|
||||
pub struct SimdU128<const LANES: usize>([u128; LANES]);
|
||||
|
||||
impl_integer_vector! { SimdU128, u128 }
|
||||
|
||||
/// Vector of two `u128` values
|
||||
pub type u128x2 = SimdU128<2>;
|
||||
|
||||
/// Vector of four `u128` values
|
||||
pub type u128x4 = SimdU128<4>;
|
||||
|
||||
from_transmute_x86! { unsafe u128x2 => __m256i }
|
||||
|
|
|
@ -1,14 +1,21 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
|
||||
/// A SIMD vector of containing `LANES` lanes of `u16`.
|
||||
/// A SIMD vector of containing `LANES` `u16` values.
|
||||
#[repr(simd)]
|
||||
pub struct SimdU16<const LANES: usize>([u16; LANES]);
|
||||
|
||||
impl_integer_vector! { SimdU16, u16 }
|
||||
|
||||
/// Vector of four `u16` values
|
||||
pub type u16x4 = SimdU16<4>;
|
||||
|
||||
/// Vector of eight `u16` values
|
||||
pub type u16x8 = SimdU16<8>;
|
||||
|
||||
/// Vector of 16 `u16` values
|
||||
pub type u16x16 = SimdU16<16>;
|
||||
|
||||
/// Vector of 32 `u16` values
|
||||
pub type u16x32 = SimdU16<32>;
|
||||
|
||||
from_transmute_x86! { unsafe u16x8 => __m128i }
|
||||
|
|
|
@ -1,14 +1,21 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
|
||||
/// A SIMD vector of containing `LANES` lanes of `u32`.
|
||||
/// A SIMD vector of containing `LANES` `u32` values.
|
||||
#[repr(simd)]
|
||||
pub struct SimdU32<const LANES: usize>([u32; LANES]);
|
||||
|
||||
impl_integer_vector! { SimdU32, u32 }
|
||||
|
||||
/// Vector of two `u32` values
|
||||
pub type u32x2 = SimdU32<2>;
|
||||
|
||||
/// Vector of four `u32` values
|
||||
pub type u32x4 = SimdU32<4>;
|
||||
|
||||
/// Vector of eight `u32` values
|
||||
pub type u32x8 = SimdU32<8>;
|
||||
|
||||
/// Vector of 16 `u32` values
|
||||
pub type u32x16 = SimdU32<16>;
|
||||
|
||||
from_transmute_x86! { unsafe u32x4 => __m128i }
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
|
||||
/// A SIMD vector of containing `LANES` lanes of `u64`.
|
||||
/// A SIMD vector of containing `LANES` `u64` values.
|
||||
#[repr(simd)]
|
||||
pub struct SimdU64<const LANES: usize>([u64; LANES]);
|
||||
|
||||
impl_integer_vector! { SimdU64, u64 }
|
||||
|
||||
/// Vector of two `u64` values
|
||||
pub type u64x2 = SimdU64<2>;
|
||||
|
||||
/// Vector of four `u64` values
|
||||
pub type u64x4 = SimdU64<4>;
|
||||
|
||||
/// Vector of eight `u64` values
|
||||
pub type u64x8 = SimdU64<8>;
|
||||
|
||||
from_transmute_x86! { unsafe u64x2 => __m128i }
|
||||
|
|
|
@ -1,14 +1,21 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
|
||||
/// A SIMD vector of containing `LANES` lanes of `u8`.
|
||||
/// A SIMD vector of containing `LANES` `u8` values.
|
||||
#[repr(simd)]
|
||||
pub struct SimdU8<const LANES: usize>([u8; LANES]);
|
||||
|
||||
impl_integer_vector! { SimdU8, u8 }
|
||||
|
||||
/// Vector of eight `u8` values
|
||||
pub type u8x8 = SimdU8<8>;
|
||||
|
||||
/// Vector of 16 `u8` values
|
||||
pub type u8x16 = SimdU8<16>;
|
||||
|
||||
/// Vector of 32 `u8` values
|
||||
pub type u8x32 = SimdU8<32>;
|
||||
|
||||
/// Vector of 64 `u8` values
|
||||
pub type u8x64 = SimdU8<64>;
|
||||
|
||||
from_transmute_x86! { unsafe u8x16 => __m128i }
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
|
||||
/// A SIMD vector of containing `LANES` lanes of `usize`.
|
||||
/// A SIMD vector of containing `LANES` `usize` values.
|
||||
#[repr(simd)]
|
||||
pub struct SimdUsize<const LANES: usize>([usize; LANES]);
|
||||
|
||||
impl_integer_vector! { SimdUsize, usize }
|
||||
|
||||
/// Vector of two `usize` values
|
||||
pub type usizex2 = SimdUsize<2>;
|
||||
|
||||
/// Vector of four `usize` values
|
||||
pub type usizex4 = SimdUsize<4>;
|
||||
|
||||
/// Vector of eight `usize` values
|
||||
pub type usizex8 = SimdUsize<8>;
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
macro_rules! mask_tests {
|
||||
{ $vector:ident, $lanes:literal } => {
|
||||
/*
|
||||
#[cfg(test)]
|
||||
mod $vector {
|
||||
use core_simd::$vector as Vector;
|
||||
|
@ -222,6 +221,5 @@ macro_rules! mask_tests {
|
|||
assert_eq!(!v, expected);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue