os

An operating system
git clone https://erai.gay/code/os/
Log | Files | Refs | README | LICENSE

commit 3c2cd14fc90f271cecd3eab71c77dcdd9cb218f5
parent 82543c91aae01d0798fe0cff438a9e8904037eb0
Author: erai <erai@omiltem.net>
Date:   Sat, 15 Feb 2025 20:53:17 +0000

integer hash table

Diffstat:
Atable.om | 175+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 175 insertions(+), 0 deletions(-)

diff --git a/table.om b/table.om @@ -0,0 +1,175 @@ +struct tentry { + present: int; + key: int; + value: int; +} + +struct table { + a: *alloc; + table: *tentry; + load: int; + fill: int; + cap: int; +} + +func thash(x: int): int { + return x * 0x9e3779b97f4a7c15; +} + +func tcreate(a: *alloc): *table { + var t: *table; + + t = alloc(a, sizeof(*t)) as *table; + + t.a = a; + t.table = nil; + t.fill = 0; + t.cap = 0; + + return t; +} + +func trehash(t: *table, cap: int) { + var table: *tentry; + var o: *tentry; + var e: *tentry; + var len: int; + var i: int; + + table = t.table; + t.table = alloc(t.a, cap * sizeof(*table)); + + len = t.cap; + i = 0; + loop { + if i == len { + break; + } + + o = &table[i]; + + if o.present == 1 { + e = tfind(t, o.key); + e.present = 1; + e.key = o.key; + e.value = o.value; + } + + i = i + 1; + } + + free(t.a, table as *byte); + t.load = t.fill; + t.cap = cap; +} + +func tfind(t: *table, x: int): *tentry { + var e: *tentry; + var mask: int; + var h: int; + + h = thash(x) & mask; + loop { + e = &t.table[h]; + + if e.present == 0 || e.key == x { + return e; + } + + h = (h * 5 + 1) & mask; + } +} + +func tget(t: *table, x: int, ok: *int): int { + var e: *tentry; + + if t.fill == 0 { + if ok { + *ok = 0; + } + + return 0; + } + + e = tfind(t, x); + + if e.present != 1 { + if ok { + *ok = 0; + } + + return 0; + } + + if ok { + *ok = 1; + } + + return e.value; +} + +func tset(t: *table, x: int, y: int) { + var e: *tentry; + + if t.cap == 0 { + t.cap = 16; + t.table = alloc(t.a, t.cap * sizeof(*t.table)); + } + + e = tfind(t, x); + + if e.present != 1 { + t.fill = t.fill + 1; + e.present = 1; + } + + if e.present == 0 { + t.load = t.load + 1; + } + + e.value = y; + + if t.load * 5 >= t.cap * 4 { + if t.fill * 5 >= t.cap * 4 { + trehash(t, t.cap * 2); + } else { + trehash(t, t.cap); + } + } +} + +func tdel(t: *table, x: int) { + var e: *tentry; + + if t.fill == 0 { + return; + } + + e = tfind(t, x); + + if e.present != 1 { + return; + } + + t.fill = t.fill - 1; + e.present = 2; + + if t.fill > 16 && t.fill * 3 < t.cap { + trehash(t, t.cap / 2); + } +} + +func tclear(t: *table) { + free(t.a, t.table as *byte); + t.table = nil; + t.fill = 0; + t.cap = 0; +} + +func tfree(t: *table) { + if t.table { + free(t.a, t.table as *byte); + } + + free(t.a, t as *byte); +}