pH/src/util/bitvec.rs
Bruce Leidl 7f3b3aa409 Large refactor.
Many many changes. The major themes of the refactor were to move the
x86 specific code into a separate 'arch' package and make the main
initialization and run loop much simpler to understand. The second big
change was to improve how errors are handled by making them more 'local'
so that packages define their own errors most of the time.
2019-10-02 16:41:02 -04:00

78 lines
2.2 KiB
Rust

/// 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]
}
}