Fixes for 64-bit usz

This commit is contained in:
Marshall Lochbaum 2023-11-13 08:24:51 -05:00
parent 4fb6ce602f
commit c94d51dcaf
4 changed files with 20 additions and 17 deletions

View File

@ -331,7 +331,7 @@ B indexOf_c2(B t, B w, B x) {
return r; return r;
} }
#if SINGELI #if SINGELI
if (we==xe && (we==el_i32 || (we==el_f64 && (split || canCompare64_norm2(&w,wia,&x,xia))))) { if (we==xe && wia<=INT32_MAX && (we==el_i32 || (we==el_f64 && (split || canCompare64_norm2(&w,wia,&x,xia))))) {
i32* rp; B r = m_i32arrc(&rp, x); i32* rp; B r = m_i32arrc(&rp, x);
if (si_indexOf_c2_hash[we-el_i32](rp, tyany_ptr(w), wia, tyany_ptr(x), xia)) { if (si_indexOf_c2_hash[we-el_i32](rp, tyany_ptr(w), wia, tyany_ptr(x), xia)) {
decG(w); decG(x); return reduceI32Width(r, wia); decG(w); decG(x); return reduceI32Width(r, wia);
@ -508,8 +508,8 @@ B count_c2(B t, B w, B x) {
goto el8or16; goto el8or16;
} else { } else {
#if SINGELI #if SINGELI
if (we==xe && (we==el_i32 || (we==el_f64 && (split || canCompare64_norm2(&w,wia,&x,xia)))) && if (we==xe && wia<=INT32_MAX && (we==el_i32 || (we==el_f64 && (split || canCompare64_norm2(&w,wia,&x,xia)))) &&
si_count_c2_hash[we-el_i32](rp, tyany_ptr(w), wia, tyany_ptr(x), xia, wnext)) { si_count_c2_hash[we-el_i32](rp, tyany_ptr(w), wia, tyany_ptr(x), xia, (u32*)wnext)) {
goto dec_nwx; goto dec_nwx;
} }
#endif #endif

View File

@ -76,7 +76,7 @@ def hash_alloc{logsz, msz, ext, Ts, v0s, has_radix, ordered} = {
k0 := h>>sh k0 := h>>sh
if (ordered) { k = max{k0, k+1} } # k0 can't be less than k if (ordered) { k = max{k0, k+1} } # k0 can't be less than k
else { k = k0; while (hash->k!=h0) ++k } else { k = k0; while (hash->k!=h0) ++k }
cc += cast_i{usz, k-k0} cc += cast_i{ux, k-k0}
hash <-{k} h hash <-{k} h
def move{p,v0} = { def move{p,v0} = {
v := p->j; if (not same{v0,'any'}) p <-{j} v0; p <-{k} v v := p->j; if (not same{v0,'any'}) p <-{j} v0; p <-{k} v

View File

@ -337,9 +337,11 @@ oper &- ({v:T,m} => v & -promote{T,m}) infix left 35
def rty{name} = if (to_prim{name}=='∊') i8 else i32 def rty{name} = if (to_prim{name}=='∊') i8 else i32
def ity{name} = (to_prim{name}=='⊒')**(*u32) def ity{name} = (to_prim{name}=='⊒')**(*u32)
fn hashtab{T, name}(rp:*rty{name}, iv:*void, m:usz, fv:*void, n:usz, links:ity{name}) = { fn hashtab{T, name}(rp:*rty{name}, iv:*void, mi:usz, fv:*void, ni:usz, links:ity{name}) = {
def wt = width{T}
def prim = to_prim{name} def prim = to_prim{name}
def U = if (prim=='∊') usz else u32
m := cast_i{U,mi}; n := cast_i{U,ni}
def wt = width{T}
ip := *T~~iv; fp := *T~~fv ip := *T~~iv; fp := *T~~fv
def swap_sides{} = each{{a,b}=>{t:=a; a=b; b=t}, tup{ip,m}, tup{fp,n}} def swap_sides{} = each{{a,b}=>{t:=a; a=b; b=t}, tup{ip,m}, tup{fp,n}}
swap:u1 = n+(1024*(prim!='⊒')) < (if (prim!='∊') m else m-m/4) swap:u1 = n+(1024*(prim!='⊒')) < (if (prim!='∊') m else m-m/4)
@ -351,12 +353,12 @@ fn hashtab{T, name}(rp:*rty{name}, iv:*void, m:usz, fv:*void, n:usz, links:ity{n
msz := usz~~1 << msl msz := usz~~1 << msl
# Starting log-size (try_vec_memb requires size>4) # Starting log-size (try_vec_memb requires size>4)
sl := msl; if (msl>=14) sl = 12+(msl&1) sl := msl; if (msl>=14) sl = 12+(msl&1)
b:usz = 64 # Block size b:U = 64 # Block size
# Filling e slots past the end requires e*(e+1)/2 collisions, so # Filling e slots past the end requires e*(e+1)/2 collisions, so
# m entries with <2 each can fill <sqrt(4*m) # m entries with <2 each can fill <sqrt(4*m)
def cc_stop = 2*m def cc_stop = 2*cast_i{u64,m}
ext := tern{m<=b, max{m,usz~~4}, b + (usz~~1 << (log/2 + 1))} ext := promote{usz, tern{m<=b, max{m,U~~4}, b + (U~~1 << (log/2 + 1))}}
maxh := T~~maxvalue{T} maxh := T~~maxvalue{T}
def aux = prim!='∊' def aux = prim!='∊'
def {tabs, sz, sh, div_thresh, hash_resize, hash_free} = hash_alloc{ def {tabs, sz, sh, div_thresh, hash_resize, hash_free} = hash_alloc{
@ -365,9 +367,9 @@ fn hashtab{T, name}(rp:*rty{name}, iv:*void, m:usz, fv:*void, n:usz, links:ity{n
def {hash,...vals} = tabs def {hash,...vals} = tabs
def abort = makelabel{} def abort = makelabel{}
i:usz = 0 # Saved to determine if hashing finished i:U = 0 # Saved to determine if hashing finished
def insert_all{set_tab, set_maxh, dup, ...uniq} = { def insert_all{set_tab, set_maxh, dup, ...uniq} = {
cc:usz = 0 # Collision counter cc:u64 = 0 # Collision counter
while (i < m) { while (i < m) {
e := tern{m-i>b, i+b, m} e := tern{m-i>b, i+b, m}
while (i < e) { while (i < e) {
@ -387,7 +389,7 @@ fn hashtab{T, name}(rp:*rty{name}, iv:*void, m:usz, fv:*void, n:usz, links:ity{n
each{store{.,je-c,.}, tabs, kv} each{store{.,je-c,.}, tabs, kv}
each{=, kv, knv} each{=, kv, knv}
} while (k != maxh) } while (k != maxh)
cc += cast_i{usz, je-j0} cc += cast_i{u64, je-j0}
} }
each{{u} => { u += promote{usz,h!=maxh} }, uniq} each{{u} => { u += promote{usz,h!=maxh} }, uniq}
store{hash, j, h} store{hash, j, h}
@ -474,7 +476,7 @@ fn hashtab{T, name}(rp:*rty{name}, iv:*void, m:usz, fv:*void, n:usz, links:ity{n
def prog_lookup{swap} = { # Progressive Index-of lookup def prog_lookup{swap} = { # Progressive Index-of lookup
def rev{a,b} = if (swap) tup{b,a} else tup{a,b} def rev{a,b} = if (swap) tup{b,a} else tup{a,b}
memset{*u32~~rp, ...rev{m,n}} memset{*u32~~rp, ...rev{m,n}}
c:usz = m; def shortcut = makelabel{} c := m; def shortcut = makelabel{}
@for (fp over i to n) { @for (fp over i to n) {
h := hash_val{fp}; j := h>>sh h := hash_val{fp}; j := h>>sh
k := load{hash,j} k := load{hash,j}

View File

@ -8,7 +8,8 @@ fn selfhashtab{T, name}(rp:*rty{name}, xp:*T, n:usz) = {
def wt = width{T} def wt = width{T}
def prim = to_prim{name} def prim = to_prim{name}
def has_radix = if (prim=='⊐') 0 else wt==32 def has_radix = if (prim=='⊐') 0 else wt==32
def {res0,cc_stop} = if (prim=='∊') tup{1,n>>has_radix} else tup{0,2*n} n64 := promote{u64,n}
def {res0,cc_stop} = if (prim=='∊') tup{1,n64>>has_radix} else tup{0,2*n64}
log := clzc{n} log := clzc{n}
# Max size # Max size
@ -50,20 +51,20 @@ fn selfhashtab{T, name}(rp:*rty{name}, xp:*T, n:usz) = {
} }
def break=makelabel{} def break=makelabel{}
cc:usz = 0 # Collision counter cc:u64 = 0 # Collision counter
i:usz=1; while (1) { i:usz=1; while (1) {
e := tern{n-i>b, i+b, n} e := tern{n-i>b, i+b, n}
while (i < e) { while (i < e) {
h := hash_val{xp->i}; j0 := h>>sh; j := j0 h := hash_val{xp->i}; j0 := h>>sh; j := j0
k:=undefined{T}; while (((k=hash->j)!=h) & (k!=x0)) ++j k:=undefined{T}; while (((k=hash->j)!=h) & (k!=x0)) ++j
cc += cast_i{usz, j-j0} cc += cast_i{u64, j-j0}
rp <-{i} write_res{j,h,k,x0} rp <-{i} write_res{j,h,k,x0}
++i ++i
} }
if (i == n) goto{break} if (i == n) goto{break}
# Check collision counter and possibly resize # Check collision counter and possibly resize
def p64 = promote{u64,.} def p64 = promote{u64,.}
dc := p64{cc} - p64{div_thresh{i}} dc := cc - p64{div_thresh{i}}
if (i64~~dc >= 0) { if (i64~~dc >= 0) {
if (sz == msz) goto{break} # Abort if (sz == msz) goto{break} # Abort
if (has_radix and i < n/2 and sz >= 1<<18) goto{break} if (has_radix and i < n/2 and sz >= 1<<18) goto{break}