use std::cell::Cell;
#[cfg(not(feature = "compact"))]
#[derive(Clone, Debug, Default)]
pub(crate) struct Metadata {
parent: Cell<usize>,
link: Cell<usize>,
rank: Cell<usize>,
}
#[cfg(not(feature = "compact"))]
impl Metadata {
pub(crate) fn new(index: usize) -> Self {
Self {
parent: Cell::new(index),
link: Cell::new(index),
rank: Cell::new(0),
}
}
pub(crate) fn parent(&self) -> usize {
self.parent.get()
}
pub(crate) fn set_parent(&self, value: usize) {
self.parent.set(value);
}
pub(crate) fn link(&self) -> usize {
self.link.get()
}
pub(crate) fn set_link(&self, value: usize) {
self.link.set(value);
}
pub(crate) fn rank(&self) -> usize {
self.rank.get()
}
pub(crate) fn set_rank(&self, value: usize) {
self.rank.set(value);
}
}
#[cfg(feature = "compact")]
const USIZE_BITS: usize = 8 * ::std::mem::size_of::<usize>();
#[cfg(all(feature = "compact", target_pointer_width = "8"))]
const RANK_BITS: usize = 2;
#[cfg(all(feature = "compact", target_pointer_width = "16"))]
const RANK_BITS: usize = 2;
#[cfg(all(feature = "compact", target_pointer_width = "32"))]
const RANK_BITS: usize = 3;
#[cfg(all(feature = "compact", target_pointer_width = "64"))]
const RANK_BITS: usize = 3;
#[cfg(all(feature = "compact", target_pointer_width = "128"))]
const RANK_BITS: usize = 4;
#[cfg(all(feature = "compact", target_pointer_width = "256"))]
const RANK_BITS: usize = 4;
#[cfg(feature = "compact")]
const MASK: usize = (1 << RANK_BITS) - 1;
#[cfg(feature = "compact")]
const MAX: usize = 1 << (USIZE_BITS - RANK_BITS);
#[cfg(feature = "compact")]
#[derive(Clone, Debug, Default)]
pub(crate) struct Metadata {
parent: Cell<usize>,
link: Cell<usize>,
}
#[cfg(feature = "compact")]
impl Metadata {
pub(crate) fn new(index: usize) -> Self {
if index > MAX {
panic!("A PartitionVec can only hold {} values.", MAX)
}
Self {
parent: Cell::new(index << RANK_BITS),
link: Cell::new(index << RANK_BITS),
}
}
pub(crate) fn parent(&self) -> usize {
self.parent.get() >> RANK_BITS
}
pub(crate) fn set_parent(&self, value: usize) {
let old = self.parent.get();
self.parent.set((old & MASK) | (value << RANK_BITS));
}
pub(crate) fn link(&self) -> usize {
self.link.get() >> RANK_BITS
}
pub(crate) fn set_link(&self, value: usize) {
let old = self.link.get();
self.link.set((old & MASK) | (value << RANK_BITS));
}
pub(crate) fn rank(&self) -> usize {
let left = self.link.get() & RANK_BITS;
let right = self.parent.get() & RANK_BITS;
(left << RANK_BITS) | right
}
pub(crate) fn set_rank(&self, value: usize) {
let old = self.parent.get();
self.parent.set((old & !MASK) | (value >> RANK_BITS));
let old = self.link.get();
self.link.set((old & !MASK) | (value & RANK_BITS));
}
}