Return unsigned integers from some signed integer functions

This commit is contained in:
Caleb Zulawski 2023-09-10 18:20:47 -04:00
parent c948b703ff
commit 0a1e745320
2 changed files with 24 additions and 21 deletions

View File

@ -1,6 +1,7 @@
use super::sealed::Sealed; use super::sealed::Sealed;
use crate::simd::{ use crate::simd::{
intrinsics, LaneCount, Mask, Simd, SimdCast, SimdElement, SimdPartialOrd, SupportedLaneCount, intrinsics, LaneCount, Mask, Simd, SimdCast, SimdElement, SimdPartialOrd, SimdUint,
SupportedLaneCount,
}; };
/// Operations on SIMD vectors of signed integers. /// Operations on SIMD vectors of signed integers.
@ -11,6 +12,9 @@ pub trait SimdInt: Copy + Sealed {
/// Scalar type contained by this SIMD vector type. /// Scalar type contained by this SIMD vector type.
type Scalar; type Scalar;
/// A SIMD vector of unsigned integers with the same element size.
type Unsigned;
/// A SIMD vector with a different element type. /// A SIMD vector with a different element type.
type Cast<T: SimdElement>; type Cast<T: SimdElement>;
@ -200,20 +204,20 @@ pub trait SimdInt: Copy + Sealed {
fn reverse_bits(self) -> Self; fn reverse_bits(self) -> Self;
/// Returns the number of leading zeros in the binary representation of each element. /// Returns the number of leading zeros in the binary representation of each element.
fn leading_zeros(self) -> Self; fn leading_zeros(self) -> Self::Unsigned;
/// Returns the number of trailing zeros in the binary representation of each element. /// Returns the number of trailing zeros in the binary representation of each element.
fn trailing_zeros(self) -> Self; fn trailing_zeros(self) -> Self::Unsigned;
/// Returns the number of leading ones in the binary representation of each element. /// Returns the number of leading ones in the binary representation of each element.
fn leading_ones(self) -> Self; fn leading_ones(self) -> Self::Unsigned;
/// Returns the number of trailing ones in the binary representation of each element. /// Returns the number of trailing ones in the binary representation of each element.
fn trailing_ones(self) -> Self; fn trailing_ones(self) -> Self::Unsigned;
} }
macro_rules! impl_trait { macro_rules! impl_trait {
{ $($ty:ty),* } => { { $($ty:ident ($unsigned:ident)),* } => {
$( $(
impl<const LANES: usize> Sealed for Simd<$ty, LANES> impl<const LANES: usize> Sealed for Simd<$ty, LANES>
where where
@ -227,6 +231,7 @@ impl<const LANES: usize> SimdInt for Simd<$ty, LANES>
{ {
type Mask = Mask<<$ty as SimdElement>::Mask, LANES>; type Mask = Mask<<$ty as SimdElement>::Mask, LANES>;
type Scalar = $ty; type Scalar = $ty;
type Unsigned = Simd<$unsigned, LANES>;
type Cast<T: SimdElement> = Simd<T, LANES>; type Cast<T: SimdElement> = Simd<T, LANES>;
#[inline] #[inline]
@ -340,29 +345,27 @@ fn reverse_bits(self) -> Self {
} }
#[inline] #[inline]
fn leading_zeros(self) -> Self { fn leading_zeros(self) -> Self::Unsigned {
// Safety: `self` is an integer vector self.cast::<$unsigned>().leading_zeros()
unsafe { intrinsics::simd_ctlz(self) }
} }
#[inline] #[inline]
fn trailing_zeros(self) -> Self { fn trailing_zeros(self) -> Self::Unsigned {
// Safety: `self` is an integer vector self.cast::<$unsigned>().trailing_zeros()
unsafe { intrinsics::simd_cttz(self) }
} }
#[inline] #[inline]
fn leading_ones(self) -> Self { fn leading_ones(self) -> Self::Unsigned {
(!self).leading_zeros() self.cast::<$unsigned>().leading_ones()
} }
#[inline] #[inline]
fn trailing_ones(self) -> Self { fn trailing_ones(self) -> Self::Unsigned {
(!self).trailing_zeros() self.cast::<$unsigned>().trailing_ones()
} }
} }
)* )*
} }
} }
impl_trait! { i8, i16, i32, i64, isize } impl_trait! { i8 (u8), i16 (u16), i32 (u32), i64 (u64), isize (usize) }

View File

@ -213,7 +213,7 @@ fn reverse_bits<const LANES: usize>() {
fn leading_zeros<const LANES: usize>() { fn leading_zeros<const LANES: usize>() {
test_helpers::test_unary_elementwise( test_helpers::test_unary_elementwise(
&$vector::<LANES>::leading_zeros, &$vector::<LANES>::leading_zeros,
&|x| x.leading_zeros() as $scalar, &|x| x.leading_zeros() as _,
&|_| true, &|_| true,
) )
} }
@ -221,7 +221,7 @@ fn leading_zeros<const LANES: usize>() {
fn trailing_zeros<const LANES: usize>() { fn trailing_zeros<const LANES: usize>() {
test_helpers::test_unary_elementwise( test_helpers::test_unary_elementwise(
&$vector::<LANES>::trailing_zeros, &$vector::<LANES>::trailing_zeros,
&|x| x.trailing_zeros() as $scalar, &|x| x.trailing_zeros() as _,
&|_| true, &|_| true,
) )
} }
@ -229,7 +229,7 @@ fn trailing_zeros<const LANES: usize>() {
fn leading_ones<const LANES: usize>() { fn leading_ones<const LANES: usize>() {
test_helpers::test_unary_elementwise( test_helpers::test_unary_elementwise(
&$vector::<LANES>::leading_ones, &$vector::<LANES>::leading_ones,
&|x| x.leading_ones() as $scalar, &|x| x.leading_ones() as _,
&|_| true, &|_| true,
) )
} }
@ -237,7 +237,7 @@ fn leading_ones<const LANES: usize>() {
fn trailing_ones<const LANES: usize>() { fn trailing_ones<const LANES: usize>() {
test_helpers::test_unary_elementwise( test_helpers::test_unary_elementwise(
&$vector::<LANES>::trailing_ones, &$vector::<LANES>::trailing_ones,
&|x| x.trailing_ones() as $scalar, &|x| x.trailing_ones() as _,
&|_| true, &|_| true,
) )
} }