diff --git a/Cargo.toml b/Cargo.toml index 138a6b0..dc3ec25 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,5 +3,8 @@ name = "bit-set" version = "0.1.0" authors = ["logaritmisk "] +[dependencies] +unreachable = "1.0" + [profile.release] lto = true diff --git a/src/hasher.rs b/src/hasher.rs new file mode 100644 index 0000000..cbba651 --- /dev/null +++ b/src/hasher.rs @@ -0,0 +1,32 @@ +use std::default::Default; +use std::hash::{BuildHasherDefault, Hasher}; + +use unreachable; + +pub 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]) { + unsafe { unreachable::unreachable() }; + } + + #[inline] + fn write_u64(&mut self, i: u64) { + *self = BitHasher(i); + } +} + +pub type BitBuildHasher = BuildHasherDefault; diff --git a/src/lib.rs b/src/lib.rs index 8609b6b..624c8db 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,43 +1,18 @@ +extern crate unreachable; + use std::ops; use std::iter::FromIterator; use std::default::Default; -use std::hash::{BuildHasherDefault, Hasher}; use std::collections::HashMap; +mod hasher; + +use hasher::BitBuildHasher; + 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; - type Block = u64; -type Storage = BitHashMap; +type Storage = HashMap; #[inline] fn block_bit(x: u64, d: u64) -> (u64, u64) { @@ -60,12 +35,9 @@ impl BitSet { } #[inline] - pub fn with_capacity(nbits: usize) -> BitSet { - let (mut block, bit) = block_bit(nbits as u64, BITS); - block += (bit > 0) as u64; - + pub fn with_capacity(capacity: usize) -> BitSet { BitSet { - blocks: Storage::with_capacity_and_hasher(block as usize, Default::default()), + blocks: Storage::with_capacity_and_hasher(capacity, Default::default()), nbits: 0, } } @@ -124,8 +96,8 @@ impl BitSet { let (block, bit) = block_bit(value, BITS); match self.blocks.get(&block) { - None => false, Some(block) => (block & (1 << bit)) != 0, + None => false, } } @@ -180,22 +152,17 @@ impl ops::BitOr for BitSet { type Output = Self; #[inline] - fn bitor(self, rhs: Self) -> Self { - let mut blocks = self.blocks.clone(); - + fn bitor(mut self, rhs: Self) -> Self { for (key, value) in &rhs.blocks { - *blocks.entry(*key).or_insert(0) |= value; + *self.blocks.entry(*key).or_insert(0) |= value; } - let nbits = blocks + self.nbits = self.blocks .values() .map(|block| block.count_ones() as usize) .sum(); - BitSet { - blocks: blocks, - nbits: nbits, - } + self } } @@ -203,22 +170,17 @@ impl<'a> ops::BitOr<&'a Self> for BitSet { type Output = Self; #[inline] - fn bitor(self, rhs: &'a Self) -> Self { - let mut blocks = self.blocks.clone(); - + fn bitor(mut self, rhs: &'a Self) -> Self { for (key, value) in &rhs.blocks { - *blocks.entry(*key).or_insert(0) |= value; + *self.blocks.entry(*key).or_insert(0) |= value; } - let nbits = blocks + self.nbits = self.blocks .values() .map(|block| block.count_ones() as usize) .sum(); - BitSet { - blocks: blocks, - nbits: nbits, - } + self } }