Merge pull request #52 from mlochbaum/search
Search function improvements
This commit is contained in:
commit
1710b43966
2
makefile
2
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 $<
|
||||
|
||||
@ -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 && we<el_B && xe<el_B) {
|
||||
SGetU(x);
|
||||
Arr* ba=allZeroes(wia); arr_shVec(ba); r=taga(ba);
|
||||
for (usz i=0; i<xia; i++) r = or_c2(m_f64(0), r, eq_c2(m_f64(0), inc(w), GetU(x,i)));
|
||||
decG(w);
|
||||
goto dec_x;
|
||||
}
|
||||
// TODO O(wia×xia) for small wia or xia
|
||||
H_Sb* set = m_Sb(64);
|
||||
SGetU(x) SGetU(w)
|
||||
bool had;
|
||||
for (usz i = 0; i < xia; i++) mk_Sb(&set, GetU(x,i), &had);
|
||||
u64* rp; r = m_bitarrv(&rp, wia);
|
||||
for (usz i = 0; i < wia; i++) bitp_set(rp, i, has_Sb(set, GetU(w,i)));
|
||||
free_Sb(set); decG(w);
|
||||
goto dec_x;
|
||||
}
|
||||
|
||||
dec_x:;
|
||||
decG(x);
|
||||
return r;
|
||||
}
|
||||
|
||||
extern B rt_find;
|
||||
B find_c2(B t, B w, B x) {
|
||||
return c2(rt_find, w, x);
|
||||
}
|
||||
|
||||
extern B rt_count;
|
||||
B count_c2(B t, B w, B x) {
|
||||
return c2(rt_count, w, x);
|
||||
}
|
||||
|
||||
static H_b2i* prevImports;
|
||||
i32 getPrevImport(B path) { // -1 for unset, -2 for unfinished
|
||||
if (prevImports==NULL) prevImports = m_b2i(16);
|
||||
@ -380,8 +271,6 @@ void profiler_freeMap(void* mapRaw) {
|
||||
void fun_gcFn() {
|
||||
if (prevImports!=NULL) mm_visitP(prevImports);
|
||||
if (globalNames!=NULL) mm_visitP(globalNames);
|
||||
mm_visit(enclosed_0);
|
||||
mm_visit(enclosed_1);
|
||||
mm_visit(globalNameList);
|
||||
for (i32 i = 0; i < 3; i++) mm_visitP(bitUD[i]);
|
||||
}
|
||||
@ -400,8 +289,6 @@ void fns_init() {
|
||||
TIi(t_funBI,fn_uc1) = funBI_uc1;
|
||||
TIi(t_funBI,fn_ucw) = funBI_ucw;
|
||||
TIi(t_funBI,fn_im) = funBI_im;
|
||||
{ u64* p; Arr* a=m_bitarrp(&p, 1); arr_shAlloc(a,0); *p= 0; enclosed_0=taga(a); }
|
||||
{ u64* p; Arr* a=m_bitarrp(&p, 1); arr_shAlloc(a,0); *p=~0ULL; enclosed_1=taga(a); }
|
||||
bitUD[0] = a(emptyIVec());
|
||||
{ u64* p; B a=m_bitarrv(&p, 1); *p=0; bitUD[1] = a(a); }
|
||||
{ u64* p; B a=m_bitarrv(&p, 2); *p=0; bitp_set(p,1,1); bitUD[2] = a(a); }
|
||||
|
||||
@ -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<n; i++) INC(c0o,xp[i]); \
|
||||
@ -132,37 +133,6 @@ extern void (*const avx2_scan_min16)(int16_t* v0,int16_t* v1,uint64_t v2);
|
||||
) \
|
||||
TFREE(alloc)
|
||||
|
||||
#define PRE(K) s##K=c##K[j]+=s##K
|
||||
#define RADIX_SUM_1(T) T s0=0; for(usz j=0;j<256;j++) { PRE(0); }
|
||||
#define RADIX_SUM_2(T) GRADE_UD(c1[0]=0;,) T s0=0, s1=0; for(usz j=0;j<256;j++) { PRE(0); PRE(1); }
|
||||
#define RADIX_SUM_4(T) GRADE_UD(c1[0]=c2[0]=c3[0]=0;,) T s0=0, s1=0, s2=0, s3=0; for(usz j=0;j<256;j++) { PRE(0); PRE(1); PRE(2); PRE(3); }
|
||||
|
||||
#if SINGELI
|
||||
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_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 RADIX_SUM_1(u8)
|
||||
#define RADIX_SUM_2_u8 RADIX_SUM_2(u8)
|
||||
#define RADIX_SUM_2_u32 RADIX_SUM_2(u32)
|
||||
#define RADIX_SUM_4_u8 RADIX_SUM_4(u8)
|
||||
#define RADIX_SUM_4_u32 RADIX_SUM_4(u32)
|
||||
#endif
|
||||
|
||||
#if SINGELI && !USZ_64
|
||||
#define RADIX_SUM_1_usz avx2_scan_pluswrap_u32(c0,c0, 256,0);
|
||||
#define RADIX_SUM_2_usz avx2_scan_pluswrap_u32(c0,c0,2*256,0);
|
||||
#define RADIX_SUM_4_usz avx2_scan_pluswrap_u32(c0,c0,4*256,0);
|
||||
#else
|
||||
#define RADIX_SUM_1_usz RADIX_SUM_1(usz)
|
||||
#define RADIX_SUM_2_usz RADIX_SUM_2(usz)
|
||||
#define RADIX_SUM_4_usz RADIX_SUM_4(usz)
|
||||
#endif
|
||||
|
||||
#define SORT_C1 CAT(GRADE_UD(and,or),c1)
|
||||
B SORT_C1(B t, B x) {
|
||||
if (isAtm(x) || RNK(x)==0) thrM(GRADE_UD("∧","∨")": Argument cannot have rank 0");
|
||||
@ -413,17 +383,6 @@ done:
|
||||
#undef RADIX_SORT_i8
|
||||
#undef RADIX_SORT_i16
|
||||
#undef RADIX_SORT_i32
|
||||
#undef RADIX_SUM_1
|
||||
#undef RADIX_SUM_2
|
||||
#undef RADIX_SUM_4
|
||||
#undef RADIX_SUM_1_u8
|
||||
#undef RADIX_SUM_1_usz
|
||||
#undef RADIX_SUM_2_u8
|
||||
#undef RADIX_SUM_2_usz
|
||||
#undef RADIX_SUM_2_u32
|
||||
#undef RADIX_SUM_4_u8
|
||||
#undef RADIX_SUM_4_usz
|
||||
#undef RADIX_SUM_4_u32
|
||||
#undef GRADE_CAT
|
||||
#undef GRADE_NEG
|
||||
#undef GRADE_UD
|
||||
|
||||
@ -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;
|
||||
|
||||
42
src/builtins/radix.h
Normal file
42
src/builtins/radix.h
Normal file
@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
// Radix sorting utilities
|
||||
// These are leaky macros and assume counts are c0, c1,...
|
||||
// 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.
|
||||
|
||||
#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); }
|
||||
#define RDX_SUM_4(T) GRADE_UD(c1[0]=c2[0]=c3[0]=0;,) T s0=0, s1=0, s2=0, s3=0; for(usz j=0;j<256;j++) { RDX_PRE(0); RDX_PRE(1); RDX_PRE(2); RDX_PRE(3); }
|
||||
|
||||
#if SINGELI
|
||||
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)
|
||||
#define RADIX_SUM_4_u32 RDX_SUM_4(u32)
|
||||
#endif
|
||||
|
||||
#if SINGELI && !USZ_64
|
||||
#define RADIX_SUM_1_usz avx2_scan_pluswrap_u32(c0,c0, 256,0);
|
||||
#define RADIX_SUM_2_usz avx2_scan_pluswrap_u32(c0,c0,2*256,0);
|
||||
#define RADIX_SUM_4_usz avx2_scan_pluswrap_u32(c0,c0,4*256,0);
|
||||
#else
|
||||
#define RADIX_SUM_1_usz RDX_SUM_1(usz)
|
||||
#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
|
||||
245
src/builtins/search.c
Normal file
245
src/builtins/search.c
Normal file
@ -0,0 +1,245 @@
|
||||
#include "../core.h"
|
||||
#include "../utils/hash.h"
|
||||
#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 add_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<<elWidthLogBits(eltype)); }
|
||||
|
||||
#define TABLE(IN, FOR, TY, INIT, SET) \
|
||||
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); \
|
||||
void* fp = tyany_ptr(FOR); \
|
||||
/* Initialize */ \
|
||||
if (FOR##e==el_i16 && n<ft/(64/sizeof(TY))) \
|
||||
{ for (usz i=0; i<n; i++) tab[((i16*)fp)[i]]=INIT; } \
|
||||
else { TY* to=tab-(ft/2-(ft==2)); for (i64 i=0; i<ft; i++) to[i]=INIT; } \
|
||||
/* Set */ \
|
||||
if (IN##e==el_i8) { for (usz i=m; i--; ) tab[((i8 *)ip)[i]]=SET; } \
|
||||
else { for (usz i=m; i--; ) tab[((i16*)ip)[i]]=SET; } \
|
||||
decG(IN); \
|
||||
/* Lookup */ \
|
||||
if (FOR##e==el_bit) { \
|
||||
r = bit_sel(FOR, m_i32(tab[0]), m_i32(tab[1])); \
|
||||
} else { \
|
||||
TY* rp; r = m_##TY##arrc(&rp, FOR); \
|
||||
if (FOR##e==el_i8){ for (usz i=0; i<n; i++) rp[i]=tab[((i8 *)fp)[i]]; } \
|
||||
else { for (usz i=0; i<n; i++) rp[i]=tab[((i16*)fp)[i]]; } \
|
||||
decG(FOR); \
|
||||
} \
|
||||
TFREE(tab0);
|
||||
|
||||
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 {
|
||||
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];
|
||||
u64 i = bit_find(wp, wia, !w0); decG(w);
|
||||
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 && we<el_B && xe<el_B) {
|
||||
SGetU(w);
|
||||
#define XEQ(I) C2(ne, GetU(w,I), incG(x))
|
||||
B r = XEQ(wia-1);
|
||||
for (usz i=wia-1; i--; ) r = C2(mul, XEQ(i), C2i(add, 1, r));
|
||||
#undef XEQ
|
||||
decG(w); decG(x); return r;
|
||||
}
|
||||
if (xia+wia>20 && we<=el_i16 && xe<=el_i16) {
|
||||
B r;
|
||||
TABLE(w, x, i32, wia, i)
|
||||
return r;
|
||||
}
|
||||
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;
|
||||
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 = incG(enclosed_1); goto dec_wx; }
|
||||
r = incG(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 == 0) { r=taga(arr_shVec(allZeroes(wia))); decG(w); goto dec_x; }
|
||||
#define WEQ(V) C2(eq, incG(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 = C2(or, r, WEQ(m_usz(!x0)));
|
||||
decG(w); goto dec_x;
|
||||
}
|
||||
if (xia<=(xe==el_i16?8:16) && wia>16 && we<el_B && xe<el_B) {
|
||||
SGetU(x);
|
||||
r = WEQ(GetU(x,0));
|
||||
for (usz i=1; i<xia; i++) r = C2(or, r, WEQ(GetU(x,i)));
|
||||
decG(w); goto dec_x;
|
||||
}
|
||||
#undef WEQ
|
||||
// TODO O(wia×xia) for small wia
|
||||
if (xia+wia>20 && we<=el_i16 && xe<=el_i16) {
|
||||
B r;
|
||||
TABLE(x, w, i8, 0, 1)
|
||||
return num_squeeze(r);
|
||||
}
|
||||
H_Sb* set = m_Sb(64);
|
||||
SGetU(x) SGetU(w)
|
||||
bool had;
|
||||
for (usz i = 0; i < xia; i++) mk_Sb(&set, GetU(x,i), &had);
|
||||
u64* rp; r = m_bitarrv(&rp, wia);
|
||||
for (usz i = 0; i < wia; i++) bitp_set(rp, i, has_Sb(set, GetU(w,i)));
|
||||
free_Sb(set); decG(w);
|
||||
goto dec_x;
|
||||
}
|
||||
|
||||
dec_x:;
|
||||
decG(x);
|
||||
return r;
|
||||
}
|
||||
|
||||
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) 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 && n<ft/(64/sizeof(i32)))
|
||||
{ for (usz i=0; i<n; i++) tab[((i16*)fp)[i]]=wia; }
|
||||
else { for (i64 i=0; i<ft; i++) tab[i-ft/2]=wia; }
|
||||
// Set
|
||||
#define SET(T) for (usz i=m; i--; ) { i32* p=tab+((T*)ip)[i]; wnext[i]=*p; *p=i; }
|
||||
if (we==el_i8) { SET(i8) } else { SET(i16) }
|
||||
#undef SET
|
||||
// Lookup
|
||||
#define GET(T) for (usz i=0; i<n; i++) { i32* p=tab+((T*)fp)[i]; *p=wnext[rp[i]=*p]; }
|
||||
if (xe==el_i8) { GET(i8) } else { GET(i16) }
|
||||
#undef GET
|
||||
TFREE(tab0);
|
||||
} else {
|
||||
H_b2i* map = m_b2i(64);
|
||||
SGetU(x)
|
||||
SGetU(w)
|
||||
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;
|
||||
}
|
||||
free_b2i(map);
|
||||
}
|
||||
TFREE(wnext); decG(w); decG(x);
|
||||
return wia<=I8_MAX? taga(cpyI8Arr(r)) : wia<=I16_MAX? taga(cpyI16Arr(r)) : r;
|
||||
}
|
||||
|
||||
|
||||
void search_gcFn() {
|
||||
mm_visit(enclosed_0);
|
||||
mm_visit(enclosed_1);
|
||||
}
|
||||
|
||||
void search_init() {
|
||||
gc_addFn(search_gcFn);
|
||||
{ u64* p; Arr* a=m_bitarrp(&p, 1); arr_shAlloc(a,0); *p= 0; enclosed_0=taga(a); }
|
||||
{ u64* p; Arr* a=m_bitarrp(&p, 1); arr_shAlloc(a,0); *p=~0ULL; enclosed_1=taga(a); }
|
||||
}
|
||||
@ -3,6 +3,58 @@
|
||||
#include "../utils/mut.h"
|
||||
#include "../utils/talloc.h"
|
||||
|
||||
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;
|
||||
usz* c1 = c0 + rx;
|
||||
// Count keys
|
||||
for (usz j=0; j<2*rx+1; j++) c0[j] = 0;
|
||||
for (usz i=0; i<n; i++) { u32 v=v0[i]; (c0+1)[(u8)(v>>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;
|
||||
}
|
||||
#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 */ \
|
||||
if (bytes==0) { \
|
||||
if (n<tim) for (usz i=0; i< n; i++) tab[(u16)v0[i]]=INIT; \
|
||||
else for (usz j=0; j<tn; j++) tab[j]=INIT; \
|
||||
for (usz i=0; i<n; i++) { u32 j=(u16)v0[i]; r0[i]=tab[j]; tab[j]SETTAB; } \
|
||||
} else { \
|
||||
if (bytes==1) { v1=v2; r1=r2; } \
|
||||
for (usz i=0; i<n; i++) { u32 v=v0[i]; u8 k=k0[i]=(u8)(v>>16); usz c=c0[k]++; v1[c]=v; } \
|
||||
if (bytes==1) { \
|
||||
/* Table lookup, getting radix boundaries from c0 */ \
|
||||
for (usz i=0; i<n; ) { \
|
||||
usz l=c0[(u8)(v1[i]>>16)]; \
|
||||
if (l-i < tim) for (usz ii=i; ii<l; ii++) tab[(u16)v1[ii]]=INIT; \
|
||||
else for (usz j=0; j<tn; j++) tab[j]=INIT; \
|
||||
for (; i<l; i++) { u32 j=(u16)v1[i]; r1[i]=tab[j]; tab[j]SETTAB; } \
|
||||
} \
|
||||
} else { \
|
||||
/* Radix move */ \
|
||||
for (usz i=0; i<n; i++) { u32 v=v1[i]; u8 k=k1[i]=(u8)(v>>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<n; ) { \
|
||||
for (; ; l++) { u32 v=v2[l], t0=tv; tv=v>>16; if (tv!=t0) break; tab[(u16)v]=INIT; } \
|
||||
for (; i<l; i++) { u32 j=(u16)v2[i]; r2[i]=tab[j]; tab[j]SETTAB; } \
|
||||
} \
|
||||
/* Radix unmove; back up c0 to account for increments in radix step */ \
|
||||
*--c1=0; for (usz i=0; i<n; i++) { r1[i]=r2[c1[k1[i]]++]; } \
|
||||
} \
|
||||
*--c0=0; for (usz i=0; i<n; i++) { r0[i]=r1[c0[k0[i]]++]; } \
|
||||
} \
|
||||
decG(x); TFREE(alloc);
|
||||
|
||||
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 +62,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<n) bitp_set(rp, i, 1);
|
||||
return r;
|
||||
}
|
||||
#define BRUTE(T) \
|
||||
i##T* xp = xv; \
|
||||
u64* rp; B r = m_bitarrv(&rp, n); bitp_set(rp, 0, 1); \
|
||||
@ -51,31 +110,8 @@ B memberOf_c1(B t, B x) {
|
||||
u8 *r2 = (u8 *)(v2); // n [+.....] r2 n ##
|
||||
u8 *r1 = (u8 *)(k1+n); // n [+..] r1 n ##
|
||||
u8 *tab= (u8 *)(r1); // tn [+] tab tn #####
|
||||
|
||||
// Count keys
|
||||
for (usz j=0; j<2*rx; j++) c0[j] = 0;
|
||||
for (usz i=0; i<n; i++) { u32 v=v0[i]; c0[(u8)(v>>24)]++; c1[(u8)(v>>16)]++; }
|
||||
// Exclusive prefix sum
|
||||
usz s0=0, s1=0;
|
||||
for (usz j=0; j<rx; j++) {
|
||||
usz p0 = s0, p1 = s1;
|
||||
s0 += c0[j]; s1 += c1[j];
|
||||
c0[j] = p0; c1[j] = p1;
|
||||
}
|
||||
// Radix moves
|
||||
for (usz i=0; i<n; i++) { u32 v=v0[i]; u8 k=k0[i]=(u8)(v>>24); usz c=c0[k]++; v1[c]=v; }
|
||||
for (usz i=0; i<n; i++) { u32 v=v1[i]; u8 k=k1[i]=(u8)(v>>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<n; ) {
|
||||
for (; ; l++) { u32 v=v2[l], t0=tv; tv=v>>16; if (tv!=t0) break; tab[(u16)v]=1; }
|
||||
for (; i<l; i++) { u32 j=(u16)v2[i]; r2[i]=tab[j]; tab[j]=0; }
|
||||
}
|
||||
// Radix unmoves
|
||||
*--c0 = *--c1 = 0; // Move back one to account for increments in radix step
|
||||
for (usz i=0; i<n; i++) { r1[i]=r2[c1[k1[i]]++]; }
|
||||
for (usz i=0; i<n; i++) { r0[i]=r1[c0[k0[i]]++]; }
|
||||
decG(x); TFREE(alloc);
|
||||
|
||||
RADIX_LOOKUP_32(1, =0)
|
||||
return num_squeeze(r);
|
||||
}
|
||||
#undef BRUTE
|
||||
@ -96,6 +132,7 @@ B count_c1(B t, B x) {
|
||||
if (n>(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; \
|
||||
@ -127,7 +164,6 @@ B count_c1(B t, B x) {
|
||||
i32* r0; B r = m_i32arrv(&r0, n);
|
||||
|
||||
TALLOC(u8, alloc, 6*n+(4+4*(tn>n?tn:n)+(2*rx+1)*sizeof(usz)));
|
||||
|
||||
// timeline
|
||||
// Allocations len count radix hash deradix bytes layout:
|
||||
usz *c0 = (usz*)(alloc)+1; // rx [+++................] c0 rx #
|
||||
@ -140,30 +176,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<n; i++) { u32 v=v0[i]; c0[(u8)(v>>24)]++; c1[(u8)(v>>16)]++; }
|
||||
// Exclusive prefix sum
|
||||
usz s0=0, s1=0;
|
||||
for (usz j=0; j<rx; j++) {
|
||||
usz p0 = s0, p1 = s1;
|
||||
s0 += c0[j]; s1 += c1[j];
|
||||
c0[j] = p0; c1[j] = p1;
|
||||
}
|
||||
// Radix moves
|
||||
for (usz i=0; i<n; i++) { u32 v=v0[i]; u8 k=k0[i]=(u8)(v>>24); usz c=c0[k]++; v1[c]=v; }
|
||||
for (usz i=0; i<n; i++) { u32 v=v1[i]; u8 k=k1[i]=(u8)(v>>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<n; ) {
|
||||
for (; ; l++) { u32 v=v2[l], t0=tv; tv=v>>16; if (tv!=t0) break; tab[(u16)v]=0; }
|
||||
for (; i<l; i++) { u32 j=(u16)v2[i]; r2[i]=tab[j]++; }
|
||||
}
|
||||
// Radix unmoves
|
||||
*--c0 = *--c1 = 0; // Move back one to account for increments in radix step
|
||||
for (usz i=0; i<n; i++) { r1[i]=r2[c1[k1[i]]++]; }
|
||||
for (usz i=0; i<n; i++) { r0[i]=r1[c0[k0[i]]++]; }
|
||||
decG(x); TFREE(alloc);
|
||||
RADIX_LOOKUP_32(0, ++)
|
||||
return num_squeeze(r);
|
||||
}
|
||||
#undef BRUTE
|
||||
@ -189,6 +202,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; \
|
||||
|
||||
@ -42,6 +42,22 @@ static inline u64 bitp_l1(u64* arr, u64 ia) { // last u64 of the array, with the
|
||||
static inline u64 bitx(B x) { // repeats the boolean across all 64 bits
|
||||
return o2bG(x)? ~(u64)0 : 0;
|
||||
}
|
||||
static inline bool bit_has(u64* arr, u64 ia, bool v) {
|
||||
u64 w = ~-(u64)v;
|
||||
u64 e = ia/64, q = ia%64;
|
||||
for (usz i=0; i<e; i++) if (arr[i]^w) return 1;
|
||||
return q && ((arr[e]^w) & ((1ULL<<q)-1));
|
||||
}
|
||||
static inline u64 bit_find(u64* arr, u64 ia, bool v) {
|
||||
u64 w = ~-(u64)v;
|
||||
u64 e = ia/64;
|
||||
for (u64 i=0; i<e; i++) {
|
||||
u64 f = w ^ arr[i];
|
||||
if (f) return 64*i + CTZ(f);
|
||||
}
|
||||
u64 q = ia%64;
|
||||
return (ia - q) | CTZ((w^arr[e]) | ~(u64)0<<q);
|
||||
}
|
||||
|
||||
// BitArr
|
||||
#define BITARR_SZ(IA) fsizeof(BitArr, a, u64, BIT_N(IA))
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#include "ns.h"
|
||||
#include "builtins.h"
|
||||
|
||||
#define FOR_INIT(F) F(base) F(harr) F(mutF) F(fillarr) F(tyarr) F(hash) F(sfns) F(fns) F(arith) F(md1) F(md2) F(derv) F(comp) F(rtWrap) F(ns) F(nfn) F(sysfn) F(inverse) F(slash) F(load) F(sysfnPost) F(dervPost) F(ffi) F(mmap) F(typesFinished)
|
||||
#define FOR_INIT(F) F(base) F(harr) F(mutF) F(fillarr) F(tyarr) F(hash) F(sfns) F(fns) F(arith) F(md1) F(md2) F(derv) F(comp) F(rtWrap) F(ns) F(nfn) F(sysfn) F(inverse) F(slash) F(search) F(load) F(sysfnPost) F(dervPost) F(ffi) F(mmap) F(typesFinished)
|
||||
#define F(X) void X##_init(void);
|
||||
FOR_INIT(F)
|
||||
#undef F
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
#include "../builtins/group.c"
|
||||
#include "../builtins/sysfn.c"
|
||||
#include "../builtins/sort.c"
|
||||
#include "../builtins/search.c"
|
||||
#include "../builtins/selfsearch.c"
|
||||
#include "../builtins/arithm.c"
|
||||
#include "../builtins/arithd.c"
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user