diff --git a/src/builtins/selfsearch.c b/src/builtins/selfsearch.c index d13a1520..6e2e0297 100644 --- a/src/builtins/selfsearch.c +++ b/src/builtins/selfsearch.c @@ -110,17 +110,17 @@ B memberOf_c1(B t, B x) { u32* xp = (u32*)xv; i8* rp; B r = m_i8arrv(&rp, n); usz log = 64 - CLZ(n); - usz msl = (64 - CLZ(n+n/2)) + 1; if (msl>18) msl=18; - usz sh = 32 - (msl<14? msl : 14); // Shift to fit to table + usz msl = (64 - CLZ(n+n/2)) + 1; if (msl>20) msl=20; + usz sh = 32 - (msl<14? msl : 12+(msl&1)); // Shift to fit to table usz sz = 1 << (32 - sh); // Initial size usz msz = 1 << msl; // Max sz usz b = 64; // Block size // Resize or abort if more than 1/2^thresh collisions/element - #define THRESH sz==msz? 1 : sz>=(1<<13)? 2 : 3 + #define THRESH sz==msz? 1 : sz>=(1<<15)? 3 : 5 usz thresh = THRESH; // Filling e slots past the end requires e*(e+1)/2 collisions, so - // n entries with 1/2 each can fill = e>>thresh) { - if (sz == msz) break; // Abort - // Resize hash - usz m = 1 + (sz < msz/4); - sh -= m; - usz dif = sz; sz <<= m; dif = sz-dif; + i64 dc = (i64)cc - (i>>thresh); + if (dc >= 0) { + if (sz == msz || (i < n/2 && sz >= 1<<18)) break; // Abort + // Avoid resizing if close to the end + if (cc>(5+log-(32-sh))) continue; + // Resize hash, factor of 4 + usz m = 2; + usz dif = sz*((1<>sh; while (hash[k]!=x0) k++; + u32 k0 = h>>sh, k = k0; while (hash[k]!=x0) k++; + cc += k-k0; hash[k] = h; } + if (cc >= n/2) break; thresh = THRESH; } }