ai-0/lab2/src/algo/bit_vector.rs

102 lines
2.4 KiB
Rust

use std::cmp::min;
use std::ops::{BitAnd, BitAndAssign, Index, IndexMut, Not, Shl};
pub struct BitVector {
len: usize,
data: Box<[usize]>,
}
impl BitVector {
pub fn alloc(len: usize) -> Self {
return Self {
len,
data: vec![0usize; (len + (usize::BITS as usize) - 1) / (usize::BITS as usize)]
.into_boxed_slice(),
};
}
pub fn count1(&self) -> usize {
let mut counter = 0usize;
for i in 0..(self.data.len() - 1) {
counter += self.data[i].count_ones() as usize;
}
counter += (self.data[self.data.len() - 1]
& (0usize.not().shl(self.len % (usize::BITS as usize)).not()))
.count_ones() as usize;
return counter;
}
pub fn len(&self) -> usize {
return self.len;
}
}
impl Clone for BitVector {
fn clone(&self) -> Self {
return Self {
len: self.len,
data: self.data.clone(),
};
}
}
impl BitAnd<Self> for &BitVector {
type Output = BitVector;
fn bitand(self, rhs: Self) -> Self::Output {
let mut intersected = self.clone();
intersected &= rhs;
return intersected;
}
}
impl BitAndAssign<&Self> for BitVector {
fn bitand_assign(&mut self, rhs: &Self) {
assert_eq!(self.len, rhs.len, "Vectors has different length's");
for i in 0..self.data.len() {
self.data[i] &= rhs.data[i]
}
}
}
struct _BitLocation {
offset: usize,
mask: usize,
}
impl BitVector {
fn _unpackIndex(&self, i: usize) -> _BitLocation {
assert!(i < self.len);
return _BitLocation {
offset: i / (usize::BITS as usize),
mask: 1 << i % (usize::BITS as usize),
};
}
pub fn get(&self, i: usize) -> bool {
let bl = self._unpackIndex(i);
return self.data[bl.offset] & bl.mask != 0;
}
pub fn set(&mut self, i: usize, value: bool) {
let bl = self._unpackIndex(i);
if value {
self.data[bl.offset] |= bl.mask;
} else {
self.data[bl.offset] &= !bl.mask;
}
}
}
impl BitVector {
pub fn resized(&self, newLen: usize) -> BitVector {
let mut new = Self::alloc(newLen);
for i in 0..(min(self.data.len(), new.data.len())) {
new.data[i] = self.data[i]
}
return new;
}
}