Rollup merge of #149539 - quaternic:gather-scatter-bits, r=Mark-Simulacrum
Additional test for uN::{gather,scatter}_bits
Feature gate: #![feature(uint_gather_scatter_bits)]
Tracking issue: https://github.com/rust-lang/rust/issues/149069
Accepted ACP: https://github.com/rust-lang/libs-team/issues/695#issuecomment-3549284861
Adds an additional runtime test for `uN::gather_bits` and `uN::scatter_bits` in coretests. They are each other's inverses in a sense, so a shared test can test both with relative ease.
I plan to follow up with optimized implementations for these functions.
This commit is contained in:
commit
8fe12253f7
1 changed files with 62 additions and 0 deletions
|
|
@ -387,6 +387,68 @@ macro_rules! uint_module {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(miri))] // Miri is too slow
|
||||
#[test]
|
||||
fn test_lots_of_gather_scatter() {
|
||||
// Generate a handful of bit patterns to use as inputs
|
||||
let xs = {
|
||||
let mut xs = vec![];
|
||||
let mut x: $T = !0;
|
||||
let mut w = $T::BITS;
|
||||
while w > 0 {
|
||||
w >>= 1;
|
||||
xs.push(x);
|
||||
xs.push(!x);
|
||||
x ^= x << w;
|
||||
}
|
||||
xs
|
||||
};
|
||||
if $T::BITS == 8 {
|
||||
assert_eq!(&xs, &[0xff, 0x00, 0x0f, 0xf0, 0x33, 0xcc, 0x55, 0xaa]);
|
||||
}
|
||||
|
||||
// `256 * (BITS / 5)` masks
|
||||
let sparse_masks = (i8::MIN..=i8::MAX)
|
||||
.map(|i| (i as i128 as $T).rotate_right(4))
|
||||
.flat_map(|x| (0..$T::BITS).step_by(5).map(move |r| x.rotate_right(r)));
|
||||
|
||||
for sparse in sparse_masks {
|
||||
// Collect the set bits to sequential low bits
|
||||
let dense = sparse.gather_bits(sparse);
|
||||
let count = sparse.count_ones();
|
||||
assert_eq!(count, dense.count_ones());
|
||||
assert_eq!(count, dense.trailing_ones());
|
||||
|
||||
// Check that each bit is individually mapped correctly
|
||||
let mut t = sparse;
|
||||
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));
|
||||
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));
|
||||
|
||||
for &x in &xs {
|
||||
// Gather bits from `x & sparse` to `dense`
|
||||
let dx = x.gather_bits(sparse);
|
||||
assert_eq!(dx & !dense, 0);
|
||||
|
||||
// Scatter bits from `x & dense` to `sparse`
|
||||
let sx = x.scatter_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test_runtime_and_compiletime! {
|
||||
fn test_div_floor() {
|
||||
assert_eq_const_safe!($T: (8 as $T).div_floor(3), 2);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue