Move hasher to a seperate file.
This commit is contained in:
@@ -3,5 +3,8 @@ name = "bit-set"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["logaritmisk <anders.e.olsson@gmail.com>"]
|
authors = ["logaritmisk <anders.e.olsson@gmail.com>"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
unreachable = "1.0"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = true
|
||||||
|
|||||||
32
src/hasher.rs
Normal file
32
src/hasher.rs
Normal file
@@ -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<BitHasher>;
|
||||||
74
src/lib.rs
74
src/lib.rs
@@ -1,43 +1,18 @@
|
|||||||
|
extern crate unreachable;
|
||||||
|
|
||||||
use std::ops;
|
use std::ops;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::hash::{BuildHasherDefault, Hasher};
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
mod hasher;
|
||||||
|
|
||||||
|
use hasher::BitBuildHasher;
|
||||||
|
|
||||||
const BITS: u64 = 64;
|
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>;
|
|
||||||
|
|
||||||
type Block = u64;
|
type Block = u64;
|
||||||
type Storage = BitHashMap<u64, Block>;
|
type Storage = HashMap<u64, Block, BitBuildHasher>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn block_bit(x: u64, d: u64) -> (u64, u64) {
|
fn block_bit(x: u64, d: u64) -> (u64, u64) {
|
||||||
@@ -60,12 +35,9 @@ impl BitSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn with_capacity(nbits: usize) -> BitSet {
|
pub fn with_capacity(capacity: usize) -> BitSet {
|
||||||
let (mut block, bit) = block_bit(nbits as u64, BITS);
|
|
||||||
block += (bit > 0) as u64;
|
|
||||||
|
|
||||||
BitSet {
|
BitSet {
|
||||||
blocks: Storage::with_capacity_and_hasher(block as usize, Default::default()),
|
blocks: Storage::with_capacity_and_hasher(capacity, Default::default()),
|
||||||
nbits: 0,
|
nbits: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,8 +96,8 @@ impl BitSet {
|
|||||||
let (block, bit) = block_bit(value, BITS);
|
let (block, bit) = block_bit(value, BITS);
|
||||||
|
|
||||||
match self.blocks.get(&block) {
|
match self.blocks.get(&block) {
|
||||||
None => false,
|
|
||||||
Some(block) => (block & (1 << bit)) != 0,
|
Some(block) => (block & (1 << bit)) != 0,
|
||||||
|
None => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,22 +152,17 @@ impl ops::BitOr for BitSet {
|
|||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn bitor(self, rhs: Self) -> Self {
|
fn bitor(mut self, rhs: Self) -> Self {
|
||||||
let mut blocks = self.blocks.clone();
|
|
||||||
|
|
||||||
for (key, value) in &rhs.blocks {
|
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()
|
.values()
|
||||||
.map(|block| block.count_ones() as usize)
|
.map(|block| block.count_ones() as usize)
|
||||||
.sum();
|
.sum();
|
||||||
|
|
||||||
BitSet {
|
self
|
||||||
blocks: blocks,
|
|
||||||
nbits: nbits,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,22 +170,17 @@ impl<'a> ops::BitOr<&'a Self> for BitSet {
|
|||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn bitor(self, rhs: &'a Self) -> Self {
|
fn bitor(mut self, rhs: &'a Self) -> Self {
|
||||||
let mut blocks = self.blocks.clone();
|
|
||||||
|
|
||||||
for (key, value) in &rhs.blocks {
|
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()
|
.values()
|
||||||
.map(|block| block.count_ones() as usize)
|
.map(|block| block.count_ones() as usize)
|
||||||
.sum();
|
.sum();
|
||||||
|
|
||||||
BitSet {
|
self
|
||||||
blocks: blocks,
|
|
||||||
nbits: nbits,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user