Reverse Member-of hash lookup

This commit is contained in:
Marshall Lochbaum 2023-11-07 22:06:34 -05:00
parent 8a2190b092
commit c75fdbc277
2 changed files with 34 additions and 20 deletions

View File

@ -370,7 +370,7 @@ B memberOf_c2(B t, B w, B x) {
}
CHECK_CHRS_ELSE { tyEls: // Both numbers
if (xia>32 && wia<=(xe<=el_i8?1:6)) {
if (xia>32 && wia<=(xe<=el_i8?1:xe==el_i32?4:6)) {
SGetU(w);
i8* rp; r = m_i8arrc(&rp, w);
for (usz i=0; i<wia; i++) rp[i] = indexOfOne(x, GetU(w,i)) < xia;

View File

@ -341,10 +341,9 @@ fn hashtab{T, name}(rp:*rty{name}, iv:*void, m:usz, fv:*void, n:usz, links:ity{n
def wt = width{T}
def prim = to_prim{name}
ip := *T~~iv; fp := *T~~fv
def swap_sides{} = each{{a,b}=>{t:=a; a=b; b=t}, tup{ip,m}, tup{fp,n}}
swap:u1 = 0
if (prim=='⊒' and (swap = n < m)) {
each{{a,b}=>{t:=a; a=b; b=t}, tup{ip,m}, tup{fp,n}}
}
if ((prim=='⊒' or prim=='∊') and (swap = n < m)) swap_sides{}
def stop = m
log := clzc{m}
@ -372,11 +371,24 @@ fn hashtab{T, name}(rp:*rty{name}, iv:*void, m:usz, fv:*void, n:usz, links:ity{n
def setm{found, i} = has_maxh |= found
end := maxh>>sh # Clip trailing maxh if it shouldn't be in the table
def usem{} = {
try_vec_memb{T, hash, sz+ext, sh, maxh, has_maxh, rp, fp, n, abort}
if (swap) {
swap_sides{}; i=m # i==m return value is kind of dumb
@for (ip over m) { # Remove values in ip from hash
h := hash_val{ip}; j := h>>sh
if (h == maxh) { has_maxh = 0 } else {
k := load{hash,j}
if (k <= h) {
while (k < h) { ++j; k = load{hash,j} }
if (k==h) hash_remove{j,h}
}
}
}
}
try_vec_memb{T, hash, sz+ext, sh, maxh, has_maxh, swap, rp, fp, n, abort}
if (has_maxh) { while (load{hash,end}!=maxh) ++end }
else end += promote{T,ext} # Unreachable
}
def get{found, j} = promote{i8, found & (j<end)}
def get{found, j} = promote{i8, swap ^ (found & (j<end))}
tup{set, setm, usem, get}
}
{('⊐')} => {
@ -454,6 +466,16 @@ fn hashtab{T, name}(rp:*rty{name}, iv:*void, m:usz, fv:*void, n:usz, links:ity{n
}
}
def hash_remove{j,h} = {
do {
jp:=j; ++j
h=load{hash,j}
if (h>>sh == j) h = maxh
store{hash, jp, h}
each{{t} => store{t, jp, load{t,j}}, vals}
} while (h!=maxh)
}
setlabel{lookup}
fixup{}
def prog_lookup{swap} = { # Progressive Index-of lookup
@ -471,17 +493,8 @@ fn hashtab{T, name}(rp:*rty{name}, iv:*void, m:usz, fv:*void, n:usz, links:ity{n
store{rp, ...rev{i, m-ti}}
c -= promote{usz,ti>0}; if (c==0) goto{shortcut}
ti = load{link, ti}
if (ti > 0) {
store{inds, j, ti}
} else {
do {
jp:=j; ++j
h=load{hash,j}
if (h>>sh == j) h = maxh
store{hash, jp, h}
store{inds, jp, load{inds,j}}
} while (h!=maxh)
}
if (ti > 0) store{inds, j, ti}
else hash_remove{j,h}
}
}
}
@ -503,7 +516,7 @@ fn hashtab{T, name}(rp:*rty{name}, iv:*void, m:usz, fv:*void, n:usz, links:ity{n
}
def try_vec_memb{..._} = {}
def try_vec_memb{T, hash, hashlen, sh, maxh, has_maxh, rp, fp, n, done
def try_vec_memb{T, hash, hashlen, sh, maxh, has_maxh, swap, rp, fp, n, done
& hasarch{'SSE4.2'} & T==u32} = {
# Hash h wants bin h>>sh, so the offset for h in slot i is (in infite-precision ints)
# i-h>>sh = i+((1<<sh-1)-h)>>sh = (((i+1)<<sh-1)-h)>>sh
@ -515,6 +528,7 @@ def try_vec_memb{T, hash, hashlen, sh, maxh, has_maxh, rp, fp, n, done
mv := V**0
@for (h in *V~~(hash+o) over nh) { mv=max{mv, io-min{h,io}}; io+=id }
max_off := vfold{max, mv} >> sh
vswap := base{256,vl**1} * promote{T,swap}
def memb{test} = {
def R = i8; def rw = width{R}; def u = width{T}/rw
@ -522,9 +536,9 @@ def try_vec_memb{T, hash, hashlen, sh, maxh, has_maxh, rp, fp, n, done
@for (r in *T~~rp over i to l) {
c := V**0 # Will combine u results to avoid folding too much
@unroll (f in fp+u*i over a to u) c |= V**(1<<(rw*a)) & test{f}
r = vfold{|, c}
r = vswap ^ vfold{|, c}
}
@for (rp, fp over _ from u*l to n) rp = promote{R, homAny{test{fp}}}
@for (rp, fp over _ from u*l to n) rp = promote{R, swap ^ homAny{test{fp}}}
goto{done}
}
def try{nv} = {