mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Use pow of two capacity for hash maps to allow for & (n-1) instead of % n
This commit is contained in:
@@ -232,6 +232,9 @@ __dynamic_map_reserve :: proc(using header: Map_Header, cap: int, loc := #caller
|
|||||||
}
|
}
|
||||||
context = c
|
context = c
|
||||||
|
|
||||||
|
cap := cap
|
||||||
|
cap = next_pow2(cap)
|
||||||
|
|
||||||
__dynamic_array_reserve(&m.entries, entry_size, entry_align, cap, loc)
|
__dynamic_array_reserve(&m.entries, entry_size, entry_align, cap, loc)
|
||||||
|
|
||||||
if m.entries.len*2 < len(m.hashes) {
|
if m.entries.len*2 < len(m.hashes) {
|
||||||
@@ -267,7 +270,6 @@ __dynamic_map_get :: proc(h: Map_Header, hash: Map_Hash) -> rawptr {
|
|||||||
|
|
||||||
__dynamic_map_set :: proc(h: Map_Header, hash: Map_Hash, value: rawptr, loc := #caller_location) -> ^Map_Entry_Header #no_bounds_check {
|
__dynamic_map_set :: proc(h: Map_Header, hash: Map_Hash, value: rawptr, loc := #caller_location) -> ^Map_Entry_Header #no_bounds_check {
|
||||||
index: int
|
index: int
|
||||||
// assert(value != nil)
|
|
||||||
|
|
||||||
if len(h.m.hashes) == 0 {
|
if len(h.m.hashes) == 0 {
|
||||||
__dynamic_map_reserve(h, INITIAL_MAP_CAP, loc)
|
__dynamic_map_reserve(h, INITIAL_MAP_CAP, loc)
|
||||||
@@ -300,17 +302,36 @@ __dynamic_map_set :: proc(h: Map_Header, hash: Map_Hash, value: rawptr, loc := #
|
|||||||
|
|
||||||
if __dynamic_map_full(h) {
|
if __dynamic_map_full(h) {
|
||||||
__dynamic_map_grow(h, loc)
|
__dynamic_map_grow(h, loc)
|
||||||
// index = __dynamic_map_find(h, hash).entry_index
|
|
||||||
// assert(index >= 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return __dynamic_map_get_entry(h, index)
|
return __dynamic_map_get_entry(h, index)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@(private="file")
|
||||||
|
next_pow2 :: proc "contextless" (n: int) -> int {
|
||||||
|
n := n
|
||||||
|
if n <= 0 {
|
||||||
|
return 0
|
||||||
|
} else if n <= 2 {
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
n -= 1
|
||||||
|
n |= n >> 1
|
||||||
|
n |= n >> 2
|
||||||
|
n |= n >> 4
|
||||||
|
n |= n >> 8
|
||||||
|
n |= n >> 16
|
||||||
|
when size_of(int) == 8 {
|
||||||
|
n |= n >> 32
|
||||||
|
}
|
||||||
|
n += 1
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
__dynamic_map_grow :: proc(using h: Map_Header, loc := #caller_location) {
|
__dynamic_map_grow :: proc(using h: Map_Header, loc := #caller_location) {
|
||||||
// TODO(bill): Determine an efficient growing rate
|
// TODO(bill): Determine an efficient growing rate
|
||||||
new_count := max(4*m.entries.cap + 7, INITIAL_MAP_CAP)
|
new_count := max(m.entries.cap * 2, INITIAL_MAP_CAP)
|
||||||
__dynamic_map_rehash(h, new_count, loc)
|
__dynamic_map_rehash(h, new_count, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -325,8 +346,8 @@ __dynamic_map_hash_equal :: proc "contextless" (h: Map_Header, a, b: Map_Hash) -
|
|||||||
|
|
||||||
__dynamic_map_find :: proc(using h: Map_Header, hash: Map_Hash) -> Map_Find_Result #no_bounds_check {
|
__dynamic_map_find :: proc(using h: Map_Header, hash: Map_Hash) -> Map_Find_Result #no_bounds_check {
|
||||||
fr := Map_Find_Result{-1, -1, -1}
|
fr := Map_Find_Result{-1, -1, -1}
|
||||||
if n := uintptr(len(m.hashes)); n > 0 {
|
if n := uintptr(len(m.hashes)); n != 0 {
|
||||||
fr.hash_index = int(hash.hash % n)
|
fr.hash_index = int(hash.hash & (n-1))
|
||||||
fr.entry_index = m.hashes[fr.hash_index]
|
fr.entry_index = m.hashes[fr.hash_index]
|
||||||
for fr.entry_index >= 0 {
|
for fr.entry_index >= 0 {
|
||||||
entry := __dynamic_map_get_entry(h, fr.entry_index)
|
entry := __dynamic_map_get_entry(h, fr.entry_index)
|
||||||
|
|||||||
Reference in New Issue
Block a user