use crate::types::DenseNodeId;
#[derive(Clone, Debug, Default)]
pub struct BitSet {
words: Vec<u64>,
len: usize,
}
impl BitSet {
#[must_use]
pub fn with_len(len: usize) -> Self {
Self { words: vec![0; len.div_ceil(64)], len }
}
pub fn clear(&mut self) {
for w in &mut self.words {
*w = 0;
}
}
pub fn resize(&mut self, len: usize) {
self.len = len;
self.words.resize(len.div_ceil(64), 0);
}
#[must_use]
pub const fn bit_len(&self) -> usize {
self.len
}
#[must_use]
pub fn words(&self) -> &[u64] {
&self.words
}
pub fn insert(&mut self, id: DenseNodeId) {
let i = id.as_usize();
debug_assert!(i < self.len);
self.words[i / 64] |= 1u64 << (i % 64);
}
pub fn remove(&mut self, id: DenseNodeId) {
let i = id.as_usize();
if i >= self.len {
return;
}
self.words[i / 64] &= !(1u64 << (i % 64));
}
#[must_use]
pub fn contains(&self, id: DenseNodeId) -> bool {
let i = id.as_usize();
if i >= self.len {
return false;
}
(self.words[i / 64] >> (i % 64)) & 1 == 1
}
#[must_use]
pub fn any(&self) -> bool {
self.words.iter().any(|w| *w != 0)
}
#[must_use]
pub fn count_ones(&self) -> usize {
self.words.iter().map(|w| w.count_ones() as usize).sum()
}
#[must_use]
pub fn to_dense_ids(&self) -> Vec<DenseNodeId> {
let mut out = Vec::with_capacity(self.count_ones());
for i in 0..self.len {
let Ok(raw) = u32::try_from(i) else {
break;
};
let id = DenseNodeId::from_raw(raw);
if self.contains(id) {
out.push(id);
}
}
out
}
pub fn union_with(&mut self, other: &Self) {
debug_assert_eq!(self.len, other.len);
for (a, b) in self.words.iter_mut().zip(other.words.iter()) {
*a |= *b;
}
}
pub fn intersect_with(&mut self, other: &Self) {
debug_assert_eq!(self.len, other.len);
for (a, b) in self.words.iter_mut().zip(other.words.iter()) {
*a &= *b;
}
}
pub fn difference_with(&mut self, other: &Self) {
debug_assert_eq!(self.len, other.len);
for (a, b) in self.words.iter_mut().zip(other.words.iter()) {
*a &= !*b;
}
}
#[must_use]
pub fn is_subset_of(&self, other: &Self) -> bool {
debug_assert_eq!(self.len, other.len);
self.words.iter().zip(other.words.iter()).all(|(a, b)| a & !b == 0)
}
#[must_use]
pub fn equal_set(&self, other: &Self) -> bool {
self.len == other.len && self.words == other.words
}
}
impl std::hash::Hash for BitSet {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.len.hash(state);
self.words.hash(state);
}
}
impl PartialEq for BitSet {
fn eq(&self, other: &Self) -> bool {
self.equal_set(other)
}
}
impl Eq for BitSet {}
#[derive(Clone, Debug, Default)]
pub struct GraphWorkspace {
pub visited: BitSet,
pub frontier: Vec<DenseNodeId>,
pub scratch_nodes: Vec<DenseNodeId>,
pub predecessor: Vec<Option<DenseNodeId>>,
}
impl GraphWorkspace {
pub fn prepare(&mut self, n: usize) {
self.visited.resize(n);
self.visited.clear();
self.frontier.clear();
self.scratch_nodes.clear();
self.predecessor.clear();
self.predecessor.resize(n, None);
}
}