extern crate core;
extern crate bit_vec;
use bit_vec::BitVec;
pub struct ValueVec {
bits_per_val: usize,
mask: u32,
bits: BitVec,
}
impl ValueVec {
pub fn new(bits_per_val: usize, count: usize) -> ValueVec {
let bits = bits_per_val*count;
ValueVec {
bits_per_val: bits_per_val,
mask: 2u32.pow(bits_per_val as u32)-1,
bits: BitVec::from_elem(bits,false),
}
}
pub fn with_max(max_val: u32, count: usize) -> ValueVec {
let mut bits_per_val = 0;
let mut cur = max_val;
while cur > 0 {
bits_per_val+=1;
cur>>=1;
}
ValueVec::new(bits_per_val,count)
}
pub fn bits_per_val(&self) -> usize {
self.bits_per_val
}
pub fn max_value(&self) -> u32 {
self.mask
}
pub fn clear(&mut self) {
self.bits.clear();
}
fn set_bits(&mut self, idx: usize, val: u32, num_bits: usize) {
let mut blocks = unsafe {self.bits.storage_mut()};
let blockidx = idx/32;
let shift = 32-(idx%32)-num_bits;
let mask =
if num_bits==self.bits_per_val {
self.mask
} else {
2u32.pow(num_bits as u32)-1
} << shift;
let block = blocks[blockidx];
let zeroed = (block ^ mask) & block;
blocks[blockidx] = zeroed | (val<<shift);
}
fn get_bits(&self, idx: usize, num_bits: usize) -> u32 {
let blocks = self.bits.storage();
let shift = 32-(idx%32)-num_bits;
let mask =
if num_bits==self.bits_per_val {
self.mask
} else {
2u32.pow(num_bits as u32)-1
} << shift;
let val = blocks[idx/32] & mask;
val >> shift
}
pub fn len(&self) -> usize {
self.bits.len()
}
pub fn set(&mut self, i: usize, val: u32) {
if val > self.mask {
panic!("set with val {}, max value this ValueVec can hold is {}",
val,self.mask);
}
let idx = i*self.bits_per_val;
let rem = 32-(idx%32);
if rem < self.bits_per_val {
let left = self.bits_per_val-rem;
let lowerval = val>>left;
self.set_bits(idx,lowerval,rem);
let upval = val&(2u32.pow(left as u32)-1);
self.set_bits(idx+rem,upval,left);
} else {
let vs = self.bits_per_val;
self.set_bits(idx,val,vs);
}
}
pub fn get(&self, i: usize) -> u32 {
let idx = i*self.bits_per_val;
let rem = 32-(idx%32);
if rem < self.bits_per_val {
let lower = self.get_bits(idx,rem);
let left = self.bits_per_val-rem;
let upper = self.get_bits(idx+rem,left);
(lower<<left)|upper
} else {
self.get_bits(idx,self.bits_per_val)
}
}
}
#[cfg(test)]
mod tests {
use valuevec::ValueVec;
#[test]
fn set_get_no_overlap() {
let mut vv = ValueVec::new(4,12);
vv.set(1,3);
assert_eq!(vv.get(1),3);
vv.set(2,4);
assert_eq!(vv.get(1),3);
assert_eq!(vv.get(2),4);
vv.set(11,2);
assert_eq!(vv.get(1),3);
assert_eq!(vv.get(2),4);
assert_eq!(vv.get(11),2);
}
#[test]
fn set_get_overlap() {
let mut vv = ValueVec::new(3,12);
vv.set(1,3);
assert_eq!(vv.get(1),3);
vv.set(2,4);
assert_eq!(vv.get(1),3);
assert_eq!(vv.get(2),4);
vv.set(10,7);
assert_eq!(vv.get(1),3);
assert_eq!(vv.get(2),4);
assert_eq!(vv.get(10),7);
vv.set(11,2);
assert_eq!(vv.get(1),3);
assert_eq!(vv.get(2),4);
assert_eq!(vv.get(10),7);
assert_eq!(vv.get(11),2);
}
#[test]
#[should_panic]
fn set_over_max() {
let mut vv = ValueVec::new(2,2);
vv.set(0,100);
}
#[test]
fn with_max() {
let mut vv = ValueVec::with_max(35,3);
vv.set(0,35);
assert_eq!(vv.get(0),35);
vv.set(2,14);
assert_eq!(vv.get(0),35);
assert_eq!(vv.get(2),14);
assert_eq!(vv.get(1),0);
}
#[test]
#[should_panic]
fn over_with_max() {
let mut vv = ValueVec::with_max(7,2);
vv.set(0,7);
vv.set(1,8);
}
}