Insert maxh to a special end bucket for ⊒ and reverse ⊐ (fixes ⊒ maxh bugs)
This commit is contained in:
parent
e1b0c53c92
commit
b782693d15
@ -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}
|
maxh := T~~maxvalue{T}
|
||||||
def aux = prim!='∊'
|
def aux = prim!='∊'
|
||||||
def {tabs, sz, sh, hash_resize, hash_free} = hash_alloc{
|
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
|
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) {
|
while (i < e) {
|
||||||
def ii = if (prim!='⊒') i else m-i-1
|
def ii = if (prim!='⊒') i else m-i-1
|
||||||
h := hash_val{load{ip,ii}}; j := h>>sh
|
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
|
kv := each{load{.,j}, tabs}; def {k,...kr} = kv
|
||||||
# Robin Hood insertion
|
# Robin Hood insertion
|
||||||
j0 := j; je := j # Save value; end of chain (insert at j)
|
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}
|
each{{u} => { u += promote{usz,h!=maxh} }, uniq}
|
||||||
store{hash, j, h}
|
store{hash, j, h}
|
||||||
set_tab{j, je, kr}
|
set_tab{j, h}
|
||||||
++i
|
++i
|
||||||
}
|
}
|
||||||
if (i == m) goto{insert_finish}
|
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}
|
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} = {
|
def hash_remove{j,h} = {
|
||||||
do {
|
do {
|
||||||
@ -469,14 +478,16 @@ fn hashtab{T, name}(rp:*rty{name}, iv:*void, m:usz, fv:*void, n:usz, links:ity{n
|
|||||||
if (k==h) {
|
if (k==h) {
|
||||||
def {inds} = vals; def {link} = links
|
def {inds} = vals; def {link} = links
|
||||||
ti := load{inds, j}
|
ti := load{inds, j}
|
||||||
|
if (ti > 0) {
|
||||||
store{rp, ...rev{i, m-ti}}
|
store{rp, ...rev{i, m-ti}}
|
||||||
c -= promote{usz,ti>0}; if (c==0) goto{shortcut}
|
--c; if (c==0) goto{shortcut}
|
||||||
ti = load{link, ti}
|
ti = load{link, ti}
|
||||||
if (ti > 0) store{inds, j, ti}
|
if (ti > 0 or h==maxh) store{inds, j, ti}
|
||||||
else hash_remove{j,h}
|
else hash_remove{j,h}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
setlabel{shortcut}
|
setlabel{shortcut}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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
|
uniq:usz = 0 # Uniques inserted
|
||||||
def dup = makelabel{}
|
def dup = makelabel{}
|
||||||
insert_all{
|
insert_all{
|
||||||
{j,je,kr} => setlabel{dup},
|
{j, h} => setlabel{dup},
|
||||||
{found, i} => has_maxh |= found,
|
{found, i, j} => has_maxh |= found,
|
||||||
dup, uniq
|
dup, uniq
|
||||||
}
|
}
|
||||||
if (swap) {
|
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
|
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}
|
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
|
end := get_end{} # Clip trailing maxh if it shouldn't be in the table
|
||||||
while (load{hash,end}!=maxh) ++end
|
|
||||||
if (has_maxh) ++end # Don't clip
|
if (has_maxh) ++end # Don't clip
|
||||||
lookup_all{{found, j} => promote{i8, swap ^ (found & (j<end))}}
|
lookup_all{{found, j} => promote{i8, swap ^ (found & (j<end))}}
|
||||||
}
|
}
|
||||||
@ -513,52 +523,43 @@ fn hashtab{T, name}(rp:*rty{name}, iv:*void, m:usz, fv:*void, n:usz, links:ity{n
|
|||||||
has_maxh:u1 = 0
|
has_maxh:u1 = 0
|
||||||
ind_maxh:u32 = 0
|
ind_maxh:u32 = 0
|
||||||
def dup = makelabel{}
|
def dup = makelabel{}
|
||||||
def set{j,je,kr} = {
|
def set{j, h} = {
|
||||||
store{inds, j, m-i} # So it can be cleared with one &- in get{}
|
store{inds, j, m-i} # So it can be cleared with one &- in get{}
|
||||||
setlabel{dup}
|
setlabel{dup}
|
||||||
}
|
}
|
||||||
def set_maxh{found, i} = {
|
def set_maxh{found, i, j} = {
|
||||||
ind_maxh |= i &- (found&~has_maxh)
|
ind_maxh |= i &- (found&~has_maxh)
|
||||||
has_maxh |= found
|
has_maxh |= found
|
||||||
}
|
}
|
||||||
insert_all{set, set_maxh, dup}
|
insert_all{set, set_maxh, dup}
|
||||||
end := maxh>>sh; while (load{hash,end}!=maxh) ++end
|
store{inds, get_end{}, (m-ind_maxh) &- has_maxh}
|
||||||
store{inds, end, (m-ind_maxh) &- has_maxh}
|
|
||||||
lookup_all{{found, j} => i32~~(m - (load{inds, j} &- found))}
|
lookup_all{{found, j} => i32~~(m - (load{inds, j} &- found))}
|
||||||
} else { # swap
|
} else { # swap
|
||||||
# After insert_all, position i in rp contains:
|
# After insert_all, position i in rp contains:
|
||||||
# - ≠𝕨, if i is the first occurrence of its value in 𝕩, or
|
# - ≠𝕨, if i is the first occurrence of its value in 𝕩, or
|
||||||
# - j-≠𝕩, where j<i is the index of the first occurrence
|
# - j-≠𝕩, where j<i is the index of the first occurrence
|
||||||
uniq:usz = 0
|
uniq:usz = 0
|
||||||
ind_maxh:usz = m
|
has_maxh:u1 = 0
|
||||||
ri:i32 = 0 # Placed in rp (should be scoped to insert_all loop body)
|
ri:i32 = 0 # Placed in rp (should be scoped to insert_all loop body)
|
||||||
def dup = makelabel{}; def skip_dup = makelabel{}
|
def dup = makelabel{}
|
||||||
def set_maxh{found, i} = {
|
def set_maxh{found, i, j} = {
|
||||||
|
sequester_maxh{j, found}
|
||||||
ri = cast_i{i32, n} # Initialize to not-found
|
ri = cast_i{i32, n} # Initialize to not-found
|
||||||
if (found) {
|
if (found & has_maxh) goto{dup}
|
||||||
if (ind_maxh==m) ind_maxh = i
|
has_maxh |= found
|
||||||
else ri = i32~~(ind_maxh - m)
|
|
||||||
goto{skip_dup}
|
|
||||||
}
|
}
|
||||||
}
|
def set{j, h} = {
|
||||||
def set{j,je,kr} = {
|
|
||||||
store{inds, j, i}
|
store{inds, j, i}
|
||||||
if (u1~~0) {
|
if (u1~~0) {
|
||||||
setlabel{dup}
|
setlabel{dup}
|
||||||
ri = i32~~(load{inds, j} - m)
|
ri = i32~~(load{inds, j} - m)
|
||||||
setlabel{skip_dup}
|
|
||||||
}
|
}
|
||||||
store{rp, i, ri}
|
store{rp, i, ri}
|
||||||
}
|
}
|
||||||
insert_all{set, set_maxh, dup, uniq}
|
insert_all{set, set_maxh, dup, uniq}
|
||||||
has_maxh := ind_maxh < m
|
|
||||||
# Lookup places correct result index at each first occurrence
|
# Lookup places correct result index at each first occurrence
|
||||||
swap_sides{}; i=m
|
swap_sides{}; i=m
|
||||||
if (has_maxh) {
|
if (has_maxh) { ++uniq; unsequester_maxh{inds} }
|
||||||
++uniq
|
|
||||||
end := maxh>>sh; while (load{hash,end}!=maxh) ++end
|
|
||||||
store{inds, end, ind_maxh}
|
|
||||||
}
|
|
||||||
ind_rev_lookup{uniq, has_maxh}
|
ind_rev_lookup{uniq, has_maxh}
|
||||||
# Propagate to later occurrences
|
# Propagate to later occurrences
|
||||||
@for (r in rp over i to n) r = load{rp, min{i, u32~~r+n}}
|
@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} => {
|
{('⊒'), inds, link} => {
|
||||||
store{link,0,0}
|
store{link,0,0}
|
||||||
|
store{inds, maxh>>sh + cast_i{T,ext}, 0}
|
||||||
def dup = makelabel{}
|
def dup = makelabel{}
|
||||||
def set{j,je,{kr}} = {
|
def set{j, h} = {
|
||||||
# maxh entry either stores 0 or is the last entry and stores an
|
store{inds, j, load{inds,j} &- (h==maxh)}
|
||||||
# index, so this preserves all values
|
|
||||||
++je; store{inds, je, kr|load{inds,je}}
|
|
||||||
store{inds, j, 0}
|
|
||||||
setlabel{dup}
|
setlabel{dup}
|
||||||
i1 := i+1
|
i1 := i+1
|
||||||
store{link, i1, load{inds,j}}
|
store{link, i1, load{inds,j}}
|
||||||
store{inds, j, i1}
|
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}
|
if (not swap) prog_lookup{0} else prog_lookup{1}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user