Skip to content

Commit

Permalink
Pull shared code into a module
Browse files Browse the repository at this point in the history
This implements @glennw's PR #5 to move the hashing code used by both
phf and phf_mac into a module imported by both crates. It breaks the
hard dependency of phf_mac on phf, which means phf doesn't have to be
compiled for the host architecture as well as the target. It also means
we can have a dev-dependency from phf to phf_mac for tests.
  • Loading branch information
sfackler committed Jul 13, 2014
1 parent a8bb815 commit 19c4f8d
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 43 deletions.
2 changes: 1 addition & 1 deletion Makefile.in
Expand Up @@ -26,7 +26,7 @@ $(BUILDDIR):
$(PHF): $(PHF_LIB) | $(BUILDDIR)
$(ENV) $(RUSTC) $(RUSTFLAGS) --dep-info $(BUILDDIR)/phf.d --out-dir $(@D) $<

$(PHF_MAC): $(PHF_MAC_LIB) $(PHF) | $(BUILDDIR)
$(PHF_MAC): $(PHF_MAC_LIB) | $(BUILDDIR)
$(ENV) $(RUSTC) $(RUSTFLAGS) --dep-info $(BUILDDIR)/phf_mac.d --out-dir $(@D) \
-L $(BUILDDIR) $<

Expand Down
9 changes: 9 additions & 0 deletions phf/Cargo.toml
Expand Up @@ -8,3 +8,12 @@ version = "0.0.0"

name = "phf"
path = "src/lib.rs"

[dev_dependencies.phf_mac]

path = "../phf_mac"

[[test]]

name = "test"
path = "src/test.rs"
34 changes: 7 additions & 27 deletions phf/src/lib.rs
Expand Up @@ -9,33 +9,13 @@
#![warn(missing_doc)]

use std::fmt;
use std::hash::{Hash, Hasher};
use std::hash::sip::SipHasher;
use std::hash::Hash;
use std::iter;
use std::slice;
use std::collections::Collection;

static LOG_MAX_SIZE: uint = 21;

#[doc(hidden)]
pub static MAX_SIZE: uint = 1 << LOG_MAX_SIZE;

#[doc(hidden)]
#[inline]
pub fn hash<T: Hash>(s: &T, k1: u64, k2: u64) -> (uint, uint, uint) {
let hash = SipHasher::new_with_keys(k1, k2).hash(s);
let mask = (MAX_SIZE - 1) as u64;

((hash & mask) as uint,
((hash >> LOG_MAX_SIZE) & mask) as uint,
((hash >> (2 * LOG_MAX_SIZE)) & mask) as uint)
}

#[doc(hidden)]
#[inline]
pub fn displace(f1: uint, f2: uint, d1: uint, d2: uint) -> uint {
d2 + f1 * d1 + f2
}
#[path="../../phf_shared/mod.rs"]
mod phf_shared;

