Custom hasher.

This commit is contained in:
2018-01-03 14:52:29 +01:00
parent c1d10cb659
commit b9a5b10e1c

View File

@@ -1,17 +1,47 @@
extern crate fnv;
use std::ops; use std::ops;
use std::iter::FromIterator; 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<BitHasher>;
type BitHashMap<K, V> = HashMap<K, V, BitBuildHasher>;
type BitHashSet<T> = HashSet<T, BitBuildHasher>;
const BITS: usize = 64;
type Block = u64; type Block = u64;
type Storage = FnvHashMap<usize, Block>; type Storage = BitHashMap<u64, Block>;
#[inline] #[inline]
fn block_bit(x: usize, d: usize) -> (usize, usize) { fn block_bit(x: u64, d: u64) -> (u64, u64) {
(x / d, x % d) (x / d, x % d)
} }
@@ -22,6 +52,7 @@ pub struct BitSet {
} }
impl BitSet { impl BitSet {
#[inline]
pub fn new() -> BitSet { pub fn new() -> BitSet {
BitSet { BitSet {
blocks: Storage::default(), blocks: Storage::default(),
@@ -29,30 +60,35 @@ impl BitSet {
} }
} }
#[inline]
pub fn with_capacity(nbits: usize) -> BitSet { pub fn with_capacity(nbits: usize) -> BitSet {
let (mut block, bit) = block_bit(nbits, BITS); let (mut block, bit) = block_bit(nbits as u64, BITS);
block += (bit > 0) as usize; block += (bit > 0) as u64;
BitSet { BitSet {
blocks: Storage::with_capacity_and_hasher(block, Default::default()), blocks: Storage::with_capacity_and_hasher(block as usize, Default::default()),
nbits: 0, nbits: 0,
} }
} }
#[inline]
pub fn capacity(&self) -> usize { pub fn capacity(&self) -> usize {
self.blocks.len() * BITS self.blocks.len() * BITS as usize
} }
#[inline]
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.nbits self.nbits
} }
#[inline]
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
self.nbits == 0 self.nbits == 0
} }
#[inline]
pub fn insert(&mut self, value: usize) -> bool { 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); let block = self.blocks.entry(block).or_insert(0);
if (*block & (1 << bit)) == 0 { if (*block & (1 << bit)) == 0 {
@@ -65,8 +101,9 @@ impl BitSet {
} }
} }
#[inline]
pub fn remove(&mut self, value: usize) -> bool { 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); let block = self.blocks.entry(block).or_insert(0);
if (*block & (1 << bit)) != 0 { if (*block & (1 << bit)) != 0 {
@@ -79,8 +116,9 @@ impl BitSet {
} }
} }
#[inline]
pub fn contains(&self, value: usize) -> bool { 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) { match self.blocks.get(&block) {
None => false, None => false,
@@ -113,6 +151,15 @@ impl Extend<usize> for BitSet {
} }
} }
impl<'a> Extend<&'a usize> for BitSet {
#[inline]
fn extend<I: IntoIterator<Item = &'a usize>>(&mut self, iter: I) {
for i in iter {
self.insert(*i);
}
}
}
impl ops::BitOr for BitSet { impl ops::BitOr for BitSet {
type Output = Self; type Output = Self;