diff --git a/build/src/build.bqn b/build/src/build.bqn index 19c0856b..aad8883d 100755 --- a/build/src/build.bqn +++ b/build/src/build.bqn @@ -661,7 +661,7 @@ cachedBin‿linkerCache ← { "xag"‿"src/builtins/scan.c"‿"scan", "xa."‿"src/builtins/fold.c"‿"fold", "xag"‿"src/builtins/sort.c"‿"bins" - "x.."‿"src/builtins/select.c"‿"select", "xa."‿"src/builtins/slash.c"‿"constrep", + "x.."‿"src/builtins/select.c"‿"select", "xag"‿"src/builtins/slash.c"‿"constrep", "xag"‿"src/builtins/slash.c"‿"slash", "xa."‿"src/builtins/slash.c"‿"count" ⟩ objs ← ⟨⟩ diff --git a/src/builtins/slash.c b/src/builtins/slash.c index d1dcc5d0..32bc6c4b 100644 --- a/src/builtins/slash.c +++ b/src/builtins/slash.c @@ -86,11 +86,12 @@ #endif #if SINGELI + extern void (*const si_scan_pluswrap_u8)(uint8_t* v0,uint8_t* v1,uint64_t v2,uint8_t v3); + extern void (*const si_scan_pluswrap_u16)(uint16_t* v0,uint16_t* v1,uint64_t v2,uint16_t v3); + extern void (*const si_scan_pluswrap_u32)(uint32_t* v0,uint32_t* v1,uint64_t v2,uint32_t v3); + extern void (*const si_scan_max_i32)(int32_t* v0,int32_t* v1,uint64_t v2); #define SINGELI_FILE slash #include "../utils/includeSingeli.h" -#endif - -#if SINGELI_AVX2 || SINGELI_NEON #define SINGELI_FILE constrep #include "../utils/includeSingeli.h" #endif @@ -100,20 +101,6 @@ #include "../utils/includeSingeli.h" #endif -#if SINGELI - extern void (*const si_scan_pluswrap_u8)(uint8_t* v0,uint8_t* v1,uint64_t v2,uint8_t v3); - extern void (*const si_scan_pluswrap_u16)(uint16_t* v0,uint16_t* v1,uint64_t v2,uint16_t v3); - extern void (*const si_scan_pluswrap_u32)(uint32_t* v0,uint32_t* v1,uint64_t v2,uint32_t v3); - #define ALIAS(I,U) static void si_scan_pluswrap_##I(I* a, I* b, u64 c, I d) { si_scan_pluswrap_##U((U*)a, (U*)b, c, d); } - ALIAS(i8,u8) ALIAS(i16,u16) ALIAS(i32,u32) - #undef ALIAS - #define si_scan_pluswrap_u64(V0,V1,V2,V3) for (usz i=k; i>63, js=-(xx&1); xx^=xx<<1; \ @@ -622,14 +583,13 @@ B slash_c1(B t, B x) { for (u64 j = 0; j < c; j++) *rp++ = i; } } else { + #if SINGELI if (s/32 <= xia) { // Sparse case: type of x matters - #define SPARSE_IND(T) T* xp = T##any_ptr(x); IND_BY_SCAN i32* rp; r = m_i32arrv(&rp, s); - if (xe == el_i8 ) { SPARSE_IND(i8 ); } - else if (xe == el_i16) { SPARSE_IND(i16); } - else { SPARSE_IND(i32); } - #undef SPARSE_IND - } else { // Dense case: only result type matters + si_indices_scan_i32[elwByteLog(xe)](tyany_ptr(x), rp, s); + } else + #endif + { // Dense case: only result type matters #define DENSE_IND(T) \ T* rp; r = m_##T##arrv(&rp, s); \ for (u64 i = 0; i < xia; i++) { \ @@ -748,17 +708,12 @@ B slash_c2(B t, B w, B x) { void* rv = m_tyarrlv(&r, xk, s, xt); if (rsh) { Arr* ra=a(r); SPRNK(ra,xr); ra->sh = rsh; ra->ia = s*arr_csz(x); } void* xv = tyany_ptr(x); + #if SINGELI if ((xk<3? s/64 : s/32) <= wia) { // Sparse case: use both types - #define CASE(L,XT) case L: { REP_BY_SCAN(XT, wp[j]) break; } - #define SPARSE_REP(WT) \ - WT* wp = WT##any_ptr(w); \ - switch (xk) { default: UD; CASE(0,u8) CASE(1,u16) CASE(2,u32) CASE(3,u64) } - if (we == el_i8 ) { SPARSE_REP(i8 ); } - else if (we == el_i16) { SPARSE_REP(i16); } - else { SPARSE_REP(i32); } - #undef SPARSE_REP - #undef CASE - } else { // Dense case: only type of x matters + si_replicate_scan[4*elwByteLog(we) + xk](tyany_ptr(w), xv, rv, s); + } else + #endif + { // Dense case: only type of x matters #define CASE(L,T) case L: { \ T* xp = xv; T* rp = rv; \ for (usz i = 0; i < wia; i++) { \ @@ -845,13 +800,18 @@ B slash_c2(B t, B w, B x) { u8 xk = xl-3; void* rv = m_tyarrv(&r, 1<1} + } else { + scan_core{ + {rp,j,ij} => store{rp,ij,cast_i{i32,j}}, 1, + {ptr,len} => emit{void, 'si_scan_max_i32', ptr,ptr,len}, + rp, xp, s + } + } +} + +def rep_by_scan{T, wp, xv:*void, rv:*void, s} = { + xp := *T~~xv; js := *xp; px := js + def inc{j} = {sx:=px; px=load{xp,j}; px-sx} + indrep_by_sum{T, *T~~rv, wp, s, js, inc} +} +fn rep_by_scan{W, T}(wp:*void, xv:*void, rv:*void, s:usz) : void = { + rep_by_scan{T, *W~~wp, xv, rv, s} +} + +exportT{'si_indices_scan_i32', each{ind_by_scan_i32, ind_types}} +exportT{'si_replicate_scan', flat_table{rep_by_scan, ind_types, dat_types}} + + +# Constant replicate +if (not (hasarch{'AVX2'} | hasarch{'AARCH64'})) { + +fn rep_const{T}(wv:u64, x:*void, r:*void, n:u64) : void = { + rep_by_scan{T, cast_i{usz,wv}, x, r, cast_i{usz, wv*n}} +} + +} else { + def incl{a,b} = slice{iota{b+1},a} # 1+˝∨`⌾⌽0=div|⌜range @@ -220,6 +284,6 @@ fn rep_const{T}(wv:u64, x:*void, r:*void, n:u64) : void = { } } -exportT{'simd_constrep', each{rep_const, tup{i8, i16, i32, u64}}} +} -} \ No newline at end of file +exportT{'si_constrep', each{rep_const, dat_types}}