Use slash and comparison functions to filter •rand.Subset output faster

This commit is contained in:
Marshall Lochbaum 2022-11-01 20:25:13 -04:00
parent c6aba44a11
commit 600ee411f8
3 changed files with 29 additions and 8 deletions

View File

@ -51,7 +51,7 @@ CMP_REC(ne, ne, swapped=0;)
typedef void (*CmpAAFn)(u64*, void*, void*, u64);
typedef void (*CmpASFn)(u64*, void*, u64, u64);
#define CMPFN(A,F,S,T) A##_##F##S##_##T
#define FN_LUT(B,A,F,S) static const Cmp##S##Fn B##_##F##S[] = {CMPFN(A,F,S,u1), CMPFN(A,F,S,i8), CMPFN(A,F,S,i16), CMPFN(A,F,S,i32), CMPFN(A,F,S,f64), CMPFN(A,F,S,u8), CMPFN(A,F,S,u16), CMPFN(A,F,S,u32)}
#define FN_LUT(B,A,F,S) const Cmp##S##Fn B##_##F##S[] = {CMPFN(A,F,S,u1), CMPFN(A,F,S,i8), CMPFN(A,F,S,i16), CMPFN(A,F,S,i32), CMPFN(A,F,S,f64), CMPFN(A,F,S,u8), CMPFN(A,F,S,u16), CMPFN(A,F,S,u32)}
#if SINGELI
#include "../singeli/c/cmp.c"

View File

@ -362,6 +362,24 @@ static NOINLINE B zeroCells(B x) { // doesn't consume
return r;
}
typedef void (*CmpASFn)(u64*, void*, u64, u64);
extern const CmpASFn cmp_fns_neAS[];
void filter_ne_i32(i32* rp, i32* xp, usz len, usz sum, i32 val) {
usz b = bsp_max; TALLOC(i16, buf, b + b/16);
u64* wp = (u64*)(buf + b);
i32* rp0=rp;
CmpASFn cmp = cmp_fns_neAS[el_i32]; B c = m_i32(val);
for (usz i=0; i<len; i+=b) {
bool last = b>len-i; if (last) b=len-i;
cmp(wp, xp, c.u, b);
usz bs = last? sum-(rp-rp0) : bit_sum(wp,b);
where_block_u16(wp, (u16*)buf, b, bs);
for (usz j=0; j<bs; j++) rp[j] = xp[buf[j]];
rp+= bs; xp+= b;
}
TFREE(buf)
}
extern B take_c2(B, B, B);
static B compress(B w, B x, usz wia, u8 xl, u8 xt) {
u64* wp = bitarr_ptr(w);

View File

@ -462,6 +462,9 @@ B rand_deal_c2(B t, B w, B x) {
}
B ud_c1(B t, B x);
B slash_c1(B t, B x);
extern void filter_ne_i32(i32* dst, i32* src, usz len, usz sum, i32 val); // slash.c
B rand_subset_c2(B t, B w, B x) {
i32 wi = o2i(w);
i32 xi = o2i(x);
@ -475,7 +478,7 @@ B rand_subset_c2(B t, B w, B x) {
RAND_START;
if (wi > xi/8) {
// Bit set (as bytes)
TALLOC(u8, set, xi);
i8* set; B s = m_i8arrv(&set, xi);
bool invert = wi > xi/2;
i32 wn = invert ? xi-wi : wi;
for (i64 i = 0; i < xi; i++) set[i] = 0;
@ -484,10 +487,9 @@ B rand_subset_c2(B t, B w, B x) {
if (set[j]) j=i;
set[j] = 1;
}
i32* rp; r = m_i32arrv(&rp, wi);
if (!invert) { for (i64 i = 0; i < xi; i++) if ( set[i]) *rp++=i; }
else { for (i64 i = 0; i < xi; i++) if (!set[i]) *rp++=i; }
TFREE(set);
s = taga(cpyBitArr(s));
if (invert) s = bit_negate(s);
return slash_c1(t, s);
} else {
// Sorted "hash" set
u64 sh = 0;
@ -510,11 +512,12 @@ B rand_subset_c2(B t, B w, B x) {
}
}
i32* rp; r = m_i32arrv(&rp, wi);
for (u64 i = 0; i < sz; i++) if (hash[i]!=xi) *rp++=hash[i];
filter_ne_i32(rp, hash, sz, wi, xi);
TFREE(hash);
r = xi<=128? taga(cpyI8Arr(r)) : xi<=32768? taga(cpyI16Arr(r)) : r;
}
RAND_END;
return xi<=128? taga(cpyI8Arr(r)) : xi<=32768? taga(cpyI16Arr(r)) : r;
return r;
}
#if USE_VALGRIND