macro_rules! impl_big_endian_for {
($mod:ident => $t:ty) => {
#[cfg_attr(not(feature = "bigendian"), allow(dead_code))] pub mod $mod {
use core::cmp::min;
pub const ELEMENT_BITS: usize = <$t>::BITS as usize;
#[inline]
pub const fn mask(ndx: usize) -> $t {
let bit_ndx = ELEMENT_BITS - 1 - (ndx % ELEMENT_BITS);
1 << bit_ndx
}
const fn mask_suffix(ndx: usize) -> $t {
assert!(ndx <= ELEMENT_BITS);
if ndx >= ELEMENT_BITS {
0
} else {
!0 >> ndx
}
}
pub const fn make_element_inc(value: $t, prefix: usize) -> ($t, bool) {
assert!(prefix <= ELEMENT_BITS);
if prefix == ELEMENT_BITS {
return (value, true);
}
if prefix == 0 {
return value.overflowing_add(1);
}
let result = value.wrapping_add(1);
let fixed_bits_mask = !mask_suffix(prefix);
if (result ^ value) & fixed_bits_mask != 0 {
return (value & fixed_bits_mask, true);
}
(result, false)
}
pub fn element_inc(value: &mut $t, prefix: usize) -> bool {
let overflow;
(*value, overflow) = make_element_inc(*value, prefix);
overflow
}
pub fn slice_inc(slice: &mut [$t], prefix: usize) -> bool {
let slice_ndx = prefix / ELEMENT_BITS;
let element_ndx = prefix % ELEMENT_BITS;
if slice_ndx >= slice.len() {
assert!(element_ndx == 0);
return true;
}
for i in (slice_ndx + 1..slice.len()).rev() {
let overflow;
(slice[i], overflow) = slice[i].overflowing_add(1);
if !overflow {
return false;
}
}
element_inc(&mut slice[slice_ndx], element_ndx)
}
pub const fn element_get(value: $t, ndx: usize) -> bool {
assert!(ndx < ELEMENT_BITS);
0 != value & mask(ndx)
}
pub const fn slice_get(slice: &[$t], ndx: usize) -> bool {
let slice_ndx = ndx / ELEMENT_BITS;
let element_ndx = ndx % ELEMENT_BITS;
element_get(slice[slice_ndx], element_ndx)
}
pub const fn make_element_set(value: $t, ndx: usize, bit: bool) -> $t {
assert!(ndx < ELEMENT_BITS);
let mask = mask(ndx);
if bit {
value | mask
} else {
value & !mask
}
}
pub fn element_set(value: &mut $t, ndx: usize, bit: bool) {
*value = make_element_set(*value, ndx, bit);
}
pub fn slice_set(slice: &mut [$t], ndx: usize, bit: bool) {
let slice_ndx = ndx / ELEMENT_BITS;
element_set(&mut slice[slice_ndx], ndx % ELEMENT_BITS, bit);
}
pub const fn make_element_flip(value: $t, ndx: usize) -> $t {
assert!(ndx < ELEMENT_BITS);
value ^ mask(ndx)
}
pub fn element_flip(value: &mut $t, ndx: usize) {
*value = make_element_flip(*value, ndx);
}
pub fn slice_flip(slice: &mut [$t], ndx: usize) {
let slice_ndx = ndx / ELEMENT_BITS;
element_flip(&mut slice[slice_ndx], ndx % ELEMENT_BITS);
}
pub fn element_shared_prefix_len(value: $t, other: $t, max_len: usize) -> usize {
assert!(max_len <= ELEMENT_BITS);
min((value ^ other).leading_zeros() as usize, max_len)
}
pub fn slice_shared_prefix_len(slice: &[$t], other: &[$t], max_len: usize) -> usize {
if 0 == max_len {
return 0;
}
let slice_ndx = (max_len - 1) / ELEMENT_BITS;
for i in 0..slice_ndx {
let diff = slice[i] ^ other[i];
if 0 != diff {
return i * ELEMENT_BITS + diff.leading_zeros() as usize;
}
}
let diff = slice[slice_ndx] ^ other[slice_ndx];
if 0 != diff {
min(
max_len,
slice_ndx * ELEMENT_BITS + diff.leading_zeros() as usize,
)
} else {
max_len
}
}
pub const fn make_element_set_false_from(value: $t, ndx: usize) -> $t {
if ndx >= ELEMENT_BITS {
return value;
}
value & !mask_suffix(ndx)
}
pub fn element_set_false_from(value: &mut $t, ndx: usize) {
*value = make_element_set_false_from(*value, ndx);
}
pub fn slice_set_false_from(slice: &mut [$t], ndx: usize) {
let slice_ndx = ndx / ELEMENT_BITS;
if slice_ndx >= slice.len() {
return;
}
element_set_false_from(&mut slice[slice_ndx], ndx % ELEMENT_BITS);
for i in slice_ndx + 1..slice.len() {
slice[i] = 0;
}
}
pub const fn element_is_false_from(value: $t, ndx: usize) -> bool {
if ndx >= ELEMENT_BITS {
return true;
}
0 == value & mask_suffix(ndx)
}
pub fn slice_is_false_from(slice: &[$t], ndx: usize) -> bool {
let slice_ndx = ndx / ELEMENT_BITS;
if slice_ndx >= slice.len() {
return true;
}
if !element_is_false_from(slice[slice_ndx], ndx % ELEMENT_BITS) {
return false;
}
slice[slice_ndx + 1..].iter().all(|&value| value == 0)
}
pub const fn make_element_set_true_from(value: $t, ndx: usize) -> $t {
if ndx >= ELEMENT_BITS {
return value;
}
value | mask_suffix(ndx)
}
pub fn element_set_true_from(value: &mut $t, ndx: usize) {
*value = make_element_set_true_from(*value, ndx);
}
pub fn slice_set_true_from(slice: &mut [$t], ndx: usize) {
let slice_ndx = ndx / ELEMENT_BITS;
if slice_ndx >= slice.len() {
return;
}
element_set_true_from(&mut slice[slice_ndx], ndx % ELEMENT_BITS);
for i in slice_ndx + 1..slice.len() {
slice[i] = !0;
}
}
pub const fn element_is_true_from(value: $t, ndx: usize) -> bool {
if ndx >= ELEMENT_BITS {
return true;
}
!0 == value | !mask_suffix(ndx)
}
pub fn slice_is_true_from(slice: &[$t], ndx: usize) -> bool {
let slice_ndx = ndx / ELEMENT_BITS;
if slice_ndx >= slice.len() {
return true;
}
if !element_is_true_from(slice[slice_ndx], ndx % ELEMENT_BITS) {
return false;
}
slice[slice_ndx + 1..].iter().all(|&value| value == !0)
}
pub const fn element_contains(value: $t, prefix: usize, other: $t) -> bool {
let mask = !mask_suffix(prefix);
0 == mask & (value ^ other)
}
pub fn slice_contains(slice: &[$t], prefix: usize, other: &[$t]) -> bool {
let slice_ndx = prefix / ELEMENT_BITS;
for i in 0..slice_ndx {
if slice[i] != other[i] {
return false;
}
}
let element_ndx = prefix % ELEMENT_BITS;
if 0 == element_ndx {
return true;
}
element_contains(slice[slice_ndx], element_ndx, other[slice_ndx])
}
}
};
}
impl_big_endian_for! {u8 => u8}
impl_big_endian_for! {u16 => u16}
impl_big_endian_for! {u32 => u32}
impl_big_endian_for! {u64 => u64}
impl_big_endian_for! {u128 => u128}