const REMAP_BITS: u32 = if cfg!(any(target_arch = "x86_64", target_arch = "aarch64")) {
4
} else {
3
};
#[derive(Clone, Copy, Debug)]
pub(super) struct Geometry {
order: u32,
}
impl Geometry {
pub(super) const fn new(order: u32) -> Self {
Self { order }
}
pub(super) const fn n(self) -> usize {
1 << self.order
}
pub(super) const fn ring_len(self) -> usize {
2 << self.order
}
const fn index_bits(self) -> u32 {
self.order + 1
}
pub(super) const fn bot(self) -> usize {
(1 << self.index_bits()) - 1
}
const fn safe_bit(self) -> usize {
1 << self.index_bits()
}
const fn cycle_shift(self) -> u32 {
self.index_bits() + 1
}
pub(super) const fn pack(self, cycle: usize, safe: bool, index: usize) -> usize {
(cycle << self.cycle_shift()) | ((safe as usize) << self.index_bits()) | index
}
pub(super) const fn cycle(self, entry: usize) -> usize {
entry >> self.cycle_shift()
}
pub(super) const fn is_safe(self, entry: usize) -> bool {
entry & self.safe_bit() != 0
}
pub(super) const fn index(self, entry: usize) -> usize {
entry & self.bot()
}
pub(super) const fn cycle_of(self, pos: usize) -> usize {
pos >> self.index_bits()
}
pub(super) const fn slot(self, pos: usize) -> usize {
remap(pos & (self.ring_len() - 1), self.index_bits())
}
pub(super) const fn initial_index(self, i: usize) -> usize {
remap(i, self.order)
}
}
const fn remap(i: usize, bits: u32) -> usize {
if bits <= REMAP_BITS {
return i;
}
let mask = (1 << bits) - 1;
((i >> (bits - REMAP_BITS)) | (i << REMAP_BITS)) & mask
}
#[cfg(all(test, not(loom)))]
mod tests {
use super::*;
#[test]
fn pack_round_trips() {
for order in 0..20 {
let g = Geometry::new(order);
for &(cycle, safe, index) in &[
(0, true, 0),
(1, false, g.n() - 1),
(12_345, true, g.bot()),
(usize::MAX >> g.cycle_shift(), false, 0),
] {
let e = g.pack(cycle, safe, index);
assert_eq!((g.cycle(e), g.is_safe(e), g.index(e)), (cycle, safe, index));
}
}
}
#[test]
fn bot_is_never_a_data_index() {
for order in 0..20 {
let g = Geometry::new(order);
assert!(g.bot() >= g.n());
}
}
#[test]
fn remap_is_a_bijection() {
for bits in 0..=16 {
let len = 1usize << bits;
let mut seen = vec![false; len];
for i in 0..len {
let r = remap(i, bits);
assert!(r < len && !seen[r], "bits={bits} i={i}");
seen[r] = true;
}
}
}
#[test]
fn consecutive_positions_land_on_different_lines() {
let g = Geometry::new(10);
let line = |slot: usize| slot >> REMAP_BITS;
for p in 0..64 {
assert_ne!(line(g.slot(p)), line(g.slot(p + 1)));
}
}
#[test]
fn cycles_fit_below_the_closed_bit() {
for order in 0..32 {
let g = Geometry::new(order);
let pos = (1usize << 63) - 1;
let e = g.pack(g.cycle_of(pos), true, g.bot());
assert_eq!(g.cycle(e), g.cycle_of(pos));
}
}
}