use num_traits::{One, Zero, ToPrimitive};
use storage::{Address, BlockType};
pub trait BitVec {
type Block: BlockType;
fn bit_len(&self) -> u64;
fn block_len(&self) -> usize {
self.bit_len().ceil_div(Self::Block::nbits() as u64) as usize
}
fn get_bit(&self, position: u64) -> bool {
assert!(position < self.bit_len(), "BitVec::get_bit: out of bounds");
let address = Address::new::<Self::Block>(position);
let block = self.get_block(address.block_index);
block.get_bit(address.bit_offset)
}
fn get_block(&self, position: usize) -> Self::Block {
assert!(position < self.block_len(),
"IntSlice::get_block: out of bounds");
let bit_position = position as u64 * Self::Block::nbits() as u64;
let mut result = Self::Block::zero();
let mut mask = Self::Block::one();
for i in 0 .. Self::Block::nbits() as u64 {
if bit_position + i < self.bit_len() && self.get_bit(bit_position + i) {
result = result | mask;
}
mask = mask << 1;
}
result
}
fn get_bits(&self, start: u64, count: usize) -> Self::Block {
let limit = start + count as u64;
assert!(limit <= self.bit_len(), "BitVec::get_bits: out of bounds");
let address = Address::new::<Self::Block>(start);
let margin = Self::Block::nbits() - address.bit_offset;
if margin >= count {
let block = self.get_block(address.block_index);
return block.get_bits(address.bit_offset, count)
}
let extra = count - margin;
let block1 = self.get_block(address.block_index);
let block2 = self.get_block(address.block_index + 1);
let low_bits = block1.get_bits(address.bit_offset, margin);
let high_bits = block2.get_bits(0, extra);
(high_bits << margin) | low_bits
}
}
pub trait BitVecMut: BitVec {
fn set_bit(&mut self, position: u64, value: bool) {
assert!(position < self.bit_len(), "BitVecMut::set_bit: out of bounds");
let address = Address::new::<Self::Block>(position);
let old_block = self.get_block(address.block_index);
let new_block = old_block.with_bit(address.bit_offset, value);
self.set_block(address.block_index, new_block);
}
fn set_block(&mut self, position: usize, mut value: Self::Block) {
let limit = if position + 1 == self.block_len() {
Self::Block::last_block_bits(self.bit_len())
} else {
Self::Block::nbits()
};
let start = Self::Block::mul_nbits(position);
for i in 0 .. limit as u64 {
let bit = value & Self::Block::one() != Self::Block::zero();
self.set_bit(start + i, bit);
value = value >> 1;
}
}
fn set_bits(&mut self, start: u64, count: usize, value: Self::Block) {
let limit = start + count as u64;
assert!(limit <= self.bit_len(), "BitVecMut::set_bits: out of bounds");
let address = Address::new::<Self::Block>(start);
let margin = Self::Block::nbits() - address.bit_offset;
if margin >= count {
let old_block = self.get_block(address.block_index);
let new_block = old_block.with_bits(address.bit_offset, count, value);
self.set_block(address.block_index, new_block);
return;
}
let extra = count - margin;
let old_block1 = self.get_block(address.block_index);
let old_block2 = self.get_block(address.block_index + 1);
let high_bits = value >> margin;
let new_block1 = old_block1.with_bits(address.bit_offset,
margin, value);
let new_block2 = old_block2.with_bits(0, extra, high_bits);
self.set_block(address.block_index, new_block1);
self.set_block(address.block_index + 1, new_block2);
}
}
pub trait BitVecPush: BitVecMut {
fn push_bit(&mut self, value: bool);
fn pop_bit(&mut self) -> Option<bool>;
fn align_block(&mut self, value: bool) {
while Self::Block::mod_nbits(self.bit_len()) != 0 {
self.push_bit(value);
}
}
fn push_block(&mut self, mut value: Self::Block) {
self.align_block(false);
for _ in 0 .. Self::Block::nbits() {
self.push_bit(value & Self::Block::one() != Self::Block::zero());
value = value >> 1;
}
}
}
impl<Block: BlockType> BitVec for [Block] {
type Block = Block;
#[inline]
fn bit_len(&self) -> u64 {
self.len() as u64 * Block::nbits() as u64
}
#[inline]
fn block_len(&self) -> usize {
self.len()
}
#[inline]
fn get_block(&self, position: usize) -> Block {
self[position]
}
}
impl<Block: BlockType> BitVecMut for [Block] {
#[inline]
fn set_block(&mut self, position: usize, value: Block) {
self[position] = value;
}
}
impl<'a, Block: BlockType> BitVec for &'a [Block] {
type Block = Block;
#[inline]
fn bit_len(&self) -> u64 {
self.len() as u64 * Block::nbits() as u64
}
#[inline]
fn block_len(&self) -> usize {
self.len()
}
#[inline]
fn get_block(&self, position: usize) -> Block {
self[position]
}
}
impl<'a, Block: BlockType> BitVec for &'a mut [Block] {
type Block = Block;
#[inline]
fn bit_len(&self) -> u64 {
self.len() as u64 * Block::nbits() as u64
}
#[inline]
fn block_len(&self) -> usize {
self.len()
}
#[inline]
fn get_block(&self, position: usize) -> Block {
self[position]
}
}
impl<'a, Block: BlockType> BitVecMut for &'a mut [Block] {
#[inline]
fn set_block(&mut self, position: usize, value: Block) {
self[position] = value;
}
}
impl<Block: BlockType> BitVec for Vec<Block> {
type Block = Block;
#[inline]
fn bit_len(&self) -> u64 {
self.len() as u64 * Block::nbits() as u64
}
#[inline]
fn block_len(&self) -> usize {
self.len()
}
#[inline]
fn get_block(&self, position: usize) -> Block {
self[position]
}
}
impl<Block: BlockType> BitVecMut for Vec<Block> {
#[inline]
fn set_block(&mut self, position: usize, value: Block) {
self[position] = value;
}
}
impl BitVec for Vec<bool> {
type Block = u8;
#[inline]
fn bit_len(&self) -> u64 {
self.len() as u64
}
fn get_bit(&self, position: u64) -> bool {
self[position.to_usize().expect("Vec<bool>::get_bit: overflow")]
}
}
impl BitVecMut for Vec<bool> {
fn set_bit(&mut self, position: u64, value: bool) {
let position = position.to_usize()
.expect("Vec<bool>::set_bit: overflow");
self[position] = value;
}
}
impl BitVecPush for Vec<bool> {
fn push_bit(&mut self, value: bool) {
self.push(value);
}
fn pop_bit(&mut self) -> Option<bool> {
self.pop()
}
}