Skip to content

Commit

Permalink
Add count_ones() and count_zeros()
Browse files Browse the repository at this point in the history
Implement on integer types using the simd_ctpop intrinsic.
  • Loading branch information
AndrewScull committed Sep 11, 2024
1 parent e967f5e commit 27e2832
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 0 deletions.
16 changes: 16 additions & 0 deletions crates/core_simd/src/simd/num/int.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,12 @@ pub trait SimdInt: Copy + Sealed {
/// The least significant bit becomes the most significant bit, second least-significant bit becomes second most-significant bit, etc.
fn reverse_bits(self) -> Self;

/// Returns the number of ones in the binary representation of each element.
fn count_ones(self) -> Self::Unsigned;

/// Returns the number of zeros in the binary representation of each element.
fn count_zeros(self) -> Self::Unsigned;

/// Returns the number of leading zeros in the binary representation of each element.
fn leading_zeros(self) -> Self::Unsigned;

Expand Down Expand Up @@ -367,6 +373,16 @@ macro_rules! impl_trait {
unsafe { core::intrinsics::simd::simd_bitreverse(self) }
}

#[inline]
fn count_ones(self) -> Self::Unsigned {
self.cast::<$unsigned>().count_ones()
}

#[inline]
fn count_zeros(self) -> Self::Unsigned {
self.cast::<$unsigned>().count_zeros()
}

#[inline]
fn leading_zeros(self) -> Self::Unsigned {
self.cast::<$unsigned>().leading_zeros()
Expand Down
17 changes: 17 additions & 0 deletions crates/core_simd/src/simd/num/uint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,12 @@ pub trait SimdUint: Copy + Sealed {
/// The least significant bit becomes the most significant bit, second least-significant bit becomes second most-significant bit, etc.
fn reverse_bits(self) -> Self;

/// Returns the number of ones in the binary representation of each element.
fn count_ones(self) -> Self;

/// Returns the number of zeros in the binary representation of each element.
fn count_zeros(self) -> Self;

/// Returns the number of leading zeros in the binary representation of each element.
fn leading_zeros(self) -> Self;

Expand Down Expand Up @@ -215,6 +221,17 @@ macro_rules! impl_trait {
unsafe { core::intrinsics::simd::simd_bitreverse(self) }
}

#[inline]
fn count_ones(self) -> Self {
// Safety: `self` is an integer vector
unsafe { core::intrinsics::simd::simd_ctpop(self) }
}

#[inline]
fn count_zeros(self) -> Self {
(!self).count_ones()
}

#[inline]
fn leading_zeros(self) -> Self {
// Safety: `self` is an integer vector
Expand Down
16 changes: 16 additions & 0 deletions crates/core_simd/tests/ops_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,22 @@ macro_rules! impl_common_integer_tests {
)
}

fn count_ones<const LANES: usize>() {
test_helpers::test_unary_elementwise(
&$vector::<LANES>::count_ones,
&|x| x.count_ones() as _,
&|_| true,
)
}

fn count_zeros<const LANES: usize>() {
test_helpers::test_unary_elementwise(
&$vector::<LANES>::count_zeros,
&|x| x.count_zeros() as _,
&|_| true,
)
}

fn leading_zeros<const LANES: usize>() {
test_helpers::test_unary_elementwise(
&$vector::<LANES>::leading_zeros,
Expand Down

0 comments on commit 27e2832

Please sign in to comment.