From b782693d158402e18a15ee3e86ea05fc0f8abd8e Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Fri, 10 Nov 2023 08:22:52 -0500 Subject: [PATCH] =?UTF-8?q?Insert=20maxh=20to=20a=20special=20end=20bucket?= =?UTF-8?q?=20for=20=E2=8A=92=20and=20reverse=20=E2=8A=90=20(fixes=20?= =?UTF-8?q?=E2=8A=92=20maxh=20bugs)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/singeli/src/search.singeli | 77 +++++++++++++++++----------------- 1 file changed, 39 insertions(+), 38 deletions(-) diff --git a/src/singeli/src/search.singeli b/src/singeli/src/search.singeli index 61579c49..beca3e04 100644 --- a/src/singeli/src/search.singeli +++ b/src/singeli/src/search.singeli @@ -360,7 +360,7 @@ fn hashtab{T, name}(rp:*rty{name}, iv:*void, m:usz, fv:*void, n:usz, links:ity{n maxh := T~~maxvalue{T} def aux = prim!='∊' def {tabs, sz, sh, hash_resize, hash_free} = hash_alloc{ - sl, msz, ext, tup{T, ...aux**u32}, tup{maxh, ...aux**(if (prim=='⊐') 'any' else 0)} + sl, msz, ext, tup{T, ...aux**u32}, tup{maxh, ...aux**'any'} } def {hash,...vals} = tabs @@ -374,7 +374,7 @@ fn hashtab{T, name}(rp:*rty{name}, iv:*void, m:usz, fv:*void, n:usz, links:ity{n while (i < e) { def ii = if (prim!='⊒') i else m-i-1 h := hash_val{load{ip,ii}}; j := h>>sh - set_maxh{h==maxh, i} + set_maxh{h==maxh, i, j} kv := each{load{.,j}, tabs}; def {k,...kr} = kv # Robin Hood insertion j0 := j; je := j # Save value; end of chain (insert at j) @@ -392,7 +392,7 @@ fn hashtab{T, name}(rp:*rty{name}, iv:*void, m:usz, fv:*void, n:usz, links:ity{n } each{{u} => { u += promote{usz,h!=maxh} }, uniq} store{hash, j, h} - set_tab{j, je, kr} + set_tab{j, h} ++i } if (i == m) goto{insert_finish} @@ -405,6 +405,15 @@ fn hashtab{T, name}(rp:*rty{name}, iv:*void, m:usz, fv:*void, n:usz, links:ity{n } setlabel{insert_finish} } + def get_end{} = { + end := maxh>>sh + while (load{hash,end}!=maxh) ++end + end + } + def sequester_maxh{j, found} = { j += cast_i{T, ext &- found} } + def unsequester_maxh{tab} = { + store{tab, get_end{}, load{tab, maxh>>sh + cast_i{T,ext}}} + } def hash_remove{j,h} = { do { @@ -469,11 +478,13 @@ fn hashtab{T, name}(rp:*rty{name}, iv:*void, m:usz, fv:*void, n:usz, links:ity{n if (k==h) { def {inds} = vals; def {link} = links ti := load{inds, j} - 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 hash_remove{j,h} + if (ti > 0) { + store{rp, ...rev{i, m-ti}} + --c; if (c==0) goto{shortcut} + ti = load{link, ti} + if (ti > 0 or h==maxh) store{inds, j, ti} + else hash_remove{j,h} + } } } } @@ -494,8 +505,8 @@ fn hashtab{T, name}(rp:*rty{name}, iv:*void, m:usz, fv:*void, n:usz, links:ity{n uniq:usz = 0 # Uniques inserted def dup = makelabel{} insert_all{ - {j,je,kr} => setlabel{dup}, - {found, i} => has_maxh |= found, + {j, h} => setlabel{dup}, + {found, i, j} => has_maxh |= found, dup, uniq } if (swap) { @@ -503,8 +514,7 @@ fn hashtab{T, name}(rp:*rty{name}, iv:*void, m:usz, fv:*void, n:usz, links:ity{n memb_remove{uniq,has_maxh} # Remove values in ip from hash } try_vec_memb{T, hash, sz, sh, maxh, has_maxh, swap, rp, fp, n, abort} - end := maxh>>sh # Clip trailing maxh if it shouldn't be in the table - while (load{hash,end}!=maxh) ++end + end := get_end{} # Clip trailing maxh if it shouldn't be in the table if (has_maxh) ++end # Don't clip lookup_all{{found, j} => promote{i8, swap ^ (found & (j>sh; while (load{hash,end}!=maxh) ++end - store{inds, end, (m-ind_maxh) &- has_maxh} + store{inds, get_end{}, (m-ind_maxh) &- has_maxh} lookup_all{{found, j} => i32~~(m - (load{inds, j} &- found))} } else { # swap # After insert_all, position i in rp contains: # - ≠𝕨, if i is the first occurrence of its value in 𝕩, or # - j-≠𝕩, where j>sh; while (load{hash,end}!=maxh) ++end - store{inds, end, ind_maxh} - } + if (has_maxh) { ++uniq; unsequester_maxh{inds} } ind_rev_lookup{uniq, has_maxh} # Propagate to later occurrences @for (r in rp over i to n) r = load{rp, min{i, u32~~r+n}} @@ -566,18 +567,18 @@ fn hashtab{T, name}(rp:*rty{name}, iv:*void, m:usz, fv:*void, n:usz, links:ity{n {('⊒'), inds, link} => { store{link,0,0} + store{inds, maxh>>sh + cast_i{T,ext}, 0} def dup = makelabel{} - def set{j,je,{kr}} = { - # maxh entry either stores 0 or is the last entry and stores an - # index, so this preserves all values - ++je; store{inds, je, kr|load{inds,je}} - store{inds, j, 0} + def set{j, h} = { + store{inds, j, load{inds,j} &- (h==maxh)} setlabel{dup} i1 := i+1 store{link, i1, load{inds,j}} store{inds, j, i1} } - insert_all{set, {found,i}=>{}, dup} + def set_maxh{found, i, j} = sequester_maxh{j, found} + insert_all{set, set_maxh, dup} + unsequester_maxh{inds} if (not swap) prog_lookup{0} else prog_lookup{1} } }