pH/src/util/bitvec.rs

78 lines
2.2 KiB
Rust
Raw Normal View History

/// An efficiently stored array (or set) of bits.
///
/// Bits can be set, cleared, or tested by index into the
/// array of bits. Since the methods are named to follow
/// the set collection convention you can also think of
/// it as a set which stores `usize` index values.
///
pub struct BitSet {
blocks: Vec<u64>,
}
impl BitSet {
/// Create a new empty `BitSet`
pub fn new() -> BitSet {
BitSet { blocks: Vec::new() }
}
/// Removes all entries from the set.
pub fn clear(&mut self) {
self.blocks.clear();
}
/// Inserts a bit into the set. Sets the entry at `idx` to `true`.
pub fn insert(&mut self, idx: usize) {
let (bit,block) = Self::bit_and_block(idx);
*self.block_mut(block) |= bit;
}
/// Removes a bit from the set. Sets the entry at `idx` to `false`.
pub fn remove(&mut self, idx: usize) {
let (bit,block) = Self::bit_and_block(idx);
if self.blocks.len() > block {
*self.block_mut(block) &= !bit;
}
}
/// Returns the value of the bit at `idx`
pub fn get(&self, idx: usize) -> bool {
let (bit,block) = Self::bit_and_block(idx);
if self.block(block) & bit != 0 {
return true;
}
false
}
/// Convert a bit index `idx` into an index into
/// the block array and the corresponding bit value
/// inside of that block.
fn bit_and_block(idx: usize) -> (u64, usize) {
const SHIFT64: usize = 6;
const MASK64: usize = (1 << SHIFT64) - 1;
let bit = (1usize << (idx & MASK64)) as u64;
let block = idx >> SHIFT64;
(bit, block)
}
/// Returns value stored at index `blk` or returns 0 if `blk`
/// is index larger than block array.
fn block(&self, blk: usize) -> u64 {
if self.blocks.len() > blk {
self.blocks[blk]
} else {
0
}
}
/// Returns mutable reference to value stored at index `blk`
/// and will resize block vector if index is larger than block
/// array.
fn block_mut(&mut self, blk: usize) -> &mut u64 {
if self.blocks.len() <= blk {
self.blocks.resize_with(blk + 1, Default::default);
}
&mut self.blocks[blk]
}
}