use std::{
hash::Hash,
ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not, Shl, Shr, Sub},
usize,
};
pub trait BitRead {
type Iter<'a>: Iterator<Item = usize>
where
Self: 'a;
fn len(&self) -> usize;
#[inline(always)]
fn is_empty(&self) -> bool {
self.len() == 0
}
fn test(&self, idx: usize) -> bool;
fn count_ones(&self) -> usize {
self.iter().count()
}
fn all(&self) -> bool {
let mut pred = 0;
for (i, _b) in self.iter().enumerate() {
if i != pred {
return false;
}
pred = i + 1;
}
pred == self.len()
}
fn any(&self) -> bool {
for _b in self.iter() {
return true;
}
false
}
#[inline(always)]
fn none(&self) -> bool {
!self.any()
}
fn iter(&self) -> Self::Iter<'_>;
}
pub trait BitWrite: BitRead {
fn set(&mut self, idx: usize);
fn reset(&mut self, idx: usize);
fn flip(&mut self, idx: usize);
fn take(&mut self, idx: usize) -> bool {
let value = self.test(idx);
self.reset(idx);
value
}
fn replace(&mut self, idx: usize, value: bool) -> bool {
let old = self.test(idx);
if value {
self.set(idx);
}
old
}
fn test_and_set(&mut self, idx: usize) -> bool;
fn fill(&mut self);
fn clear(&mut self);
}
pub trait BitResize: BitWrite {
fn resize(&mut self, len: usize);
}
pub trait BitStack: BitWrite {
fn push(&mut self, value: bool);
fn pop(&mut self) -> Option<bool>;
}
pub struct BitSetIter<'a, T: BitRead + ?Sized> {
pub bitset: &'a T,
pub current: usize,
}
impl<'a, T: BitRead + ?Sized> Iterator for BitSetIter<'a, T> {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
while self.current < self.bitset.len() {
let idx = self.current;
self.current += 1;
if self.bitset.test(idx) {
return Some(idx);
}
}
None
}
}
pub trait BitWord:
Copy
+ Hash
+ From<u8>
+ BitOr<Output = Self>
+ BitOrAssign
+ BitXor<Output = Self>
+ BitXorAssign
+ BitAnd<Output = Self>
+ BitAndAssign
+ Not<Output = Self>
+ Shr<usize, Output = Self>
+ Shl<usize, Output = Self>
+ Sub<Output = Self>
+ PartialEq
{
const BITS: usize;
const MAX: Self;
fn count_ones(self) -> usize;
fn trailing_zeros(self) -> usize;
}
macro_rules! impl_bitword {
($t:ty) => {
impl BitWord for $t {
const BITS: usize = <$t>::BITS as usize;
const MAX: Self = <$t>::MAX;
#[inline(always)]
fn count_ones(self) -> usize {
self.count_ones() as usize
}
#[inline(always)]
fn trailing_zeros(self) -> usize {
self.trailing_zeros() as usize
}
}
};
}
impl_bitword!(u8);
impl_bitword!(u16);
impl_bitword!(u32);
impl_bitword!(u64);
impl_bitword!(u128);
impl_bitword!(usize);