bit vector implementation

This commit is contained in:
Bruce Leidl 2019-09-11 11:23:54 -04:00
parent 245b48cf1e
commit 3679bfd03a

78
rust/src/system/bitvec.rs Normal file
View File

@ -0,0 +1,78 @@
use std::ops::Index;
pub struct BitVec {
blocks: Vec<u64>,
}
impl BitVec {
pub fn new() -> BitVec {
BitVec { blocks: Vec::new() }
}
pub fn set_bit(&mut self, idx: usize) {
*self.mut_block(idx) |= Self::shifted_bit(idx)
}
pub fn clear_bit(&mut self, idx: usize) {
if self.blocks.len() > Self::block_idx(idx) {
let bit = Self::shifted_bit(idx);
*self.mut_block(idx) &= !bit;
}
}
pub fn get_bit(&self, n: usize) -> bool {
let off = n % 64;
let bit = 1 << off as u64;
self.get_block(n) & bit != 0
}
pub fn first_unset(&self) -> usize {
for (i,block) in self.blocks.iter().enumerate() {
if *block != u64::max_value() {
return (i * 64) + (0..64).find(|n| Self::shifted_bit(*n) & *block == 0).expect("...");
}
}
self.blocks.len() * 64
}
fn shifted_bit(idx: usize) -> u64 {
let shift = (idx % 64) as u64;
(1 << shift)
}
fn block_idx(idx: usize) -> usize {
idx / 64
}
fn get_block(&self, idx: usize) -> u64 {
let idx = Self::block_idx(idx);
if self.blocks.len() > idx {
self.blocks[idx]
} else {
0
}
}
fn mut_block(&mut self, idx: usize) -> &mut u64 {
let idx = Self::block_idx(idx);
if self.blocks.len() <= idx {
self.blocks.resize_with(idx + 1, Default::default);
}
&mut self.blocks[idx]
}
}
static TRUE: bool = true;
static FALSE: bool = false;
impl Index<usize> for BitVec {
type Output = bool;
fn index(&self, index: usize) -> &Self::Output {
if self.get_bit(index) {
&TRUE
} else {
&FALSE
}
}
}