diff --git a/src/block.rs b/src/block.rs index b15d512..1ef01cb 100644 --- a/src/block.rs +++ b/src/block.rs @@ -22,29 +22,67 @@ pub trait BitBlock const ZERO: Self; const ONE: Self; - fn bits() -> u8; + fn bits() -> usize; fn count_ones(self) -> usize; + + fn block(value: Self) -> Self; + fn bit(value: Self) -> Self; } -macro_rules! bit_block_impl { +pub trait Block + : Copy + + Hash + + Eq + + Shl + + BitAnd + + BitOr + + Not { + const ZERO: Self; + const ONE: Self; + + fn bits() -> usize; + fn count_ones(self) -> usize; + + fn block(value: Self) -> Self + where + B: Block; + fn bit(value: B) -> Self + where + B: Block; + + fn biter(value: Self) -> u8 + where + B: Block; +} + +macro_rules! block_impl { ($(($t: ty, $size: expr)),*) => ($( - impl BitBlock for $t { + impl Block for $t { const ZERO: Self = 0; const ONE: Self = 1; #[inline] - fn bits() -> u8 { $size } + fn bits() -> usize { $size } #[inline] fn count_ones(self) -> usize { self.count_ones() as usize } + + #[inline] + fn block(value: Self) -> Self where B: Block { value / B::bits() as Self } + + #[inline] + fn bit(value: B) -> Self where B: Block { B::biter::(value) as Self } + + #[inline] + fn biter(value: Self) -> u8 where B: Block { (value % B::bits() as Self) as u8 } } )*) } -bit_block_impl!{ +block_impl!{ (u8, 8), (u16, 16), (u32, 32), (u64, 64), - (usize, (mem::size_of::() * 8) as u8) + (usize, mem::size_of::() * 8) } diff --git a/src/lib.rs b/src/lib.rs index a8d27de..ea95ed5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,29 +15,29 @@ mod hasher; mod block; use hasher::BitBuildHasher; -use block::BitBlock; +use block::Block; pub type BitHashMap = HashMap; #[inline] -fn get_block_and_bit(x: T) -> (T, B) +fn index(value: T) -> (T, B) where - T: BitBlock, - B: BitBlock, + T: Block, + B: Block, { - (x / T::from(B::bits()), x % T::from(B::bits()) + (T::block::(value), B::bit(value)) } #[derive(PartialEq)] -pub struct BitSet { +pub struct BitSet { blocks: HashMap, nbits: usize, } impl BitSet where - T: BitBlock, - B: BitBlock, + T: Block, + B: Block, { #[inline] pub fn new() -> BitSet { @@ -50,7 +50,10 @@ where #[inline] pub fn with_capacity(capacity: usize) -> BitSet { BitSet { - blocks: HashMap::with_capacity_and_hasher(capacity / B::bits() as usize, Default::default()), + blocks: HashMap::with_capacity_and_hasher( + capacity / B::bits() as usize, + Default::default(), + ), nbits: 0, } } @@ -94,40 +97,40 @@ where } pub fn contains(&self, value: &T) -> bool { - let (block, bit) = get_block_and_bit::(*value); + let (block, bit) = index::(*value); match self.blocks.get(&block) { - Some(block) => (block & (B::ONE << bit)) != B::ZERO, + Some(block) => (*block & (B::ONE << bit)) != B::ZERO, None => false, } } - /* - pub fn is_subset(&self, other: &BitSet) -> bool { + + pub fn is_subset(&self, other: &BitSet) -> bool { if self.nbits > other.nbits { false } else { self.blocks .iter() .all(|(key, block_a)| match other.blocks.get(key) { - Some(block_b) => block_a | block_b == *block_b, - None => *block_a == 0, + Some(block_b) => *block_a | *block_b == *block_b, + None => *block_a == B::ZERO, }) } } #[inline] - pub fn is_superset(&self, other: &BitSet) -> bool { + pub fn is_superset(&self, other: &BitSet) -> bool { other.is_subset(self) } - pub fn insert(&mut self, value: u64) -> bool { - let (block, bit) = get_block_and_bit::(&value); - let block = self.blocks.entry(block).or_insert(0); + pub fn insert(&mut self, value: T) -> bool { + let (block, bit) = index::(value); + let block = self.blocks.entry(block).or_insert(B::ZERO); - let n = 1 << bit; + let n = B::ONE << bit; - if (*block & n) == 0 { - *block |= n; + if (*block & n) == B::ZERO { + *block = *block | n; self.nbits += 1; true @@ -136,14 +139,14 @@ where } } - pub fn remove(&mut self, value: &u64) -> bool { - let (block, bit) = get_block_and_bit::(value); - let block = self.blocks.entry(block).or_insert(0); + pub fn remove(&mut self, value: &T) -> bool { + let (block, bit) = index::(*value); + let block = self.blocks.entry(block).or_insert(B::ZERO); - let n = 1 << bit; + let n = B::ONE << bit; - if (*block & n) != 0 { - *block &= !n; + if (*block & n) != B::ZERO { + *block = *block & !n; self.nbits -= 1; true @@ -154,93 +157,97 @@ where pub fn union_with(&mut self, other: &Self) { for (key, value) in &other.blocks { - *self.blocks.entry(*key).or_insert(0) |= value; + let block = self.blocks.entry(*key).or_insert(B::ZERO); + *block = *block | *value; } self.nbits = self.blocks .values() - .map(|block| block.count_ones() as usize) + .map(|block| B::count_ones(*block)) .sum(); } - */ } + /* -impl fmt::Debug for BitSet { +impl fmt::Debug for BitSet { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_set().entries(self.iter()).finish() } } +*/ -impl FromIterator for BitSet { +impl FromIterator for BitSet where T: Block, B: Block { #[inline] - fn from_iter>(iter: I) -> BitSet { + fn from_iter>(iter: I) -> BitSet { let mut set = BitSet::new(); set.extend(iter); set } } -impl Extend for BitSet { +impl Extend for BitSet where T: Block, B: Block { #[inline] - fn extend>(&mut self, iter: I) { + fn extend>(&mut self, iter: I) { for i in iter { self.insert(i); } } } -impl<'a, B> Extend<&'a u64> for BitSet { +impl<'a, T: 'a, B> Extend<&'a T> for BitSet where T: Block, B: Block { #[inline] - fn extend>(&mut self, iter: I) { + fn extend>(&mut self, iter: I) { for i in iter { self.insert(*i); } } } -impl Default for BitSet { +impl Default for BitSet where T: Block, B: Block { #[inline] - fn default() -> BitSet { + fn default() -> BitSet { BitSet::new() } } -impl ops::BitOr for BitSet { +impl ops::BitOr for BitSet where T: Block, B: Block { type Output = Self; #[inline] fn bitor(mut self, rhs: Self) -> Self { for (key, value) in &rhs.blocks { - *self.blocks.entry(*key).or_insert(0) |= value; + let block = self.blocks.entry(*key).or_insert(B::ZERO); + *block = *block | *value; } self.nbits = self.blocks .values() - .map(|block| block.count_ones() as usize) + .map(|block| block.count_ones()) .sum(); self } } -impl<'a, B> ops::BitOr<&'a Self> for BitSet { +impl<'a, T, B> ops::BitOr<&'a Self> for BitSet where T: Block, B: Block { type Output = Self; #[inline] fn bitor(mut self, rhs: &'a Self) -> Self { for (key, value) in &rhs.blocks { - *self.blocks.entry(*key).or_insert(0) |= value; + let block = self.blocks.entry(*key).or_insert(B::ZERO); + *block = *block | *value; } self.nbits = self.blocks .values() - .map(|block| block.count_ones() as usize) + .map(|block| block.count_ones()) .sum(); self } } - +/* pub struct Iter<'a> { iter: std::collections::hash_map::Iter<'a, u64, u64>, block: u64,