From 236d8dedd63b2c49996cc495ad41def335f8b2d6 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Wed, 19 Oct 2022 20:17:47 -0400 Subject: [PATCH 01/19] Move search functions to search.c --- makefile | 2 +- src/builtins/fns.c | 113 -------------------------------------- src/builtins/search.c | 125 ++++++++++++++++++++++++++++++++++++++++++ src/load.c | 2 +- src/opt/single.c | 1 + 5 files changed, 128 insertions(+), 115 deletions(-) create mode 100644 src/builtins/search.c diff --git a/makefile b/makefile index bf26179b..34d354ab 100644 --- a/makefile +++ b/makefile @@ -212,7 +212,7 @@ ${bd}/%.o: src/jit/%.c @echo $< | cut -c 5- @$(CC_INC) $@.d -o $@ -c $< -builtins: ${addprefix ${bd}/, arithm.o arithd.o cmp.o sfns.o squeeze.o select.o slash.o group.o sort.o selfsearch.o md1.o md2.o fns.o sysfn.o internal.o inverse.o} +builtins: ${addprefix ${bd}/, arithm.o arithd.o cmp.o sfns.o squeeze.o select.o slash.o group.o sort.o search.o selfsearch.o md1.o md2.o fns.o sysfn.o internal.o inverse.o} ${bd}/%.o: src/builtins/%.c @echo $< | cut -c 5- @$(CC_INC) $@.d -o $@ -c $< diff --git a/src/builtins/fns.c b/src/builtins/fns.c index a6916e2e..ccdf0d28 100644 --- a/src/builtins/fns.c +++ b/src/builtins/fns.c @@ -198,120 +198,11 @@ B fne_c2(B t, B w, B x) { } -extern B rt_indexOf; -B indexOf_c2(B t, B w, B x) { - if (!isArr(w) || RNK(w)==0) thrM("⊐: 𝕨 must have rank at least 1"); - if (RNK(w)==1) { - if (!isArr(x) || RNK(x)==0) { - usz wia = IA(w); - B el = isArr(x)? IGetU(x,0) : x; - i32 res = wia; - if (TI(w,elType)==el_i32) { - if (q_i32(el)) { - i32* wp = i32any_ptr(w); - i32 v = o2iG(el); - for (usz i = 0; i < wia; i++) { - if (wp[i] == v) { res = i; break; } - } - } - } else { - SGetU(w) - for (usz i = 0; i < wia; i++) { - if (equal(GetU(w,i), el)) { res = i; break; } - } - } - decG(w); dec(x); - i32* rp; Arr* r = m_i32arrp(&rp, 1); - arr_shAlloc(r, 0); - rp[0] = res; - return taga(r); - } else { - usz wia = IA(w); - usz xia = IA(x); - // TODO O(wia×xia) for small wia or xia - i32* rp; B r = m_i32arrc(&rp, x); - H_b2i* map = m_b2i(64); - SGetU(x) - SGetU(w) - for (usz i = 0; i < wia; i++) { - bool had; u64 p = mk_b2i(&map, GetU(w,i), &had); - if (!had) map->a[p].val = i; - } - for (usz i = 0; i < xia; i++) rp[i] = getD_b2i(map, GetU(x,i), wia); - free_b2i(map); decG(w); decG(x); - return wia<=I8_MAX? taga(cpyI8Arr(r)) : wia<=I16_MAX? taga(cpyI16Arr(r)) : r; - } - } - return c2(rt_indexOf, w, x); -} - -B enclosed_0; -B enclosed_1; -extern B rt_memberOf; -extern B eq_c2(B,B,B); -extern B or_c2(B,B,B); -B memberOf_c2(B t, B w, B x) { - if (isAtm(x) || RNK(x)!=1) goto bad; - if (isAtm(w)) goto single; - ur wr = RNK(w); - if (wr==0) { - B w0 = IGet(w, 0); - dec(w); - w = w0; - goto single; - } - if (wr==1) goto many; - goto bad; - - bad: return c2(rt_memberOf, w, x); - - B r; - single: { - usz xia = IA(x); - SGetU(x) - for (usz i = 0; i < xia; i++) if (equal(GetU(x, i), w)) { r = inc(enclosed_1); goto dec_wx; } - r = inc(enclosed_0); - dec_wx:; dec(w); - goto dec_x; - } - - - many: { - u8 we = TI(w,elType); usz wia = IA(w); - u8 xe = TI(x,elType); usz xia = IA(x); - if (xia<=16 && wia>16 && wea[p].val = i; + } + for (usz i = 0; i < xia; i++) rp[i] = getD_b2i(map, GetU(x,i), wia); + free_b2i(map); decG(w); decG(x); + return wia<=I8_MAX? taga(cpyI8Arr(r)) : wia<=I16_MAX? taga(cpyI16Arr(r)) : r; + } + } + return c2(rt_indexOf, w, x); +} + +B enclosed_0; +B enclosed_1; +extern B rt_memberOf; +extern B eq_c2(B,B,B); +extern B or_c2(B,B,B); +B memberOf_c2(B t, B w, B x) { + if (isAtm(x) || RNK(x)!=1) goto bad; + if (isAtm(w)) goto single; + ur wr = RNK(w); + if (wr==0) { + B w0 = IGet(w, 0); + dec(w); + w = w0; + goto single; + } + if (wr==1) goto many; + goto bad; + + bad: return c2(rt_memberOf, w, x); + + B r; + single: { + usz xia = IA(x); + SGetU(x) + for (usz i = 0; i < xia; i++) if (equal(GetU(x, i), w)) { r = inc(enclosed_1); goto dec_wx; } + r = inc(enclosed_0); + dec_wx:; dec(w); + goto dec_x; + } + + + many: { + u8 we = TI(w,elType); usz wia = IA(w); + u8 xe = TI(x,elType); usz xia = IA(x); + if (xia<=16 && wia>16 && we Date: Wed, 19 Oct 2022 21:09:27 -0400 Subject: [PATCH 02/19] =?UTF-8?q?Introduce=20bit=5Fhas=20and=20use=20for?= =?UTF-8?q?=20=E2=88=A7=C2=B4,=20=E2=88=A8=C2=B4,=20and=20=F0=9D=95=A8?= =?UTF-8?q?=E2=88=8Abool?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/md1.c | 8 ++++---- src/builtins/search.c | 19 ++++++++++++++----- src/core/numarr.h | 6 ++++++ 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/builtins/md1.c b/src/builtins/md1.c index 1b1e4152..0ec8e847 100644 --- a/src/builtins/md1.c +++ b/src/builtins/md1.c @@ -320,8 +320,8 @@ B fold_c1(Md1D* d, B x) { B f = d->f; u64* xp = bitarr_ptr(x); if (rtid==n_add) { B r = m_f64(bit_sum (xp, ia)); decG(x); return r; } if (rtid==n_sub) { B r = m_f64(bit_diff(xp, ia)); decG(x); return r; } - if (rtid==n_and | rtid==n_mul | rtid==n_floor) { bool r=1; for (usz i=0; i<(ia>>6); i++) if (~xp[i]){r=0;break;} if(~bitp_l1(xp,ia))r=0; decG(x); return m_i32(r); } - if (rtid==n_or | rtid==n_ceil ) { bool r=0; for (usz i=0; i<(ia>>6); i++) if ( xp[i]){r=1;break;} if( bitp_l0(xp,ia))r=1; decG(x); return m_i32(r); } + if (rtid==n_and | rtid==n_mul | rtid==n_floor) { B r = m_i32(!bit_has(xp, ia, 0)); decG(x); return r; } + if (rtid==n_or | rtid==n_ceil ) { B r = m_i32( bit_has(xp, ia, 1)); decG(x); return r; } if (rtid==n_ne) { bool r=fold_ne(xp, ia) ; decG(x); return m_i32(r); } if (rtid==n_eq) { bool r=fold_ne(xp, ia) ^ (1&~ia); decG(x); return m_i32(r); } goto base; @@ -383,8 +383,8 @@ B fold_c2(Md1D* d, B w, B x) { B f = d->f; if (rtid==n_add) { B r = m_f64(wi + bit_sum (xp, ia)); decG(x); return r; } if (rtid==n_sub) { B r = m_f64((ia&1?-wi:wi) + bit_diff(xp, ia)); decG(x); return r; } if (wi!=(wi&1)) goto base; - if (rtid==n_and | rtid==n_mul | rtid==n_floor) { bool r=wi; if ( r) { for (usz i=0; i<(ia>>6); i++) if (~xp[i]){r=0;break;} if(~bitp_l1(xp,ia))r=0; } decG(x); return m_i32(r); } - if (rtid==n_or | rtid==n_ceil ) { bool r=wi; if (!r) { for (usz i=0; i<(ia>>6); i++) if ( xp[i]){r=1;break;} if( bitp_l0(xp,ia))r=1; } decG(x); return m_i32(r); } + if (rtid==n_and | rtid==n_mul | rtid==n_floor) { B r = m_i32(wi && !bit_has(xp, ia, 0)); decG(x); return r; } + if (rtid==n_or | rtid==n_ceil ) { B r = m_i32(wi || bit_has(xp, ia, 1)); decG(x); return r; } if (rtid==n_ne) { bool r=wi^fold_ne(xp, ia) ; decG(x); return m_i32(r); } if (rtid==n_eq) { bool r=wi^fold_ne(xp, ia) ^ (1&ia); decG(x); return m_i32(r); } goto base; diff --git a/src/builtins/search.c b/src/builtins/search.c index f82c67fe..1d1d9331 100644 --- a/src/builtins/search.c +++ b/src/builtins/search.c @@ -84,14 +84,23 @@ B memberOf_c2(B t, B w, B x) { many: { u8 we = TI(w,elType); usz wia = IA(w); u8 xe = TI(x,elType); usz xia = IA(x); + if (xia == 0) { Arr* ba=allZeroes(wia); arr_shVec(ba); r=taga(ba); decG(w); goto dec_x; } + #define WEQ(V) eq_c2(m_f64(0), inc(w), V) + if (xe==el_bit) { + u64* xp = bitarr_ptr(x); + u64 x0 = 1 & xp[0]; + r = WEQ(m_usz(x0)); + if (bit_has(xp, xia, !x0)) r = or_c2(m_f64(0), r, WEQ(m_usz(!x0))); + decG(w); goto dec_x; + } if (xia<=16 && wia>16 && we Date: Wed, 19 Oct 2022 22:00:42 -0400 Subject: [PATCH 03/19] Table-based 1- and 2-byte integer membership --- src/builtins/search.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/builtins/search.c b/src/builtins/search.c index 1d1d9331..72ce9875 100644 --- a/src/builtins/search.c +++ b/src/builtins/search.c @@ -101,6 +101,28 @@ B memberOf_c2(B t, B w, B x) { } #undef WEQ // TODO O(wia×xia) for small wia + if (xia+wia>20 && we<=el_i16 && xe<=el_i16 && we!=el_bit) { + usz xt = 1<<(8*elWidth(xe)); // Range of x writes + usz wt = 1<<(8*elWidth(we)); // Range of w lookups + usz t = xt>wt? xt : wt; // Table allocation width + void* wp = tyany_ptr(w); + void* xp = tyany_ptr(x); + usz m=wia, n=xia; + i8* rp; B r = m_i8arrv(&rp, m); + TALLOC(u8, tab0, t); u8* tab = tab0 + t/2; + // Initialize + if (we==el_i16 && m Date: Thu, 20 Oct 2022 22:05:40 -0400 Subject: [PATCH 04/19] Extend table-based membership to Index-of --- src/builtins/search.c | 50 +++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/src/builtins/search.c b/src/builtins/search.c index 72ce9875..c11d6e20 100644 --- a/src/builtins/search.c +++ b/src/builtins/search.c @@ -3,6 +3,28 @@ #include "../utils/mut.h" #include "../utils/talloc.h" +#define TABLE(IN, FOR, TY, INIT, SET) \ + usz it = 1<<(8*elWidth(IN##e)); /* Range of writes */ \ + usz ft = 1<<(8*elWidth(FOR##e)); /* Range of lookups */ \ + usz t = it>ft? it : ft; /* Table allocation width */ \ + TY* rp; B r = m_##TY##arrc(&rp, FOR); \ + TALLOC(TY, tab0, t); TY* tab = tab0 + t/2; \ + usz m=IN##ia, n=FOR##ia; \ + void* ip = tyany_ptr(IN); \ + void* fp = tyany_ptr(FOR); \ + /* Initialize */ \ + if (FOR##e==el_i16 && n20 && we<=el_i16 && xe<=el_i16 && we!=el_bit && xe!=el_bit) { + TABLE(w, x, i32, wia, i) + return r; + } i32* rp; B r = m_i32arrc(&rp, x); H_b2i* map = m_b2i(64); SGetU(x) @@ -102,25 +128,7 @@ B memberOf_c2(B t, B w, B x) { #undef WEQ // TODO O(wia×xia) for small wia if (xia+wia>20 && we<=el_i16 && xe<=el_i16 && we!=el_bit) { - usz xt = 1<<(8*elWidth(xe)); // Range of x writes - usz wt = 1<<(8*elWidth(we)); // Range of w lookups - usz t = xt>wt? xt : wt; // Table allocation width - void* wp = tyany_ptr(w); - void* xp = tyany_ptr(x); - usz m=wia, n=xia; - i8* rp; B r = m_i8arrv(&rp, m); - TALLOC(u8, tab0, t); u8* tab = tab0 + t/2; - // Initialize - if (we==el_i16 && m Date: Fri, 21 Oct 2022 20:11:40 -0400 Subject: [PATCH 05/19] Extend lookup code to boolean searched-for array --- src/builtins/search.c | 51 ++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/src/builtins/search.c b/src/builtins/search.c index c11d6e20..b9c8b8c7 100644 --- a/src/builtins/search.c +++ b/src/builtins/search.c @@ -4,26 +4,31 @@ #include "../utils/talloc.h" #define TABLE(IN, FOR, TY, INIT, SET) \ - usz it = 1<<(8*elWidth(IN##e)); /* Range of writes */ \ - usz ft = 1<<(8*elWidth(FOR##e)); /* Range of lookups */ \ - usz t = it>ft? it : ft; /* Table allocation width */ \ - TY* rp; B r = m_##TY##arrc(&rp, FOR); \ - TALLOC(TY, tab0, t); TY* tab = tab0 + t/2; \ - usz m=IN##ia, n=FOR##ia; \ - void* ip = tyany_ptr(IN); \ - void* fp = tyany_ptr(FOR); \ - /* Initialize */ \ - if (FOR##e==el_i16 && nft? it : ft; /* Table allocation width */ \ + TALLOC(TY, tab0, t); TY* tab = tab0 + t/2; \ + usz m=IN##ia, n=FOR##ia; \ + void* ip = tyany_ptr(IN); \ + void* fp = tyany_ptr(FOR); \ + /* Initialize */ \ + if (FOR##e==el_i16 && n20 && we<=el_i16 && xe<=el_i16 && we!=el_bit && xe!=el_bit) { + if (xia+wia>20 && we<=el_i16 && xe<=el_i16 && we!=el_bit) { + B r; TABLE(w, x, i32, wia, i) return r; } @@ -127,7 +133,8 @@ B memberOf_c2(B t, B w, B x) { } #undef WEQ // TODO O(wia×xia) for small wia - if (xia+wia>20 && we<=el_i16 && xe<=el_i16 && we!=el_bit) { + if (xia+wia>20 && we<=el_i16 && xe<=el_i16) { + B r; TABLE(x, w, i8, 0, 1) return num_squeeze(r); } From 0f7bfa25759c8b99a74d4aa6d12637edc9e89e7f Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Fri, 21 Oct 2022 21:07:25 -0400 Subject: [PATCH 06/19] Implement bit_find and fast self-search for booleans --- src/builtins/selfsearch.c | 15 +++++++++++++++ src/core/numarr.h | 10 ++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/builtins/selfsearch.c b/src/builtins/selfsearch.c index 37e647fd..f523298b 100644 --- a/src/builtins/selfsearch.c +++ b/src/builtins/selfsearch.c @@ -3,6 +3,9 @@ #include "../utils/mut.h" #include "../utils/talloc.h" +B not_c1(B t, B x); +B shape_c1(B t, B x); + B memberOf_c1(B t, B x) { if (isAtm(x) || RNK(x)==0) thrM("∊: Argument cannot have rank 0"); usz n = *SH(x); @@ -10,6 +13,13 @@ B memberOf_c1(B t, B x) { u8 lw = cellWidthLog(x); void* xv = tyany_ptr(x); + if (lw == 0) { + usz i = bit_find(xv, n, 1 &~ *(u64*)xv); decG(x); + B r = taga(arr_shVec(allZeroes(n))); + u64* rp = tyany_ptr(r); + rp[0]=1; if (i(usz)I32_MAX+1) thrM("⊒: Argument length >2⋆31 not supported"); u8 lw = cellWidthLog(x); + if (lw==0) { x = toI8Any(x); lw = cellWidthLog(x); } void* xv = tyany_ptr(x); #define BRUTE(T) \ i##T* xp = xv; \ @@ -189,6 +200,10 @@ B indexOf_c1(B t, B x) { u8 lw = cellWidthLog(x); void* xv = tyany_ptr(x); + if (lw == 0) { + B r = 1&*(u64*)xv ? not_c1(m_f64(0), x) : x; + return shape_c1(m_f64(0), r); + } #define BRUTE(T) \ i##T* xp = xv; \ i8* rp; B r = m_i8arrv(&rp, n); rp[0]=0; \ diff --git a/src/core/numarr.h b/src/core/numarr.h index b33b0364..4da3c809 100644 --- a/src/core/numarr.h +++ b/src/core/numarr.h @@ -48,6 +48,16 @@ static inline bool bit_has(u64* arr, u64 ia, bool v) { for (usz i=0; i Date: Fri, 21 Oct 2022 21:31:06 -0400 Subject: [PATCH 07/19] =?UTF-8?q?Index-of=20with=20boolean=20=F0=9D=95=A8,?= =?UTF-8?q?=20using=20two=20comparisons?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/search.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/builtins/search.c b/src/builtins/search.c index b9c8b8c7..216dd487 100644 --- a/src/builtins/search.c +++ b/src/builtins/search.c @@ -3,6 +3,14 @@ #include "../utils/mut.h" #include "../utils/talloc.h" +#define C2(F,X,W) F##_c2(m_f64(0),X,W) +#define C2i(F, W, X) C2(F, m_i32(W), X) +extern B eq_c2(B,B,B); +extern B ne_c2(B,B,B); +extern B or_c2(B,B,B); +extern B sub_c2(B,B,B); +extern B mul_c2(B,B,B); + #define TABLE(IN, FOR, TY, INIT, SET) \ usz it = 1<<(1<20 && we<=el_i16 && xe<=el_i16 && we!=el_bit) { + if (xia+wia>20 && we<=el_i16 && xe<=el_i16) { B r; TABLE(w, x, i32, wia, i) return r; @@ -85,8 +100,6 @@ B indexOf_c2(B t, B w, B x) { B enclosed_0; B enclosed_1; extern B rt_memberOf; -extern B eq_c2(B,B,B); -extern B or_c2(B,B,B); B memberOf_c2(B t, B w, B x) { if (isAtm(x) || RNK(x)!=1) goto bad; if (isAtm(w)) goto single; @@ -117,18 +130,18 @@ B memberOf_c2(B t, B w, B x) { u8 we = TI(w,elType); usz wia = IA(w); u8 xe = TI(x,elType); usz xia = IA(x); if (xia == 0) { Arr* ba=allZeroes(wia); arr_shVec(ba); r=taga(ba); decG(w); goto dec_x; } - #define WEQ(V) eq_c2(m_f64(0), inc(w), V) + #define WEQ(V) C2(eq, inc(w), V) if (xe==el_bit) { u64* xp = bitarr_ptr(x); u64 x0 = 1 & xp[0]; r = WEQ(m_usz(x0)); - if (bit_has(xp, xia, !x0)) r = or_c2(m_f64(0), r, WEQ(m_usz(!x0))); + if (bit_has(xp, xia, !x0)) r = C2(or, r, WEQ(m_usz(!x0))); decG(w); goto dec_x; } if (xia<=16 && wia>16 && we Date: Fri, 21 Oct 2022 22:10:39 -0400 Subject: [PATCH 08/19] =?UTF-8?q?Dyadic=20=E2=8A=92=20implementation=20wit?= =?UTF-8?q?h=20a=20generic=20hash=20table?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/search.c | 25 +++++++++++++++++++++++++ src/utils/hashmapTemplate.h | 4 ++++ 2 files changed, 29 insertions(+) diff --git a/src/builtins/search.c b/src/builtins/search.c index 216dd487..572c57ee 100644 --- a/src/builtins/search.c +++ b/src/builtins/search.c @@ -168,6 +168,31 @@ B memberOf_c2(B t, B w, B x) { extern B rt_count; B count_c2(B t, B w, B x) { + if (!isArr(w) || RNK(w)==0) thrM("⊒: 𝕨 must have rank at least 1"); + if (RNK(w)==1) { + if (!isArr(x) || IA(x)<=1) return indexOf_c2(m_f64(0), w, x); + usz wia = IA(w); + usz xia = IA(x); + i32* rp; B r = m_i32arrc(&rp, x); + TALLOC(usz, wnext, wia+1); + H_b2i* map = m_b2i(64); + SGetU(x) + SGetU(w) + wnext[wia] = wia; + for (usz i = wia; i--; ) { + bool had; u64 p = mk_b2i(&map, GetU(w,i), &had); + wnext[i] = had ? map->a[p].val : wia; + map->a[p].val = i; + } + for (usz i = 0; i < xia; i++) { + bool had; u64 p = getQ_b2i(map, GetU(x,i), &had); + usz j = wia; + if (had) { j = map->a[p].val; map->a[p].val = wnext[j]; } + rp[i] = j; + } + TFREE(wnext); free_b2i(map); decG(w); decG(x); + return wia<=I8_MAX? taga(cpyI8Arr(r)) : wia<=I16_MAX? taga(cpyI16Arr(r)) : r; + } return c2(rt_count, w, x); } diff --git a/src/utils/hashmapTemplate.h b/src/utils/hashmapTemplate.h index 88e9c0f8..4305863d 100644 --- a/src/utils/hashmapTemplate.h +++ b/src/utils/hashmapTemplate.h @@ -88,6 +88,10 @@ static inline bool N(has) (Map* m, KT k) { u64 p = N(find)(m, k, h1, h2, &has); return has? m->a[p].val : def; } + static inline u64 N(getQ) (Map* m, KT k, bool* had) { + u64 h1 = H1(k); u64 h2 = H2(k, h1); + return N(find)(m, k, h1, h2, had); + } #endif From 5df198602c2479391d003fe97d04ce71bb259495 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Sat, 22 Oct 2022 08:18:43 -0400 Subject: [PATCH 09/19] Adjust search table sparse initialization threshold for type it stores --- src/builtins/search.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/builtins/search.c b/src/builtins/search.c index 572c57ee..a2ba7fb7 100644 --- a/src/builtins/search.c +++ b/src/builtins/search.c @@ -20,7 +20,7 @@ extern B mul_c2(B,B,B); void* ip = tyany_ptr(IN); \ void* fp = tyany_ptr(FOR); \ /* Initialize */ \ - if (FOR##e==el_i16 && n Date: Sat, 22 Oct 2022 08:36:11 -0400 Subject: [PATCH 10/19] =?UTF-8?q?Table-based=20dyadic=20=E2=8A=92=20for=20?= =?UTF-8?q?integers=20up=20to=202=20bytes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/search.c | 52 ++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/src/builtins/search.c b/src/builtins/search.c index a2ba7fb7..b27f19b8 100644 --- a/src/builtins/search.c +++ b/src/builtins/search.c @@ -11,10 +11,12 @@ extern B or_c2(B,B,B); extern B sub_c2(B,B,B); extern B mul_c2(B,B,B); +static u64 elRange(u8 eltype) { return 1ull<<(1<ft? it : ft; /* Table allocation width */ \ + usz it = elRange(IN##e); /* Range of writes */ \ + usz ft = elRange(FOR##e); /* Range of lookups */ \ + usz t = it>ft? it : ft; /* Table allocation width */ \ TALLOC(TY, tab0, t); TY* tab = tab0 + t/2; \ usz m=IN##ia, n=FOR##ia; \ void* ip = tyany_ptr(IN); \ @@ -169,16 +171,40 @@ B memberOf_c2(B t, B w, B x) { extern B rt_count; B count_c2(B t, B w, B x) { if (!isArr(w) || RNK(w)==0) thrM("⊒: 𝕨 must have rank at least 1"); - if (RNK(w)==1) { - if (!isArr(x) || IA(x)<=1) return indexOf_c2(m_f64(0), w, x); - usz wia = IA(w); - usz xia = IA(x); - i32* rp; B r = m_i32arrc(&rp, x); - TALLOC(usz, wnext, wia+1); + if (RNK(w)!=1) return c2(rt_count, w, x); + if (!isArr(x) || IA(x)<=1) return indexOf_c2(m_f64(0), w, x); + u8 we = TI(w,elType); usz wia = IA(w); + u8 xe = TI(x,elType); usz xia = IA(x); + i32* rp; B r = m_i32arrc(&rp, x); + TALLOC(usz, wnext, wia+1); + wnext[wia] = wia; + if (we<=el_i16 && xe<=el_i16) { + if (we==el_bit) { w = toI8Any(w); we = TI(w,elType); } + if (xe==el_bit) { x = toI8Any(x); xe = TI(x,elType); } + usz it = elRange(we); // Range of writes + usz ft = elRange(xe); // Range of lookups + usz t = it>ft? it : ft; // Table allocation width + TALLOC(i32, tab0, t); i32* tab = tab0 + t/2; + usz m=wia, n=xia; + void* ip = tyany_ptr(w); + void* fp = tyany_ptr(x); + // Initialize + if (xe==el_i16 && na[p].val : wia; @@ -190,10 +216,10 @@ B count_c2(B t, B w, B x) { if (had) { j = map->a[p].val; map->a[p].val = wnext[j]; } rp[i] = j; } - TFREE(wnext); free_b2i(map); decG(w); decG(x); - return wia<=I8_MAX? taga(cpyI8Arr(r)) : wia<=I16_MAX? taga(cpyI16Arr(r)) : r; + free_b2i(map); } - return c2(rt_count, w, x); + TFREE(wnext); decG(w); decG(x); + return wia<=I8_MAX? taga(cpyI8Arr(r)) : wia<=I16_MAX? taga(cpyI16Arr(r)) : r; } From 552e4f67517c3c3e3d720fbaf9094323c13eda99 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Sat, 22 Oct 2022 10:38:11 -0400 Subject: [PATCH 11/19] =?UTF-8?q?Fix=20refcount=20handling=20for=20bool?= =?UTF-8?q?=E2=8A=90=F0=9D=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/search.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/builtins/search.c b/src/builtins/search.c index b27f19b8..2ed79dd2 100644 --- a/src/builtins/search.c +++ b/src/builtins/search.c @@ -74,7 +74,8 @@ B indexOf_c2(B t, B w, B x) { u64* wp = bitarr_ptr(w); u64 w0 = 1 & wp[0]; u64 i = bit_find(wp, wia, !w0); decG(w); - B r = C2i(mul, wia , C2i(ne, w0, inc(x))); + if (i!=wia) inc(x); + B r = C2i(mul, wia , C2i(ne, w0, x)) ; return i==wia? r : C2(sub, r, C2i(mul, wia-i, C2i(eq, !w0, x))); } // TODO O(wia×xia) for small wia or xia From 2207d9f1bbd3c41bed9900c200b914daa8a87534 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Sat, 22 Oct 2022 16:01:45 -0400 Subject: [PATCH 12/19] =?UTF-8?q?Combine=20monadic=20=E2=88=8A=20and=20?= =?UTF-8?q?=E2=8A=90=20radix=20lookups=20with=20a=20macro?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/selfsearch.c | 79 ++++++++++++++------------------------- 1 file changed, 29 insertions(+), 50 deletions(-) diff --git a/src/builtins/selfsearch.c b/src/builtins/selfsearch.c index f523298b..e40b3ab0 100644 --- a/src/builtins/selfsearch.c +++ b/src/builtins/selfsearch.c @@ -6,6 +6,32 @@ B not_c1(B t, B x); B shape_c1(B t, B x); +#define RADIX_LOOKUP_i32(INIT, SETTAB) \ + /* Count keys */ \ + for (usz j=0; j<2*rx; j++) c0[j] = 0; \ + for (usz i=0; i>24)]++; c1[(u8)(v>>16)]++; } \ + /* Exclusive prefix sum */ \ + usz s0=0, s1=0; \ + for (usz j=0; j>24); usz c=c0[k]++; v1[c]=v; } \ + for (usz i=0; i>16); usz c=c1[k]++; v2[c]=v; } \ + /* Table lookup */ \ + u32 tv=v2[0]>>16; v2[n]=~v2[n-1]; \ + for (usz l=0, i=0; l>16; if (tv!=t0) break; tab[(u16)v]=INIT; } \ + for (; i>24)]++; c1[(u8)(v>>16)]++; } - // Exclusive prefix sum - usz s0=0, s1=0; - for (usz j=0; j>24); usz c=c0[k]++; v1[c]=v; } - for (usz i=0; i>16); usz c=c1[k]++; v2[c]=v; } - // Table lookup - u32 tv=v2[0]>>16; v2[n]=~v2[n-1]; - for (usz l=0, i=0; l>16; if (tv!=t0) break; tab[(u16)v]=1; } - for (; in?tn:n)+(2*rx+1)*sizeof(usz))); - // timeline // Allocations len count radix hash deradix bytes layout: usz *c0 = (usz*)(alloc)+1; // rx [+++................] c0 rx # @@ -151,30 +153,7 @@ B count_c1(B t, B x) { u32 *r1 = (u32*)v1; // n [+..] r1 4*n ######## u32 *tab= (u32*)v1; // tn [+] tab 4*tn ########### - // Count keys - for (usz j=0; j<2*rx; j++) c0[j] = 0; - for (usz i=0; i>24)]++; c1[(u8)(v>>16)]++; } - // Exclusive prefix sum - usz s0=0, s1=0; - for (usz j=0; j>24); usz c=c0[k]++; v1[c]=v; } - for (usz i=0; i>16); usz c=c1[k]++; v2[c]=v; } - // Table lookup - u32 tv=v2[0]>>16; v2[n]=~v2[n-1]; - for (usz l=0, i=0; l>16; if (tv!=t0) break; tab[(u16)v]=0; } - for (; i Date: Sat, 22 Oct 2022 16:29:05 -0400 Subject: [PATCH 13/19] Unify radix sort and radix lookup prefix sums --- src/builtins/grade.h | 45 ++------------------------------------- src/builtins/radix.h | 36 +++++++++++++++++++++++++++++++ src/builtins/selfsearch.c | 13 +++++------ 3 files changed, 43 insertions(+), 51 deletions(-) create mode 100644 src/builtins/radix.h diff --git a/src/builtins/grade.h b/src/builtins/grade.h index 2643ccbb..8e9e0450 100644 --- a/src/builtins/grade.h +++ b/src/builtins/grade.h @@ -74,6 +74,7 @@ extern void (*const avx2_scan_min16)(int16_t* v0,int16_t* v1,uint64_t v2); TFREE(c0) // Radix sorting +#include "radix.h" #define INC(P,I) GRADE_UD((P+1)[I]++,P[I]--) #define ROFF GRADE_UD(1,0) // Radix offset @@ -81,7 +82,7 @@ extern void (*const avx2_scan_min16)(int16_t* v0,int16_t* v1,uint64_t v2); #define CHOOSE_SG_GRADE(S,G) G #define RADIX_SORT_i8(T, TYP) \ - TALLOC(T, c0, 256+ROFF); T* c0o=c0+128; \ + TALLOC(T, c0, 256+ROFF); T* c0o=c0+128; \ for (usz j=0; j<256; j++) c0[j]=0; \ GRADE_UD(,c0[0]=n;) \ for (usz i=0; i>24)]++; c1[(u8)(v>>16)]++; } \ - /* Exclusive prefix sum */ \ - usz s0=0, s1=0; \ - for (usz j=0; j>24)]++; (c1+1)[(u8)(v>>16)]++; } \ + /* Inclusive prefix sum; note c offsets above */ \ + RADIX_SUM_2_u32; \ /* Radix moves */ \ for (usz i=0; i>24); usz c=c0[k]++; v1[c]=v; } \ for (usz i=0; i>16); usz c=c1[k]++; v2[c]=v; } \ From 7cbd23c832f8d08cfebd321e240b679389cc9675 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Sat, 22 Oct 2022 22:16:55 -0400 Subject: [PATCH 14/19] Skip radix moves if the top bytes are all the same --- src/builtins/radix.h | 4 +++ src/builtins/selfsearch.c | 57 ++++++++++++++++++++++++--------------- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/src/builtins/radix.h b/src/builtins/radix.h index 29b93b08..f83414c1 100644 --- a/src/builtins/radix.h +++ b/src/builtins/radix.h @@ -13,12 +13,14 @@ extern void (*const avx2_scan_pluswrap_u8)(uint8_t* v0,uint8_t* v1,uint64_t v2,uint8_t v3); extern void (*const avx2_scan_pluswrap_u32)(uint32_t* v0,uint32_t* v1,uint64_t v2,uint32_t v3); #define RADIX_SUM_1_u8 avx2_scan_pluswrap_u8 (c0,c0, 256,0); +#define RADIX_SUM_1_u32 avx2_scan_pluswrap_u32(c0,c0, 256,0); #define RADIX_SUM_2_u8 avx2_scan_pluswrap_u8 (c0,c0,2*256,0); #define RADIX_SUM_2_u32 avx2_scan_pluswrap_u32(c0,c0,2*256,0); #define RADIX_SUM_4_u8 avx2_scan_pluswrap_u8 (c0,c0,4*256,0); #define RADIX_SUM_4_u32 avx2_scan_pluswrap_u32(c0,c0,4*256,0); #else #define RADIX_SUM_1_u8 RDX_SUM_1(u8) +#define RADIX_SUM_1_u32 RDX_SUM_1(u32) #define RADIX_SUM_2_u8 RDX_SUM_2(u8) #define RADIX_SUM_2_u32 RDX_SUM_2(u32) #define RADIX_SUM_4_u8 RDX_SUM_4(u8) @@ -34,3 +36,5 @@ extern void (*const avx2_scan_pluswrap_u32)(uint32_t* v0,uint32_t* v1,uint64_t v #define RADIX_SUM_2_usz RDX_SUM_2(usz) #define RADIX_SUM_4_usz RDX_SUM_4(usz) #endif + +u8 radix_offsets_2_u32(usz* c0, u32* v0, usz n); // selfsearch.c diff --git a/src/builtins/selfsearch.c b/src/builtins/selfsearch.c index 53e4f8e9..e985ffd5 100644 --- a/src/builtins/selfsearch.c +++ b/src/builtins/selfsearch.c @@ -7,26 +7,39 @@ B not_c1(B t, B x); B shape_c1(B t, B x); #include "radix.h" -#define RADIX_LOOKUP_i32(INIT, SETTAB) \ - /* Count keys */ \ - for (usz j=0; j<2*rx; j++) c0[j] = 0; \ - c1[0] = -n; \ - for (usz i=0; i>24)]++; (c1+1)[(u8)(v>>16)]++; } \ - /* Inclusive prefix sum; note c offsets above */ \ - RADIX_SUM_2_u32; \ - /* Radix moves */ \ - for (usz i=0; i>24); usz c=c0[k]++; v1[c]=v; } \ - for (usz i=0; i>16); usz c=c1[k]++; v2[c]=v; } \ - /* Table lookup */ \ - u32 tv=v2[0]>>16; v2[n]=~v2[n-1]; \ - for (usz l=0, i=0; l>16; if (tv!=t0) break; tab[(u16)v]=INIT; } \ - for (; i>16)]++; (c1+1)[(u8)(v>>24)]++; } + u32 v=v0[0]; + // Inclusive prefix sum; note c offsets above + if ((c1+1)[(u8)(v>>24)] < n) { c1[0]-=n; RADIX_SUM_2_u32; return 2; } + if ((c0+1)[(u8)(v>>16)] < n) { RADIX_SUM_1_u32; return 1; } + return 0; +} +#define RADIX_LOOKUP_32(INIT, SETTAB) \ + /* Radix moves */ \ + u8 bytes = radix_offsets_2_u32(c0, v0, n); \ + if (bytes==0) { \ + for (usz i=0; i>16); usz c=c0[k]++; v1[c]=v; } \ + if (bytes==2) for (usz i=0; i>24); usz c=c1[k]++; v2[c]=v; } \ + /* Table lookup */ \ + u32 tv=v2[0]>>16; v2[n]=~v2[n-1]; \ + for (usz l=0, i=0; l>16; if (tv!=t0) break; tab[(u16)v]=INIT; } \ + for (; i Date: Sun, 23 Oct 2022 12:06:38 -0400 Subject: [PATCH 15/19] Use saved counts and possibly dense table initialization for 1-byte radix lookup --- src/builtins/selfsearch.c | 53 +++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/src/builtins/selfsearch.c b/src/builtins/selfsearch.c index e985ffd5..dcbb07dd 100644 --- a/src/builtins/selfsearch.c +++ b/src/builtins/selfsearch.c @@ -19,27 +19,38 @@ u8 radix_offsets_2_u32(usz* c0, u32* v0, usz n) { if ((c0+1)[(u8)(v>>16)] < n) { RADIX_SUM_1_u32; return 1; } return 0; } -#define RADIX_LOOKUP_32(INIT, SETTAB) \ - /* Radix moves */ \ - u8 bytes = radix_offsets_2_u32(c0, v0, n); \ - if (bytes==0) { \ - for (usz i=0; i>16); usz c=c0[k]++; v1[c]=v; } \ - if (bytes==2) for (usz i=0; i>24); usz c=c1[k]++; v2[c]=v; } \ - /* Table lookup */ \ - u32 tv=v2[0]>>16; v2[n]=~v2[n-1]; \ - for (usz l=0, i=0; l>16; if (tv!=t0) break; tab[(u16)v]=INIT; } \ - for (; i>16); usz c=c0[k]++; v1[c]=v; } \ + if (bytes==1) { \ + /* Table lookup, getting radix boundaries from c0 */ \ + for (usz i=0; i>16)]; \ + if (l-i < tim) for (usz ii=i; ii>24); usz c=c1[k]++; v2[c]=v; } \ + /* Table lookup */ \ + u32 tv=v2[0]>>16; v2[n]=~v2[n-1]; \ + for (usz l=0, i=0; l>16; if (tv!=t0) break; tab[(u16)v]=INIT; } \ + for (; i Date: Sun, 23 Oct 2022 22:07:11 -0400 Subject: [PATCH 16/19] =?UTF-8?q?Index-of=20with=20small=20=F0=9D=95=A8=20?= =?UTF-8?q?using=20(=E2=8A=A3=C3=971+=E2=8A=A2)=C2=B4=20pattern?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/search.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/builtins/search.c b/src/builtins/search.c index 2ed79dd2..5cdd7107 100644 --- a/src/builtins/search.c +++ b/src/builtins/search.c @@ -8,6 +8,7 @@ extern B eq_c2(B,B,B); extern B ne_c2(B,B,B); extern B or_c2(B,B,B); +extern B add_c2(B,B,B); extern B sub_c2(B,B,B); extern B mul_c2(B,B,B); @@ -70,6 +71,7 @@ B indexOf_c2(B t, B w, B x) { } else { u8 we = TI(w,elType); usz wia = IA(w); u8 xe = TI(x,elType); usz xia = IA(x); + if (wia == 0) { decG(w); decG(x); return taga(arr_shVec(allZeroes(xia))); } if (we==el_bit) { u64* wp = bitarr_ptr(w); u64 w0 = 1 & wp[0]; @@ -78,7 +80,15 @@ B indexOf_c2(B t, B w, B x) { B r = C2i(mul, wia , C2i(ne, w0, x)) ; return i==wia? r : C2(sub, r, C2i(mul, wia-i, C2i(eq, !w0, x))); } - // TODO O(wia×xia) for small wia or xia + if (wia<=(we<=el_i16?4:16) && xia>16 && we20 && we<=el_i16 && xe<=el_i16) { B r; TABLE(w, x, i32, wia, i) @@ -132,7 +142,7 @@ B memberOf_c2(B t, B w, B x) { many: { u8 we = TI(w,elType); usz wia = IA(w); u8 xe = TI(x,elType); usz xia = IA(x); - if (xia == 0) { Arr* ba=allZeroes(wia); arr_shVec(ba); r=taga(ba); decG(w); goto dec_x; } + if (xia == 0) { r=taga(arr_shVec(allZeroes(wia))); decG(w); goto dec_x; } #define WEQ(V) C2(eq, inc(w), V) if (xe==el_bit) { u64* xp = bitarr_ptr(x); @@ -141,7 +151,7 @@ B memberOf_c2(B t, B w, B x) { if (bit_has(xp, xia, !x0)) r = C2(or, r, WEQ(m_usz(!x0))); decG(w); goto dec_x; } - if (xia<=16 && wia>16 && we16 && we Date: Mon, 24 Oct 2022 07:49:36 -0400 Subject: [PATCH 17/19] Need to define GRADE_UD for radix.h from selfsearch.c without Singeli --- src/builtins/radix.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/builtins/radix.h b/src/builtins/radix.h index f83414c1..c400cef6 100644 --- a/src/builtins/radix.h +++ b/src/builtins/radix.h @@ -4,6 +4,10 @@ // These are leaky macros and assume counts are c0, c1,... // which must be adjacent in memory +#ifndef GRADE_UD + // Search functions need this: they always sort up + #define GRADE_UD(U,D) U +#endif #define RDX_PRE(K) s##K=c##K[j]+=s##K #define RDX_SUM_1(T) T s0=0; for(usz j=0;j<256;j++) { RDX_PRE(0); } #define RDX_SUM_2(T) GRADE_UD(c1[0]=0;,) T s0=0, s1=0; for(usz j=0;j<256;j++) { RDX_PRE(0); RDX_PRE(1); } From 9862331696a898d8cf35aa955d628e2381739a8f Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Mon, 24 Oct 2022 22:08:28 -0400 Subject: [PATCH 18/19] Fix single-file build by defining GRADE_UD in selfsearch.c --- src/builtins/radix.h | 8 +++----- src/builtins/selfsearch.c | 2 ++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/builtins/radix.h b/src/builtins/radix.h index c400cef6..bcd68f7f 100644 --- a/src/builtins/radix.h +++ b/src/builtins/radix.h @@ -2,12 +2,10 @@ // Radix sorting utilities // These are leaky macros and assume counts are c0, c1,... -// which must be adjacent in memory +// which must be adjacent in memory. Search functions will also need +// #define GRADE_UD(U,D) U +// to do the appropriate sums for an ascending radix sort. -#ifndef GRADE_UD - // Search functions need this: they always sort up - #define GRADE_UD(U,D) U -#endif #define RDX_PRE(K) s##K=c##K[j]+=s##K #define RDX_SUM_1(T) T s0=0; for(usz j=0;j<256;j++) { RDX_PRE(0); } #define RDX_SUM_2(T) GRADE_UD(c1[0]=0;,) T s0=0, s1=0; for(usz j=0;j<256;j++) { RDX_PRE(0); RDX_PRE(1); } diff --git a/src/builtins/selfsearch.c b/src/builtins/selfsearch.c index dcbb07dd..5bf2ada2 100644 --- a/src/builtins/selfsearch.c +++ b/src/builtins/selfsearch.c @@ -6,6 +6,7 @@ B not_c1(B t, B x); B shape_c1(B t, B x); +#define GRADE_UD(U,D) U #include "radix.h" u8 radix_offsets_2_u32(usz* c0, u32* v0, usz n) { usz rx = 256; @@ -19,6 +20,7 @@ u8 radix_offsets_2_u32(usz* c0, u32* v0, usz n) { if ((c0+1)[(u8)(v>>16)] < n) { RADIX_SUM_1_u32; return 1; } return 0; } +#undef GRADE_UD #define RADIX_LOOKUP_32(INIT, SETTAB) \ u8 bytes = radix_offsets_2_u32(c0, v0, n); \ usz tim = tn/(64/sizeof(*tab)); /* sparse table init max */ \ From 5a7d702bc62100ea387c3a419df5ad555d909936 Mon Sep 17 00:00:00 2001 From: dzaima Date: Tue, 25 Oct 2022 16:59:01 +0300 Subject: [PATCH 19/19] use incG more --- src/builtins/search.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/builtins/search.c b/src/builtins/search.c index 5cdd7107..bfa805f8 100644 --- a/src/builtins/search.c +++ b/src/builtins/search.c @@ -76,19 +76,18 @@ B indexOf_c2(B t, B w, B x) { u64* wp = bitarr_ptr(w); u64 w0 = 1 & wp[0]; u64 i = bit_find(wp, wia, !w0); decG(w); - if (i!=wia) inc(x); + if (i!=wia) incG(x); B r = C2i(mul, wia , C2i(ne, w0, x)) ; return i==wia? r : C2(sub, r, C2i(mul, wia-i, C2i(eq, !w0, x))); } if (wia<=(we<=el_i16?4:16) && xia>16 && we20 && we<=el_i16 && xe<=el_i16) { B r; TABLE(w, x, i32, wia, i) @@ -132,8 +131,8 @@ B memberOf_c2(B t, B w, B x) { single: { usz xia = IA(x); SGetU(x) - for (usz i = 0; i < xia; i++) if (equal(GetU(x, i), w)) { r = inc(enclosed_1); goto dec_wx; } - r = inc(enclosed_0); + for (usz i = 0; i < xia; i++) if (equal(GetU(x, i), w)) { r = incG(enclosed_1); goto dec_wx; } + r = incG(enclosed_0); dec_wx:; dec(w); goto dec_x; } @@ -143,7 +142,7 @@ B memberOf_c2(B t, B w, B x) { u8 we = TI(w,elType); usz wia = IA(w); u8 xe = TI(x,elType); usz xia = IA(x); if (xia == 0) { r=taga(arr_shVec(allZeroes(wia))); decG(w); goto dec_x; } - #define WEQ(V) C2(eq, inc(w), V) + #define WEQ(V) C2(eq, incG(w), V) if (xe==el_bit) { u64* xp = bitarr_ptr(x); u64 x0 = 1 & xp[0];