2019-10-01 02:14:12 +03:00
|
|
|
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
|
|
|
|
// Use of this source code is governed by an MIT license
|
|
|
|
// that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
module builtin
|
|
|
|
|
|
|
|
/*
|
|
|
|
This is work in progress.
|
|
|
|
A very early test version of the hashmap with a fixed size.
|
|
|
|
Only works with string keys and int values for now.
|
2019-10-01 06:33:03 +03:00
|
|
|
|
|
|
|
I added this to improve performance of the V compiler,
|
|
|
|
which uses lots of O(log n) map get's. Turned out with N < 10 000
|
|
|
|
the performance gains are basically non-existent.
|
2019-10-01 02:14:12 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
import math
|
|
|
|
|
|
|
|
struct hashmap {
|
|
|
|
cap int
|
|
|
|
keys []string
|
|
|
|
table []hashmapentry
|
|
|
|
elm_size int
|
|
|
|
pub:
|
|
|
|
nr_collisions int
|
|
|
|
}
|
|
|
|
|
|
|
|
struct hashmapentry {
|
|
|
|
key string
|
|
|
|
val int
|
|
|
|
next &hashmapentry // linked list for collisions
|
|
|
|
}
|
|
|
|
|
|
|
|
const (
|
|
|
|
min_cap = 2 << 10
|
|
|
|
max_cap = 2 << 20
|
|
|
|
)
|
|
|
|
|
|
|
|
fn new_hashmap(planned_nr_items int) hashmap {
|
|
|
|
mut cap := planned_nr_items * 3
|
|
|
|
if cap < min_cap {
|
|
|
|
cap = min_cap
|
|
|
|
}
|
|
|
|
if cap > max_cap {
|
|
|
|
cap = max_cap
|
|
|
|
}
|
|
|
|
return hashmap{
|
|
|
|
cap: cap
|
|
|
|
elm_size: 4
|
2019-10-09 23:38:33 +03:00
|
|
|
table: make(cap, cap, sizeof(hashmapentry))
|
2019-10-01 02:14:12 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn (m mut hashmap) set(key string, val int) {
|
|
|
|
hash := int(math.abs(key.hash()))
|
|
|
|
idx := hash % m.cap
|
|
|
|
if m.table[idx].key.len != 0 {
|
|
|
|
//println('\nset() idx=$idx key="$key" hash="$hash" val=$val')
|
|
|
|
m.nr_collisions++
|
|
|
|
//println('collision:' + m.table[idx].key)
|
|
|
|
mut e := &m.table[idx]
|
|
|
|
for e.next != 0 {
|
|
|
|
e = e.next
|
|
|
|
}
|
|
|
|
e.next = &hashmapentry{key, val, 0}
|
|
|
|
} else {
|
|
|
|
m.table[idx] = hashmapentry{key, val, 0}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn (m mut hashmap) get(key string) int {
|
|
|
|
hash := int(math.abs(key.hash()))
|
|
|
|
idx := hash % m.cap
|
|
|
|
mut e := &m.table[idx]
|
|
|
|
for e.next != 0 { // todo unsafe {
|
|
|
|
if e.key == key {
|
|
|
|
return e.val
|
|
|
|
}
|
|
|
|
e = e.next
|
|
|
|
}
|
|
|
|
return e.val
|
|
|
|
}
|
|
|
|
|
|
|
|
|