Rollup merge of #151669 - quaternic:rename-gather-scatter-bits, r=scottmcm
rename uN::{gather,scatter}_bits to uN::{extract,deposit}_bits
Feature gate: `#![feature(uint_gather_scatter_bits)]`
Tracking issue: https://github.com/rust-lang/rust/issues/149069
Rename the methods as requested in https://github.com/rust-lang/rust/issues/149069#issuecomment-3633691777
- `gather_bits` -> `extract_bits`
- `scatter_bits` -> `deposit_bits`
This commit is contained in:
commit
bf01ad8916
4 changed files with 68 additions and 68 deletions
|
|
@ -1,12 +1,12 @@
|
|||
//! Implementations for `uN::gather_bits` and `uN::scatter_bits`
|
||||
//! Implementations for `uN::extract_bits` and `uN::deposit_bits`
|
||||
//!
|
||||
//! For the purposes of this implementation, the operations can be thought
|
||||
//! of as operating on the input bits as a list, starting from the least
|
||||
//! significant bit. Gathering is like `Vec::retain` that deletes bits
|
||||
//! where the mask has a zero. Scattering is like doing the inverse by
|
||||
//! inserting the zeros that gathering would delete.
|
||||
//! significant bit. Extraction is like `Vec::retain` that deletes bits
|
||||
//! where the mask has a zero. Deposition is like doing the inverse by
|
||||
//! inserting the zeros that extraction would delete.
|
||||
//!
|
||||
//! Key observation: Each bit that is gathered/scattered needs to be
|
||||
//! Key observation: Each extracted or deposited bit needs to be
|
||||
//! shifted by the count of zeros up to the corresponding mask bit.
|
||||
//!
|
||||
//! With that in mind, the general idea is to decompose the operation into
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
//! of the bits by `n = 1 << stage`. The masks for each stage are computed
|
||||
//! via prefix counts of zeros in the mask.
|
||||
//!
|
||||
//! # Gathering
|
||||
//! # Extraction
|
||||
//!
|
||||
//! Consider the input as a sequence of runs of data (bitstrings A,B,C,...),
|
||||
//! split by fixed-width groups of zeros ('.'), initially at width `n = 1`.
|
||||
|
|
@ -36,9 +36,9 @@
|
|||
//! ........abbbcccccddeghh
|
||||
//! ```
|
||||
//!
|
||||
//! # Scattering
|
||||
//! # Deposition
|
||||
//!
|
||||
//! For `scatter_bits`, the stages are reversed. We start with a single run of
|
||||
//! For `deposit_bits`, the stages are reversed. We start with a single run of
|
||||
//! data in the low bits. Each stage then splits each run of data in two by
|
||||
//! shifting part of it left by `n`, which is halved each stage.
|
||||
//! ```text
|
||||
|
|
@ -100,7 +100,7 @@ macro_rules! uint_impl {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(in super::super) const fn gather_impl(mut x: $U, sparse: $U) -> $U {
|
||||
pub(in super::super) const fn extract_impl(mut x: $U, sparse: $U) -> $U {
|
||||
let masks = prepare(sparse);
|
||||
x &= sparse;
|
||||
let mut stage = 0;
|
||||
|
|
@ -131,7 +131,7 @@ macro_rules! uint_impl {
|
|||
x
|
||||
}
|
||||
#[inline(always)]
|
||||
pub(in super::super) const fn scatter_impl(mut x: $U, sparse: $U) -> $U {
|
||||
pub(in super::super) const fn deposit_impl(mut x: $U, sparse: $U) -> $U {
|
||||
let masks = prepare(sparse);
|
||||
let mut stage = STAGES;
|
||||
while stage > 0 {
|
||||
|
|
|
|||
|
|
@ -507,15 +507,15 @@ macro_rules! uint_impl {
|
|||
/// #![feature(uint_gather_scatter_bits)]
|
||||
#[doc = concat!("let n: ", stringify!($SelfT), " = 0b1011_1100;")]
|
||||
///
|
||||
/// assert_eq!(n.gather_bits(0b0010_0100), 0b0000_0011);
|
||||
/// assert_eq!(n.gather_bits(0xF0), 0b0000_1011);
|
||||
/// assert_eq!(n.extract_bits(0b0010_0100), 0b0000_0011);
|
||||
/// assert_eq!(n.extract_bits(0xF0), 0b0000_1011);
|
||||
/// ```
|
||||
#[unstable(feature = "uint_gather_scatter_bits", issue = "149069")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn gather_bits(self, mask: Self) -> Self {
|
||||
crate::num::int_bits::$ActualT::gather_impl(self as $ActualT, mask as $ActualT) as $SelfT
|
||||
pub const fn extract_bits(self, mask: Self) -> Self {
|
||||
crate::num::int_bits::$ActualT::extract_impl(self as $ActualT, mask as $ActualT) as $SelfT
|
||||
}
|
||||
|
||||
/// Returns an integer with the least significant bits of `self`
|
||||
|
|
@ -524,15 +524,15 @@ macro_rules! uint_impl {
|
|||
/// #![feature(uint_gather_scatter_bits)]
|
||||
#[doc = concat!("let n: ", stringify!($SelfT), " = 0b1010_1101;")]
|
||||
///
|
||||
/// assert_eq!(n.scatter_bits(0b0101_0101), 0b0101_0001);
|
||||
/// assert_eq!(n.scatter_bits(0xF0), 0b1101_0000);
|
||||
/// assert_eq!(n.deposit_bits(0b0101_0101), 0b0101_0001);
|
||||
/// assert_eq!(n.deposit_bits(0xF0), 0b1101_0000);
|
||||
/// ```
|
||||
#[unstable(feature = "uint_gather_scatter_bits", issue = "149069")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn scatter_bits(self, mask: Self) -> Self {
|
||||
crate::num::int_bits::$ActualT::scatter_impl(self as $ActualT, mask as $ActualT) as $SelfT
|
||||
pub const fn deposit_bits(self, mask: Self) -> Self {
|
||||
crate::num::int_bits::$ActualT::deposit_impl(self as $ActualT, mask as $ActualT) as $SelfT
|
||||
}
|
||||
|
||||
/// Reverses the order of bits in the integer. The least significant bit becomes the most significant bit,
|
||||
|
|
|
|||
|
|
@ -50,8 +50,8 @@ macro_rules! bench_mask_kind {
|
|||
($mask_kind:ident, $mask:expr) => {
|
||||
mod $mask_kind {
|
||||
use super::{Data, ITERATIONS, U};
|
||||
bench_template!(U::gather_bits, gather_bits, $mask);
|
||||
bench_template!(U::scatter_bits, scatter_bits, $mask);
|
||||
bench_template!(U::extract_bits, extract_bits, $mask);
|
||||
bench_template!(U::deposit_bits, deposit_bits, $mask);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,50 +127,50 @@ macro_rules! uint_module {
|
|||
assert_eq_const_safe!($T: _1.swap_bytes(), _1);
|
||||
}
|
||||
|
||||
fn test_gather_bits() {
|
||||
assert_eq_const_safe!($T: $T::gather_bits(0b1010_0101, 0b0000_0011), 0b_0001);
|
||||
assert_eq_const_safe!($T: $T::gather_bits(0b1010_0101, 0b0000_0110), 0b_0010);
|
||||
assert_eq_const_safe!($T: $T::gather_bits(0b1010_0101, 0b0000_1100), 0b_0001);
|
||||
assert_eq_const_safe!($T: $T::gather_bits(0b1010_0101, 0b0001_1000), 0b_0000);
|
||||
assert_eq_const_safe!($T: $T::gather_bits(0b1010_0101, 0b0011_0000), 0b_0010);
|
||||
assert_eq_const_safe!($T: $T::gather_bits(0b1010_0101, 0b0110_0000), 0b_0001);
|
||||
assert_eq_const_safe!($T: $T::gather_bits(0b1010_0101, 0b1100_0000), 0b_0010);
|
||||
fn test_extract_bits() {
|
||||
assert_eq_const_safe!($T: $T::extract_bits(0b1010_0101, 0b0000_0011), 0b_0001);
|
||||
assert_eq_const_safe!($T: $T::extract_bits(0b1010_0101, 0b0000_0110), 0b_0010);
|
||||
assert_eq_const_safe!($T: $T::extract_bits(0b1010_0101, 0b0000_1100), 0b_0001);
|
||||
assert_eq_const_safe!($T: $T::extract_bits(0b1010_0101, 0b0001_1000), 0b_0000);
|
||||
assert_eq_const_safe!($T: $T::extract_bits(0b1010_0101, 0b0011_0000), 0b_0010);
|
||||
assert_eq_const_safe!($T: $T::extract_bits(0b1010_0101, 0b0110_0000), 0b_0001);
|
||||
assert_eq_const_safe!($T: $T::extract_bits(0b1010_0101, 0b1100_0000), 0b_0010);
|
||||
|
||||
assert_eq_const_safe!($T: A.gather_bits(_0), 0);
|
||||
assert_eq_const_safe!($T: B.gather_bits(_0), 0);
|
||||
assert_eq_const_safe!($T: C.gather_bits(_0), 0);
|
||||
assert_eq_const_safe!($T: _0.gather_bits(A), 0);
|
||||
assert_eq_const_safe!($T: _0.gather_bits(B), 0);
|
||||
assert_eq_const_safe!($T: _0.gather_bits(C), 0);
|
||||
assert_eq_const_safe!($T: A.extract_bits(_0), 0);
|
||||
assert_eq_const_safe!($T: B.extract_bits(_0), 0);
|
||||
assert_eq_const_safe!($T: C.extract_bits(_0), 0);
|
||||
assert_eq_const_safe!($T: _0.extract_bits(A), 0);
|
||||
assert_eq_const_safe!($T: _0.extract_bits(B), 0);
|
||||
assert_eq_const_safe!($T: _0.extract_bits(C), 0);
|
||||
|
||||
assert_eq_const_safe!($T: A.gather_bits(_1), A);
|
||||
assert_eq_const_safe!($T: B.gather_bits(_1), B);
|
||||
assert_eq_const_safe!($T: C.gather_bits(_1), C);
|
||||
assert_eq_const_safe!($T: _1.gather_bits(0b0010_0001), 0b0000_0011);
|
||||
assert_eq_const_safe!($T: _1.gather_bits(0b0010_1100), 0b0000_0111);
|
||||
assert_eq_const_safe!($T: _1.gather_bits(0b0111_1001), 0b0001_1111);
|
||||
assert_eq_const_safe!($T: A.extract_bits(_1), A);
|
||||
assert_eq_const_safe!($T: B.extract_bits(_1), B);
|
||||
assert_eq_const_safe!($T: C.extract_bits(_1), C);
|
||||
assert_eq_const_safe!($T: _1.extract_bits(0b0010_0001), 0b0000_0011);
|
||||
assert_eq_const_safe!($T: _1.extract_bits(0b0010_1100), 0b0000_0111);
|
||||
assert_eq_const_safe!($T: _1.extract_bits(0b0111_1001), 0b0001_1111);
|
||||
}
|
||||
|
||||
fn test_scatter_bits() {
|
||||
assert_eq_const_safe!($T: $T::scatter_bits(0b1111, 0b1001_0110), 0b1001_0110);
|
||||
assert_eq_const_safe!($T: $T::scatter_bits(0b0001, 0b1001_0110), 0b0000_0010);
|
||||
assert_eq_const_safe!($T: $T::scatter_bits(0b0010, 0b1001_0110), 0b0000_0100);
|
||||
assert_eq_const_safe!($T: $T::scatter_bits(0b0100, 0b1001_0110), 0b0001_0000);
|
||||
assert_eq_const_safe!($T: $T::scatter_bits(0b1000, 0b1001_0110), 0b1000_0000);
|
||||
fn test_deposit_bits() {
|
||||
assert_eq_const_safe!($T: $T::deposit_bits(0b1111, 0b1001_0110), 0b1001_0110);
|
||||
assert_eq_const_safe!($T: $T::deposit_bits(0b0001, 0b1001_0110), 0b0000_0010);
|
||||
assert_eq_const_safe!($T: $T::deposit_bits(0b0010, 0b1001_0110), 0b0000_0100);
|
||||
assert_eq_const_safe!($T: $T::deposit_bits(0b0100, 0b1001_0110), 0b0001_0000);
|
||||
assert_eq_const_safe!($T: $T::deposit_bits(0b1000, 0b1001_0110), 0b1000_0000);
|
||||
|
||||
assert_eq_const_safe!($T: A.scatter_bits(_0), 0);
|
||||
assert_eq_const_safe!($T: B.scatter_bits(_0), 0);
|
||||
assert_eq_const_safe!($T: C.scatter_bits(_0), 0);
|
||||
assert_eq_const_safe!($T: _0.scatter_bits(A), 0);
|
||||
assert_eq_const_safe!($T: _0.scatter_bits(B), 0);
|
||||
assert_eq_const_safe!($T: _0.scatter_bits(C), 0);
|
||||
assert_eq_const_safe!($T: A.deposit_bits(_0), 0);
|
||||
assert_eq_const_safe!($T: B.deposit_bits(_0), 0);
|
||||
assert_eq_const_safe!($T: C.deposit_bits(_0), 0);
|
||||
assert_eq_const_safe!($T: _0.deposit_bits(A), 0);
|
||||
assert_eq_const_safe!($T: _0.deposit_bits(B), 0);
|
||||
assert_eq_const_safe!($T: _0.deposit_bits(C), 0);
|
||||
|
||||
assert_eq_const_safe!($T: A.scatter_bits(_1), A);
|
||||
assert_eq_const_safe!($T: B.scatter_bits(_1), B);
|
||||
assert_eq_const_safe!($T: C.scatter_bits(_1), C);
|
||||
assert_eq_const_safe!($T: _1.scatter_bits(A), A);
|
||||
assert_eq_const_safe!($T: _1.scatter_bits(B), B);
|
||||
assert_eq_const_safe!($T: _1.scatter_bits(C), C);
|
||||
assert_eq_const_safe!($T: A.deposit_bits(_1), A);
|
||||
assert_eq_const_safe!($T: B.deposit_bits(_1), B);
|
||||
assert_eq_const_safe!($T: C.deposit_bits(_1), C);
|
||||
assert_eq_const_safe!($T: _1.deposit_bits(A), A);
|
||||
assert_eq_const_safe!($T: _1.deposit_bits(B), B);
|
||||
assert_eq_const_safe!($T: _1.deposit_bits(C), C);
|
||||
}
|
||||
|
||||
fn test_reverse_bits() {
|
||||
|
|
@ -389,7 +389,7 @@ macro_rules! uint_module {
|
|||
|
||||
#[cfg(not(miri))] // Miri is too slow
|
||||
#[test]
|
||||
fn test_lots_of_gather_scatter() {
|
||||
fn test_lots_of_extract_deposit() {
|
||||
// Generate a handful of bit patterns to use as inputs
|
||||
let xs = {
|
||||
let mut xs = vec![];
|
||||
|
|
@ -414,7 +414,7 @@ macro_rules! uint_module {
|
|||
|
||||
for sparse in sparse_masks {
|
||||
// Collect the set bits to sequential low bits
|
||||
let dense = sparse.gather_bits(sparse);
|
||||
let dense = sparse.extract_bits(sparse);
|
||||
let count = sparse.count_ones();
|
||||
assert_eq!(count, dense.count_ones());
|
||||
assert_eq!(count, dense.trailing_ones());
|
||||
|
|
@ -424,27 +424,27 @@ macro_rules! uint_module {
|
|||
let mut bit = 1 as $T;
|
||||
for _ in 0..count {
|
||||
let lowest_one = t.isolate_lowest_one();
|
||||
assert_eq!(lowest_one, bit.scatter_bits(sparse));
|
||||
assert_eq!(bit, lowest_one.gather_bits(sparse));
|
||||
assert_eq!(lowest_one, bit.deposit_bits(sparse));
|
||||
assert_eq!(bit, lowest_one.extract_bits(sparse));
|
||||
t ^= lowest_one;
|
||||
bit <<= 1;
|
||||
}
|
||||
// Other bits are ignored
|
||||
assert_eq!(0, bit.wrapping_neg().scatter_bits(sparse));
|
||||
assert_eq!(0, (!sparse).gather_bits(sparse));
|
||||
assert_eq!(0, bit.wrapping_neg().deposit_bits(sparse));
|
||||
assert_eq!(0, (!sparse).extract_bits(sparse));
|
||||
|
||||
for &x in &xs {
|
||||
// Gather bits from `x & sparse` to `dense`
|
||||
let dx = x.gather_bits(sparse);
|
||||
let dx = x.extract_bits(sparse);
|
||||
assert_eq!(dx & !dense, 0);
|
||||
|
||||
// Scatter bits from `x & dense` to `sparse`
|
||||
let sx = x.scatter_bits(sparse);
|
||||
let sx = x.deposit_bits(sparse);
|
||||
assert_eq!(sx & !sparse, 0);
|
||||
|
||||
// The other recovers the input (within the mask)
|
||||
assert_eq!(dx.scatter_bits(sparse), x & sparse);
|
||||
assert_eq!(sx.gather_bits(sparse), x & dense);
|
||||
assert_eq!(dx.deposit_bits(sparse), x & sparse);
|
||||
assert_eq!(sx.extract_bits(sparse), x & dense);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue