From d54621b5dd1b4fac58164412ad058a3e1a222345 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Thu, 2 Nov 2023 12:00:32 -0400 Subject: [PATCH] Extend hash table to 32-bit Index-of --- src/builtins/search.c | 7 ++++ src/singeli/src/search.singeli | 59 +++++++++++++++++++++++----------- 2 files changed, 47 insertions(+), 19 deletions(-) diff --git a/src/builtins/search.c b/src/builtins/search.c index 2c7a7563..b264f4e3 100644 --- a/src/builtins/search.c +++ b/src/builtins/search.c @@ -268,6 +268,13 @@ B indexOf_c2(B t, B w, B x) { TABLE(w, x, i32, wia, i) return reduceI32Width(r, wia); } + if (we==el_i32 && xe==el_i32) { + i32* rp; B r = m_i32arrc(&rp, x); + if (indexOf_c2_hash32(rp, tyany_ptr(w), wia, tyany_ptr(x), xia)) { + decG(w); decG(x); return reduceI32Width(r, wia); + } + decG(r); + } } i32* rp; B r = m_i32arrc(&rp, x); diff --git a/src/singeli/src/search.singeli b/src/singeli/src/search.singeli index e59f3adf..b238fbf9 100644 --- a/src/singeli/src/search.singeli +++ b/src/singeli/src/search.singeli @@ -333,8 +333,17 @@ exportT{'simd_getRangeRaw', each{getRange, tup{i8,i16,i32,f64}}} # Hash tables -fn hashtab_memberOf{T}(rp:*i8, ip:*T, m:usz, fp:*T, n:usz) = { +def names = tup{'memberOf', 'count', 'indexOf'} +def prims = tup{'∊', '⊒', '⊐' } +def map{{f,...fs}, {t,...ts}, v} = if (v==f) t else map{fs, ts, v} +def to_prim = map{names, prims, .} + +oper &- ({v:T,m} => v & -promote{T,m}) infix left 35 + +def rty{name} = if (to_prim{name}=='∊') i8 else i32 +fn hashtab{T, name}(rp:*rty{name}, ip:*T, m:usz, fp:*T, n:usz) = { def wt = width{T} + def prim = to_prim{name} def stop = m log := clzc{m} @@ -348,35 +357,39 @@ fn hashtab_memberOf{T}(rp:*i8, ip:*T, m:usz, fp:*T, n:usz) = { # m entries with <2 each can fill {mi:u32=0}, vals} i:usz=0; while (1) { e := tern{m-i>b, i+b, m} while (i < e) { h := hash_val{load{ip,i}}; j := h>>sh - k := load{hash, j} + each{{mi}=>{mi|=i&-((h==maxh)&~has_maxh)}, ind_maxh} + has_maxh |= h==maxh + kv := each{load{.,j}, tabs}; def {k,..._} = kv # Robin Hood insertion - if (k == maxh) { - has_maxh |= h==maxh - store{hash, j, h} - } else if (k != h) { - j0 := j; ji := j # Save value; insertion point + if (k != maxh) { + if (k == h) goto{dup} + j0 := j; je := j # Save value; end of chain (insert at j) do { - ++j; kn := load{hash,j}; if (kn==h) goto{dup} + ++je; knv := each{load{.,je}, tabs}; def {kn,..._} = knv + if (kn == h) goto{dup} def c = promote{T, h >= k} - store{hash, j-c, k} - ji += c - k = kn + each{store{.,je-c,.}, tabs, kv} + j += c + each{=, kv, knv} } while (k != maxh) - store{hash, ji, h} - cc += cast_i{usz, j-j0} - setlabel{dup} + cc += cast_i{usz, je-j0} } + each{store{., j, .}, tabs, tup{h,...aux**(m-i)}} + setlabel{dup} ++i } if (i == m) goto{lookup} @@ -389,14 +402,22 @@ fn hashtab_memberOf{T}(rp:*i8, ip:*T, m:usz, fp:*T, n:usz) = { } setlabel{lookup} end := maxh>>sh + promote{T,ext} # Unreachable - if (has_maxh) { end=maxh>>sh; while (load{hash,end}!=maxh) ++end } + if (has_maxh) { + end=maxh>>sh; while (load{hash,end}!=maxh) ++end + each{store{.,end,.}, vals, ind_maxh} + } @for (rp, fp over n) { h := hash_val{fp}; j := h>>sh k:=undefined{T}; while ((k=load{hash,j}) < h) ++j - rp = promote{i8, (k==h) & (jeach{exp_hash{.,n},tup{u32}}, tup{'memberOf', 'indexOf'}}