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::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;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user