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 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; } }