hashmap: use fnv32 as hash algo

pull/3173/head
joe-conigliaro 2019-12-21 17:59:12 +11:00 committed by Alexander Medvednikov
parent 6763a92834
commit 4dc4f12ccd
1 changed files with 38 additions and 7 deletions

View File

@ -33,7 +33,17 @@ const (
max_cap = 2<<20 max_cap = 2<<20
) )
fn new_hashmap(planned_nr_items int) hashmap { const(
fnv64_prime = 1099511628211
fnv64_offset_basis = 14695981039346656037
)
const(
fnv32_offset_basis = u32(2166136261)
fnv32_prime = u32(16777619)
)
pub fn new_hashmap(planned_nr_items int) hashmap {
mut cap := planned_nr_items * 5 mut cap := planned_nr_items * 5
if cap < min_cap { if cap < min_cap {
cap = min_cap cap = min_cap
@ -48,9 +58,10 @@ fn new_hashmap(planned_nr_items int) hashmap {
} }
} }
fn (m mut hashmap) set(key string, val int) { pub fn (m mut hashmap) set(key string, val int) {
mut hash := int(b_fabs(key.hash())) // mut hash := int(b_fabs(key.hash()))
idx := hash % m.cap // idx := hash % m.cap
idx := int(fnv1a32(key) % m.cap)
if m.table[idx].key.len != 0 { if m.table[idx].key.len != 0 {
// println('\nset() idx=$idx key="$key" hash="$hash" val=$val') // println('\nset() idx=$idx key="$key" hash="$hash" val=$val')
m.nr_collisions++ m.nr_collisions++
@ -68,9 +79,10 @@ fn (m mut hashmap) set(key string, val int) {
} }
} }
fn (m mut hashmap) get(key string) int { pub fn (m mut hashmap) get(key string) int {
hash := int(b_fabs(key.hash())) // mut hash := int(b_fabs(key.hash()))
idx := hash % m.cap // idx := hash % m.cap
idx := int(fnv1a32(key) % m.cap)
mut e := &m.table[idx] mut e := &m.table[idx]
for e.next != 0 { for e.next != 0 {
// todo unsafe { // todo unsafe {
@ -87,3 +99,22 @@ fn b_fabs(v int) f64 {
return if v < 0 { -v } else { v } return if v < 0 { -v } else { v }
} }
// inline functions here for speed
// rather than full impl in vlib
[inline]
fn fnv1a32(data string) u32 {
mut hash := fnv32_offset_basis
for i := 0; i < data.len; i++ {
hash = (hash ^ u32(data[i])) * fnv32_prime
}
return hash
}
[inline]
fn fnv1a64(data string) u64 {
mut hash := fnv64_offset_basis
for i := 0; i < data.len; i++ {
hash = (hash ^ u64(data[i])) * fnv64_prime
}
return hash
}