Return hash_resize{} from hash_alloc{}
This commit is contained in:
parent
d54621b5dd
commit
64f2a10fbb
@ -28,9 +28,13 @@ def hash_val{x:u32 & hasarch{'SSE4.2'}} = {
|
||||
# Allocate and initialize resizing hash table
|
||||
# Initial size sz+ext and maximum size msz+ext
|
||||
# One region for each type in Ts initialized with value from v0s
|
||||
def hash_alloc{sz, msz, ext, Ts, v0s} = {
|
||||
def hash_alloc{logsz, msz, ext, Ts, v0s} = {
|
||||
def ws = each{width,Ts}
|
||||
each{assert, slice{ws,0,-1} >= slice{ws,1}} # Doesn't do alignment
|
||||
# Variables updated on resize
|
||||
sz := usz~~1 << logsz
|
||||
sh := tupsel{0,ws} - logsz
|
||||
|
||||
def add{}=0; def add{a,...r} = a+add{...r}
|
||||
halloc := talloc{u8, (msz+ext)*add{...ws/8}}
|
||||
szo := msz-sz # Beginning of allocation to initial table
|
||||
@ -40,25 +44,25 @@ def hash_alloc{sz, msz, ext, Ts, v0s} = {
|
||||
def pl{{...R, T}} = { def ps=pl{R}; tup{...ps, *T~~pe{ps}+szo} }
|
||||
ptrs := pl{Ts}
|
||||
each{memset{., ., sze}, ptrs, v0s}
|
||||
tup{ptrs, {}=>tfree{halloc}}
|
||||
}
|
||||
|
||||
def hash_resize{hash,vals, x0,sh,sz,ext,cc, m} = {
|
||||
dif := sz*((1<<m)-1)
|
||||
sh -= m; sz <<= m
|
||||
hash -= dif
|
||||
j:usz = 0
|
||||
cc = 0
|
||||
memset{hash, x0, dif}
|
||||
each{{val} => { val -= dif; memset{val, 0, dif} }, vals}
|
||||
@for (j from dif to sz + ext) {
|
||||
h := hash->j
|
||||
if (h != x0) {
|
||||
hash <-{j} x0
|
||||
k0 := h>>sh; k := k0; while (hash->k!=x0) ++k
|
||||
cc += cast_i{usz, k-k0}
|
||||
hash <-{k} h
|
||||
each{{val} => { v := val->j; val <-{j} 0; val <-{k} v }, vals}
|
||||
def hash_resize{cc, m} = {
|
||||
dif := sz*((1<<m)-1)
|
||||
sh -= m; sz <<= m
|
||||
j:usz = 0
|
||||
cc = 0
|
||||
each{{p,v} => { p -= dif; memset{p, v, dif} }, ptrs, v0s}
|
||||
def {hash, ...vals} = ptrs; def {h0, ...v0r} = v0s
|
||||
@for (j from dif to sz + ext) {
|
||||
h := hash->j
|
||||
if (h != h0) {
|
||||
hash <-{j} h0
|
||||
k0 := h>>sh; k := k0; while (hash->k!=h0) ++k
|
||||
cc += cast_i{usz, k-k0}
|
||||
hash <-{k} h
|
||||
each{{p,v0} => { v := p->j; p <-{j} v0; p <-{k} v }, vals, v0r}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tup{ptrs, sz, sh, hash_resize, {}=>tfree{halloc}}
|
||||
}
|
||||
|
||||
@ -347,10 +347,11 @@ fn hashtab{T, name}(rp:*rty{name}, ip:*T, m:usz, fp:*T, n:usz) = {
|
||||
def stop = m
|
||||
|
||||
log := clzc{m}
|
||||
# Max size
|
||||
msl := clzc{m} + 2
|
||||
sh := wt - tern{msl<14, msl, 12+(msl&1)} # Shift to fit to table
|
||||
sz := usz~~1 << (wt - sh) # Initial size
|
||||
msz := usz~~1 << msl # Max sz
|
||||
msz := usz~~1 << msl
|
||||
# Starting log-size
|
||||
sl := msl; if (msl>=14) sl = 12+(msl&1)
|
||||
b:usz = 64 # Block size
|
||||
|
||||
# Filling e slots past the end requires e*(e+1)/2 collisions, so
|
||||
@ -358,8 +359,8 @@ fn hashtab{T, name}(rp:*rty{name}, ip:*T, m:usz, fp:*T, n:usz) = {
|
||||
ext := tern{m<=b, m, b + (usz~~1 << (log/2 + 1))}
|
||||
maxh := T~~maxvalue{T}
|
||||
def aux = prim!='∊'
|
||||
def {tabs, hash_free} = hash_alloc{
|
||||
sz, msz, ext, tup{T, ...aux**u32}, tup{maxh, ...aux**0}
|
||||
def {tabs, sz, sh, hash_resize, hash_free} = hash_alloc{
|
||||
sl, msz, ext, tup{T, ...aux**u32}, tup{maxh, ...aux**0}
|
||||
}
|
||||
def {hash,...vals} = tabs
|
||||
|
||||
@ -396,7 +397,7 @@ fn hashtab{T, name}(rp:*rty{name}, ip:*T, m:usz, fp:*T, n:usz) = {
|
||||
# Check collision counter and possibly resize (needs tuning)
|
||||
if (cc >= stop and sz == msz) goto{abort}
|
||||
if (16*cc >= stop and sz < msz) {
|
||||
hash_resize{hash,vals, maxh,sh,sz,ext,cc, 2} # Resize hash, factor of 4
|
||||
hash_resize{cc, 2} # Factor of 4
|
||||
if (cc >= stop) goto{abort}
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,12 +16,23 @@ fn selfhashtab{T, name}(rp:*rty{name}, xp:*T, n:usz) = {
|
||||
def {res0,stop} = if (prim=='∊') tup{1,n>>has_radix} else tup{0,2*n}
|
||||
|
||||
log := clzc{n}
|
||||
# Max size
|
||||
msl := clzc{n+n/2} + 1; if (has_radix and msl>20) msl=20
|
||||
sh := wt - tern{msl<14, msl, 12+(msl&1)} # Shift to fit to table
|
||||
sz := usz~~1 << (wt - sh) # Initial size
|
||||
msz := usz~~1 << msl # Max sz
|
||||
msz := usz~~1 << msl
|
||||
# Starting log-size
|
||||
sl := msl; if (msl>=14) sl = 12+(msl&1)
|
||||
b:usz = 64 # Block size
|
||||
|
||||
# Filling e slots past the end requires e*(e+1)/2 collisions, so
|
||||
# n entries with <2 each can fill <sqrt(4*n)
|
||||
ext := tern{n<=b, n, b + (usz~~1 << (log/2 + 1))}
|
||||
x0 := hash_val{xp->0}
|
||||
rp <-{0} res0
|
||||
def aux = prim!='∊'
|
||||
def {{hash,...vals}, sz, sh, hash_resize, hash_free} = hash_alloc{
|
||||
sl, msz, ext, tup{T, ...aux**u32}, tup{x0, ...aux**0}
|
||||
}
|
||||
|
||||
# Resize or abort if more than 1/2^thresh collisions/element
|
||||
def {set_thresh, div_thresh} = {
|
||||
t:usz = 0 # Shift amount
|
||||
@ -40,16 +51,6 @@ fn selfhashtab{T, name}(rp:*rty{name}, xp:*T, n:usz) = {
|
||||
}
|
||||
set_thresh{}
|
||||
|
||||
# Filling e slots past the end requires e*(e+1)/2 collisions, so
|
||||
# n entries with <2 each can fill <sqrt(4*n)
|
||||
ext := tern{n<=b, n, b + (usz~~1 << (log/2 + 1))}
|
||||
x0 := hash_val{xp->0}
|
||||
rp <-{0} res0
|
||||
def aux = prim!='∊'
|
||||
def {{hash,...vals}, hash_free} = hash_alloc{
|
||||
sz, msz, ext, tup{T, ...aux**u32}, tup{x0, ...aux**0}
|
||||
}
|
||||
|
||||
def {output, write_res} = match (prim) {
|
||||
{('∊')} => tup{{b}=>b, {j,h,k,x0} => { hash<-{j}h; k!=h }}
|
||||
{('⊒')} => {
|
||||
@ -91,7 +92,7 @@ fn selfhashtab{T, name}(rp:*rty{name}, xp:*T, n:usz) = {
|
||||
if (has_radix and i < n/2 and sz >= 1<<18) goto{break}
|
||||
# Avoid resizing if close to the end
|
||||
if (cc>=stop or p64{n-i}*dc >= (p64{i}*p64{n+i})>>(5+log-(wt-sh))) {
|
||||
hash_resize{hash,vals, x0,sh,sz,ext,cc, 2} # Resize hash, factor of 4
|
||||
hash_resize{cc, 2} # Factor of 4
|
||||
if (cc >= stop) goto{break}
|
||||
set_thresh{}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user