Custom hasher.
This commit is contained in:
73
src/lib.rs
73
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<BitHasher>;
|
||||
type BitHashMap<K, V> = HashMap<K, V, BitBuildHasher>;
|
||||
type BitHashSet<T> = HashSet<T, BitBuildHasher>;
|
||||
|
||||
const BITS: usize = 64;
|
||||
|
||||
type Block = u64;
|
||||
type Storage = FnvHashMap<usize, Block>;
|
||||
type Storage = BitHashMap<u64, Block>;
|
||||
|
||||
#[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<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 {
|
||||
type Output = Self;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user