/// An immutable map constructed at compile time.
///
Expand Down Expand Up @@ -106,9 +86,9 @@ impl<K: fmt::Show, V: fmt::Show> fmt::Show for PhfMap<K, V> {
impl<K: Hash+Eq, V> PhfMap<K, V> {
fn get_entry<'a, T: Hash>(&'a self, key: &T, check: |&K| -> bool)
-> Option<&'a (K, V)> {
let (g, f1, f2) = hash(key, self.k1, self.k2);
let (g, f1, f2) = phf_shared::hash(key, self.k1, self.k2);
let (d1, d2) = self.disps[g % self.disps.len()];
let entry @ &(ref s, _) = &self.entries[displace(f1, f2, d1, d2) %
let entry @ &(ref s, _) = &self.entries[phf_shared::displace(f1, f2, d1, d2) %
self.entries.len()];
if check(s) {
Some(entry)
Expand Down Expand Up @@ -426,9 +406,9 @@ impl<'a, K: Hash+Eq, V> Map<K, V> for PhfOrderedMap<K, V> {

impl<K: Hash+Eq, V> PhfOrderedMap<K, V> {
fn find_entry<'a>(&'a self, key: &K) -> Option<&'a (K, V)> {
let (g, f1, f2) = hash(key, self.k1, self.k2);
let (g, f1, f2) = phf_shared::hash(key, self.k1, self.k2);
let (d1, d2) = self.disps[g % self.disps.len()];
let idx = self.idxs[displace(f1, f2, d1, d2) % self.idxs.len()];
let idx = self.idxs[phf_shared::displace(f1, f2, d1, d2) % self.idxs.len()];
let entry @ &(ref s, _) = &self.entries[idx];

if s == key {
Expand Down
4 changes: 0 additions & 4 deletions phf_mac/Cargo.toml
Expand Up @@ -9,7 +9,3 @@ version = "0.0.0"
name = "phf_mac"
path = "src/lib.rs"
plugin = true

[dependencies.phf]

path = "../phf"
24 changes: 13 additions & 11 deletions phf_mac/src/lib.rs
Expand Up @@ -9,13 +9,12 @@
extern crate rand;
extern crate syntax;
extern crate time;
extern crate phf;
extern crate rustc;

use std::collections::HashMap;
use std::gc::{Gc, GC};
use std::hash;
use std::hash::{Hash};
use std::hash::Hash;
use std::os;
use std::rc::Rc;
use syntax::ast;
Expand All @@ -31,6 +30,9 @@ use syntax::print::pprust;
use rand::{Rng, SeedableRng, XorShiftRng};
use rustc::plugin::Registry;

#[path="../../phf_shared/mod.rs"]
mod phf_shared;

static DEFAULT_LAMBDA: uint = 5;

static FIXED_SEED: [u32, ..4] = [3141592653, 589793238, 462643383, 2795028841];
Expand Down Expand Up @@ -188,10 +190,10 @@ fn parse_map(cx: &mut ExtCtxt, tts: &[TokenTree]) -> Option<Vec<Entry>> {
}
}

if entries.len() > phf::MAX_SIZE {
if entries.len() > phf_shared::MAX_SIZE {
cx.span_err(parser.span,
format!("maps with more than {} entries are not supported",
phf::MAX_SIZE).as_slice());
phf_shared::MAX_SIZE).as_slice());
return None;
}

Expand Down Expand Up @@ -228,10 +230,10 @@ fn parse_set(cx: &mut ExtCtxt, tts: &[TokenTree]) -> Option<Vec<Entry>> {
}
}

if entries.len() > phf::MAX_SIZE {
if entries.len() > phf_shared::MAX_SIZE {
cx.span_err(parser.span,
format!("maps with more than {} entries are not supported",
phf::MAX_SIZE).as_slice());
phf_shared::MAX_SIZE).as_slice());
return None;
}

Expand Down Expand Up @@ -336,7 +338,7 @@ fn try_generate_hash(entries: &[Entry], rng: &mut XorShiftRng)
let k2 = rng.gen();

let hashes: Vec<Hashes> = entries.iter().map(|entry| {
let (g, f1, f2) = phf::hash(&entry.key_contents, k1, k2);
let (g, f1, f2) = phf_shared::hash(&entry.key_contents, k1, k2);
Hashes {
g: g,
f1: f1,
Expand Down Expand Up @@ -364,10 +366,10 @@ fn try_generate_hash(entries: &[Entry], rng: &mut XorShiftRng)
'disps: for d2 in range(0, table_len) {
try_map.clear();
for &key in bucket.keys.iter() {
let idx = phf::displace(hashes.get(key).f1,
hashes.get(key).f2,
d1,
d2) % table_len;
let idx = phf_shared::displace(hashes.get(key).f1,
hashes.get(key).f2,
d1,
d2) % table_len;
if map.get(idx).is_some() || try_map.find(&idx).is_some() {
continue 'disps;
}
Expand Down
19 changes: 19 additions & 0 deletions phf_shared/mod.rs
@@ -0,0 +1,19 @@
use std::hash::{Hash, Hasher};
use std::hash::sip::SipHasher;

static LOG_MAX_SIZE: uint = 21;

pub static MAX_SIZE: uint = 1 << LOG_MAX_SIZE;

pub fn hash<T: Hash>(s: &T, k1: u64, k2: u64) -> (uint, uint, uint) {
let hash = SipHasher::new_with_keys(k1, k2).hash(s);
let mask = (MAX_SIZE - 1) as u64;

((hash & mask) as uint,
((hash >> LOG_MAX_SIZE) & mask) as uint,
((hash >> (2 * LOG_MAX_SIZE)) & mask) as uint)
}

pub fn displace(f1: uint, f2: uint, d1: uint, d2: uint) -> uint {
d2 + f1 * d1 + f2
}

0 comments on commit 19c4f8d

Please sign in to comment.