diff options
| author | gingerBill <gingerBill@users.noreply.github.com> | 2021-11-05 18:12:40 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-11-05 18:12:40 +0000 |
| commit | ee259e42298eca0e4e5d6b8681c2403c3bf7a80e (patch) | |
| tree | 7bfd15490ddc4be6fcd41b4f969df6c901d98f76 /src/string_set.cpp | |
| parent | e963fc4d6a2b8fc63f46bb57b2c727999ce39e29 (diff) | |
| parent | 36985f8da0cea59cb1912f62ae4e700983159b6a (diff) | |
Merge pull request #1273 from odin-lang/compiler-map-improvements
Compiler Map Improvements
Diffstat (limited to 'src/string_set.cpp')
| -rw-r--r-- | src/string_set.cpp | 137 |
1 files changed, 76 insertions, 61 deletions
diff --git a/src/string_set.cpp b/src/string_set.cpp index 671b2c9ff..e27145289 100644 --- a/src/string_set.cpp +++ b/src/string_set.cpp @@ -1,17 +1,11 @@ -struct StringSetFindResult { - isize hash_index; - isize entry_prev; - isize entry_index; -}; - struct StringSetEntry { - u64 hash; - isize next; - String value; + u32 hash; + MapIndex next; + String value; }; struct StringSet { - Array<isize> hashes; + Slice<MapIndex> hashes; Array<StringSetEntry> entries; }; @@ -27,31 +21,35 @@ void string_set_rehash (StringSet *s, isize new_count); gb_inline void string_set_init(StringSet *s, gbAllocator a, isize capacity) { - array_init(&s->hashes, a); - array_init(&s->entries, a); + capacity = next_pow2_isize(gb_max(16, capacity)); + + slice_init(&s->hashes, a, capacity); + array_init(&s->entries, a, 0, capacity); + for (isize i = 0; i < capacity; i++) { + s->hashes.data[i] = MAP_SENTINEL; + } } gb_inline void string_set_destroy(StringSet *s) { + slice_free(&s->hashes, s->entries.allocator); array_free(&s->entries); - array_free(&s->hashes); } -gb_internal isize string_set__add_entry(StringSet *s, StringHashKey const &key) { +gb_internal MapIndex string_set__add_entry(StringSet *s, StringHashKey const &key) { StringSetEntry e = {}; e.hash = key.hash; - e.next = -1; + e.next = MAP_SENTINEL; e.value = key.string; array_add(&s->entries, e); - return s->entries.count-1; + return cast(MapIndex)(s->entries.count-1); } -gb_internal StringSetFindResult string_set__find(StringSet *s, StringHashKey const &key) { - StringSetFindResult fr = {-1, -1, -1}; +gb_internal MapFindResult string_set__find(StringSet *s, StringHashKey const &key) { + MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; if (s->hashes.count > 0) { - // fr.hash_index = u128_to_i64(key.key % u128_from_i64(s->hashes.count)); - fr.hash_index = key.hash % s->hashes.count; + fr.hash_index = cast(MapIndex)(((u64)key.hash) % s->hashes.count); fr.entry_index = s->hashes[fr.hash_index]; - while (fr.entry_index >= 0) { + while (fr.entry_index != MAP_SENTINEL) { auto const &entry = s->entries[fr.entry_index]; if (entry.hash == key.hash && entry.value == key.string) { return fr; @@ -62,68 +60,83 @@ gb_internal StringSetFindResult string_set__find(StringSet *s, StringHashKey con } return fr; } +gb_internal MapFindResult string_set__find_from_entry(StringSet *s, StringSetEntry *e) { + MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; + if (s->hashes.count > 0) { + fr.hash_index = cast(MapIndex)(e->hash % s->hashes.count); + fr.entry_index = s->hashes[fr.hash_index]; + while (fr.entry_index != MAP_SENTINEL) { + if (&s->entries[fr.entry_index] == e) { + return fr; + } + fr.entry_prev = fr.entry_index; + fr.entry_index = s->entries[fr.entry_index].next; + } + } + return fr; +} + gb_internal b32 string_set__full(StringSet *s) { return 0.75f * s->hashes.count <= s->entries.count; } gb_inline void string_set_grow(StringSet *s) { - isize new_count = ARRAY_GROW_FORMULA(s->entries.count); + isize new_count = gb_max(s->hashes.count<<1, 16); string_set_rehash(s, new_count); } -void string_set_rehash(StringSet *s, isize new_count) { - isize i, j; - StringSet ns = {}; - string_set_init(&ns, s->hashes.allocator); - array_resize(&ns.hashes, new_count); - array_reserve(&ns.entries, s->entries.count); - for (i = 0; i < new_count; i++) { - ns.hashes[i] = -1; + +void string_set_reset_entries(StringSet *s) { + for (isize i = 0; i < s->hashes.count; i++) { + s->hashes.data[i] = MAP_SENTINEL; } - for (i = 0; i < s->entries.count; i++) { - StringSetEntry *e = &s->entries[i]; - StringSetFindResult fr; - if (ns.hashes.count == 0) { - string_set_grow(&ns); - } - StringHashKey key = {e->hash, e->value}; - fr = string_set__find(&ns, key); - j = string_set__add_entry(&ns, key); - if (fr.entry_prev < 0) { - ns.hashes[fr.hash_index] = j; + for (isize i = 0; i < s->entries.count; i++) { + MapFindResult fr; + StringSetEntry *e = &s->entries.data[i]; + e->next = MAP_SENTINEL; + fr = string_set__find_from_entry(s, e); + if (fr.entry_prev == MAP_SENTINEL) { + s->hashes[fr.hash_index] = cast(MapIndex)i; } else { - ns.entries[fr.entry_prev].next = j; - } - ns.entries[j].next = fr.entry_index; - ns.entries[j].value = e->value; - if (string_set__full(&ns)) { - string_set_grow(&ns); + s->entries[fr.entry_prev].next = cast(MapIndex)i; } } - string_set_destroy(s); - *s = ns; +} + +void string_set_reserve(StringSet *s, isize cap) { + array_reserve(&s->entries, cap); + if (s->entries.count*2 < s->hashes.count) { + return; + } + slice_resize(&s->hashes, s->entries.allocator, cap*2); + string_set_reset_entries(s); +} + + +void string_set_rehash(StringSet *s, isize new_count) { + string_set_reserve(s, new_count); } gb_inline bool string_set_exists(StringSet *s, String const &str) { StringHashKey key = string_hash_string(str); isize index = string_set__find(s, key).entry_index; - return index >= 0; + return index != MAP_SENTINEL; } void string_set_add(StringSet *s, String const &str) { - isize index; - StringSetFindResult fr; + MapIndex index; + MapFindResult fr; StringHashKey key = string_hash_string(str); if (s->hashes.count == 0) { string_set_grow(s); } fr = string_set__find(s, key); - if (fr.entry_index >= 0) { + if (fr.entry_index != MAP_SENTINEL) { index = fr.entry_index; } else { index = string_set__add_entry(s, key); - if (fr.entry_prev >= 0) { + if (fr.entry_prev != MAP_SENTINEL) { s->entries[fr.entry_prev].next = index; } else { s->hashes[fr.hash_index] = index; @@ -137,9 +150,9 @@ void string_set_add(StringSet *s, String const &str) { } -void string_set__erase(StringSet *s, StringSetFindResult fr) { - StringSetFindResult last; - if (fr.entry_prev < 0) { +void string_set__erase(StringSet *s, MapFindResult fr) { + MapFindResult last; + if (fr.entry_prev == MAP_SENTINEL) { s->hashes[fr.hash_index] = s->entries[fr.entry_index].next; } else { s->entries[fr.entry_prev].next = s->entries[fr.entry_index].next; @@ -152,7 +165,7 @@ void string_set__erase(StringSet *s, StringSetFindResult fr) { *entry = s->entries[s->entries.count-1]; StringHashKey key = {entry->hash, entry->value}; last = string_set__find(s, key); - if (last.entry_prev >= 0) { + if (last.entry_prev != MAP_SENTINEL) { s->entries[last.entry_prev].next = fr.entry_index; } else { s->hashes[last.hash_index] = fr.entry_index; @@ -161,13 +174,15 @@ void string_set__erase(StringSet *s, StringSetFindResult fr) { void string_set_remove(StringSet *s, String const &str) { StringHashKey key = string_hash_string(str); - StringSetFindResult fr = string_set__find(s, key); - if (fr.entry_index >= 0) { + MapFindResult fr = string_set__find(s, key); + if (fr.entry_index != MAP_SENTINEL) { string_set__erase(s, fr); } } gb_inline void string_set_clear(StringSet *s) { - array_clear(&s->hashes); array_clear(&s->entries); + for_array(i, s->hashes) { + s->hashes.data[i] = MAP_SENTINEL; + } } |