diff --git a/src/lib.rs b/src/lib.rs index 92099bd..7a23fe4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,17 +1,47 @@ -extern crate fnv; - use std::ops; use std::iter::FromIterator; +use std::default::Default; +use std::hash::{Hasher, BuildHasherDefault}; +use std::collections::{HashMap, HashSet}; -use fnv::FnvHashMap; +const BITS: u64 = 64; + +struct BitHasher(u64); + +impl Default for BitHasher { + #[inline] + fn default() -> BitHasher { + BitHasher(0) + } +} + +impl Hasher for BitHasher { + #[inline] + fn finish(&self) -> u64 { + self.0 + } + + #[inline] + fn write(&mut self, _: &[u8]) { + panic!("this hasher only works with u64"); + } + + #[inline] + fn write_u64(&mut self, i: u64) { + *self = BitHasher(i); + } +} + +type BitBuildHasher = BuildHasherDefault; +type BitHashMap = HashMap; +type BitHashSet = HashSet; -const BITS: usize = 64; type Block = u64; -type Storage = FnvHashMap; +type Storage = BitHashMap; #[inline] -fn block_bit(x: usize, d: usize) -> (usize, usize) { +fn block_bit(x: u64, d: u64) -> (u64, u64) { (x / d, x % d) } @@ -22,6 +52,7 @@ pub struct BitSet { } impl BitSet { + #[inline] pub fn new() -> BitSet { BitSet { blocks: Storage::default(), @@ -29,30 +60,35 @@ impl BitSet { } } + #[inline] pub fn with_capacity(nbits: usize) -> BitSet { - let (mut block, bit) = block_bit(nbits, BITS); - block += (bit > 0) as usize; + let (mut block, bit) = block_bit(nbits as u64, BITS); + block += (bit > 0) as u64; BitSet { - blocks: Storage::with_capacity_and_hasher(block, Default::default()), + blocks: Storage::with_capacity_and_hasher(block as usize, Default::default()), nbits: 0, } } + #[inline] pub fn capacity(&self) -> usize { - self.blocks.len() * BITS + self.blocks.len() * BITS as usize } + #[inline] pub fn len(&self) -> usize { self.nbits } + #[inline] pub fn is_empty(&self) -> bool { self.nbits == 0 } + #[inline] pub fn insert(&mut self, value: usize) -> bool { - let (block, bit) = block_bit(value, BITS); + let (block, bit) = block_bit(value as u64, BITS); let block = self.blocks.entry(block).or_insert(0); if (*block & (1 << bit)) == 0 { @@ -65,8 +101,9 @@ impl BitSet { } } + #[inline] pub fn remove(&mut self, value: usize) -> bool { - let (block, bit) = block_bit(value, BITS); + let (block, bit) = block_bit(value as u64, BITS); let block = self.blocks.entry(block).or_insert(0); if (*block & (1 << bit)) != 0 { @@ -79,8 +116,9 @@ impl BitSet { } } + #[inline] pub fn contains(&self, value: usize) -> bool { - let (block, bit) = block_bit(value, BITS); + let (block, bit) = block_bit(value as u64, BITS); match self.blocks.get(&block) { None => false, @@ -113,6 +151,15 @@ impl Extend for BitSet { } } +impl<'a> Extend<&'a usize> for BitSet { + #[inline] + fn extend>(&mut self, iter: I) { + for i in iter { + self.insert(*i); + } + } +} + impl ops::BitOr for BitSet { type Output = Self;