From 7dc5aa90908193883713dddabc2c2529a9f09024 Mon Sep 17 00:00:00 2001 From: dzaima Date: Sun, 25 May 2025 18:09:43 +0300 Subject: [PATCH] =?UTF-8?q?more=20complete=20DirectArr=20thing,=20use=20fo?= =?UTF-8?q?r=20=F0=9D=94=BD=E2=8C=BE(f64arr=E2=8A=B8=E2=8A=8F)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/select.c | 70 +++++------------------------------- src/builtins/slash.c | 2 +- src/utils/mut.c | 84 +++++++++++++++++++++++++++++++++++++++++-- src/utils/mut.h | 22 ++++++++++++ test/cases/under.bqn | 2 ++ 5 files changed, 114 insertions(+), 66 deletions(-) diff --git a/src/builtins/select.c b/src/builtins/select.c index 726131ea..9d5aad08 100644 --- a/src/builtins/select.c +++ b/src/builtins/select.c @@ -125,51 +125,6 @@ FORCE_INLINE void cf_call(CFRes f, void* r, ux rs, void* x, ux xs) { f.fn(r, rs, x, xs, f.data); } -extern INIT_GLOBAL u8 reuseElType[t_COUNT]; -typedef struct { B obj; void* data; } DirectArr; -static NOINLINE DirectArr toFillArr(B x, B fill) { - usz ia = IA(x); - Arr* r = arr_shCopy(m_fillarrp(ia), x); - fillarr_setFill(r, fill); - B* rp = fillarrv_ptr(r); - COPY_TO(rp, el_B, 0, x, 0, ia); - NOGC_E; - decG(x); - return (DirectArr){taga(r), rp}; -} -static void* reusableArr_ptr(Arr* t, u8 el) { - return el==el_B? (void*)(PTY(t)==t_fillarr? fillarrv_ptr(t) : harrv_ptr(t)) : tyarrv_ptr((TyArr*)t); -} -static DirectArr toEltypeArr(B x, u8 re) { // consumes x; returns an array with eltype==re, with same shape/elements/fill as x, and its data pointer - assert(isArr(x)); - if (reusable(x) && re==reuseElType[TY(x)]) { - x = REUSE(x); - return (DirectArr){x, reusableArr_ptr(a(x), re)}; - } - - Arr* tyarr; - switch (re) { default: UD; - case el_bit: tyarr = cpyBitArr(x); goto tyarr; - case el_i8: tyarr = cpyI8Arr(x); goto tyarr; - case el_i16: tyarr = cpyI16Arr(x); goto tyarr; - case el_i32: tyarr = cpyI32Arr(x); goto tyarr; - case el_f64: tyarr = cpyF64Arr(x); goto tyarr; - case el_c8: tyarr = cpyC8Arr(x); goto tyarr; - case el_c16: tyarr = cpyC16Arr(x); goto tyarr; - case el_c32: tyarr = cpyC32Arr(x); goto tyarr; - case el_B:; - B fill = getFillR(x); - if (noFill(fill)) { - Arr* r = cpyHArr(x); - return (DirectArr){taga(r), harrv_ptr(r)}; - } - return toFillArr(x, fill); - } - - tyarr: - return (DirectArr){taga(tyarr), tyarrv_ptr((TyArr*) tyarr)}; -} - extern GLOBAL B rt_select; @@ -513,40 +468,33 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz cam, usz csz) { // consu u8 we = TI(w,elType); assert(elNum(we) || wia==0); u8 xe = TI(x,elType); u8 re = el_or(xe, TI(rep,elType)); - Arr* ra; B rb; // w = taga(cpyF64Arr(w)); we = el_f64; // test the float path + DIRECTARR_COPY(r, re, x); + B rb = r.obj; + if (we==el_f64) { f64* wp = f64any_ptr(w); SPARSE_INIT((i64)wp[i]) - - MAKE_MUT(r, cam*csz); - mut_init_copy(r, x, re); - NOGC_E; - MUTG_INIT(r); if (csz==1) { SGet(rep) for (usz i = 0; i < wia; i++) { READ_W(cw, i); B cn = Get(rep, i); - EQ1(!compatible(mut_getU(r, cw), cn)); - mut_rm(r, cw); - mut_setG(r, cw, cn); + EQ1(!compatible(DIRECTARR_GETU(r, cw), cn)); + DIRECTARR_REPLACE(r, cw, cn); } } else { SGetU(rep) for (usz i = 0; i < wia; i++) { READ_W(cw, i); - EQ(for (usz j = 0; j < csz; j++), !compatible(mut_getU(r, cw*csz + j), GetU(rep, i*csz + j))); - for (usz j = 0; j < csz; j++) mut_rm(r, cw*csz + j); - mut_copyG(r, cw*csz, rep, i*csz, csz); + EQ(for (usz j = 0; j < csz; j++), !compatible(DIRECTARR_GETU(r, cw*csz + j), GetU(rep, i*csz + j))); + DIRECTARR_REPLACE_RANGE(r, cw*csz, rep, i*csz, csz); } } - ra = mut_fp(r); - goto dec_ret_ra; + goto dec_ret_rb; } assert(elInt(we) || wia==0); - DirectArr r = toEltypeArr(x, re); rb = r.obj; w = toI32Any(w); i32* wp = i32any_ptr(w); SPARSE_INIT(wp[i]) @@ -638,8 +586,6 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz cam, usz csz) { // consu - dec_ret_ra:; - rb = taga(ra); dec_ret_rb:; decG(w); decG(rep); FREE_CHECK; diff --git a/src/builtins/slash.c b/src/builtins/slash.c index 7a9be56a..e43199c0 100644 --- a/src/builtins/slash.c +++ b/src/builtins/slash.c @@ -1089,7 +1089,7 @@ B slash_ucw(B t, B o, B w, B x) { #if SINGELI_SIMD if (isFun(o) && TY(o)==t_md1D) { u8 xe = TI(x,elType); - if (xe==el_B) goto notConstEach; + if (xe==el_B) goto notConstEach; // TODO not Md1D* od = c(Md1D,o); if (PRTID(od->m1) != n_each) goto notConstEach; diff --git a/src/utils/mut.c b/src/utils/mut.c index 19bdd3cc..322b1e77 100644 --- a/src/utils/mut.c +++ b/src/utils/mut.c @@ -800,12 +800,79 @@ NOINLINE void apd_widen(ApdMut* m, B x, ApdFn* const* fns) { +static NOINLINE DirectArr toFillArr(B x, B fill) { + usz ia = IA(x); + Arr* r = arr_shCopy(m_fillarrp(ia), x); + fillarr_setFill(r, fill); + B* rp = fillarrv_ptr(r); + COPY_TO(rp, el_B, 0, x, 0, ia); + NOGC_E; + decG(x); + return (DirectArr){taga(r), rp}; +} +static void* reusableArr_ptr(Arr* t, u8 el) { + return el==el_B? (void*)(PTY(t)==t_fillarr? fillarrv_ptr(t) : harrv_ptr(t)) : tyarrv_ptr((TyArr*)t); +} +DirectArr toEltypeArr(B x, u8 re) { // consumes x; returns an array with eltype==re, with same shape/elements/fill as x, and its data pointer + assert(isArr(x)); + if (reusable(x) && re==reuseElType[TY(x)]) { + x = REUSE(x); + return (DirectArr){x, reusableArr_ptr(a(x), re)}; + } + + Arr* tyarr; + switch (re) { default: UD; + case el_bit: tyarr = cpyBitArr(x); goto tyarr; + case el_i8: tyarr = cpyI8Arr(x); goto tyarr; + case el_i16: tyarr = cpyI16Arr(x); goto tyarr; + case el_i32: tyarr = cpyI32Arr(x); goto tyarr; + case el_f64: tyarr = cpyF64Arr(x); goto tyarr; + case el_c8: tyarr = cpyC8Arr(x); goto tyarr; + case el_c16: tyarr = cpyC16Arr(x); goto tyarr; + case el_c32: tyarr = cpyC32Arr(x); goto tyarr; + case el_B:; + B fill = getFillR(x); + if (noFill(fill)) { + Arr* r = cpyHArr(x); + return (DirectArr){taga(r), harrv_ptr(r)}; + } + return toFillArr(x, fill); + } + + tyarr: + return (DirectArr){taga(tyarr), tyarrv_ptr((TyArr*) tyarr)}; +} +B directGetU_bit(void* data, ux i) { return m_f64(bitp_get(data,i));} void directSet_bit(void* data, ux i, B v) { bitp_set(data, i, o2bG(v)); } +B directGetU_i8 (void* data, ux i) { return m_f64((( i8*)data)[i]); } void directSet_i8 (void* data, ux i, B v) { (( i8*)data)[i] = o2iG(v); } +B directGetU_i16(void* data, ux i) { return m_f64(((i16*)data)[i]); } void directSet_i16(void* data, ux i, B v) { ((i16*)data)[i] = o2iG(v); } +B directGetU_i32(void* data, ux i) { return m_f64(((i32*)data)[i]); } void directSet_i32(void* data, ux i, B v) { ((i32*)data)[i] = o2iG(v); } +B directGetU_f64(void* data, ux i) { return m_f64(((f64*)data)[i]); } void directSet_f64(void* data, ux i, B v) { ((f64*)data)[i] = o2fG(v); } +B directGetU_c8 (void* data, ux i) { return m_c32((( u8*)data)[i]); } void directSet_c8 (void* data, ux i, B v) { (( u8*)data)[i] = o2cG(v); } +B directGetU_c16(void* data, ux i) { return m_c32(((u16*)data)[i]); } void directSet_c16(void* data, ux i, B v) { ((u16*)data)[i] = o2cG(v); } +B directGetU_c32(void* data, ux i) { return m_c32(((u32*)data)[i]); } void directSet_c32(void* data, ux i, B v) { ((u32*)data)[i] = o2cG(v); } +B directGetU_B (void* data, ux i) { return ((B*)data)[i]; } void directSet_B (void* data, ux i, B v) { B* p = i+(B*)data; dec(*p); *p = v; } + +void directSetRange_bit(void* data, ux rs, B x, ux xs, ux l) { COPY_TO(data, el_bit, rs, x, xs, l); } +void directSetRange_i8 (void* data, ux rs, B x, ux xs, ux l) { COPY_TO(data, el_i8 , rs, x, xs, l); } +void directSetRange_i16(void* data, ux rs, B x, ux xs, ux l) { COPY_TO(data, el_i16, rs, x, xs, l); } +void directSetRange_i32(void* data, ux rs, B x, ux xs, ux l) { COPY_TO(data, el_i32, rs, x, xs, l); } +void directSetRange_f64(void* data, ux rs, B x, ux xs, ux l) { COPY_TO(data, el_f64, rs, x, xs, l); } +void directSetRange_c8 (void* data, ux rs, B x, ux xs, ux l) { COPY_TO(data, el_c8 , rs, x, xs, l); } +void directSetRange_c16(void* data, ux rs, B x, ux xs, ux l) { COPY_TO(data, el_c16, rs, x, xs, l); } +void directSetRange_c32(void* data, ux rs, B x, ux xs, ux l) { COPY_TO(data, el_c32, rs, x, xs, l); } +void directSetRange_B (void* data, ux rs, B x, ux xs, ux l) { + for (ux i = 0; i < l; i++) dec(((B*)data)[rs+i]); + COPY_TO(data, el_B, rs, x, xs, l); +} INIT_GLOBAL M_CopyF copyFns[el_MAX]; INIT_GLOBAL M_FillF fillFns[el_MAX]; INIT_GLOBAL MutFns mutFns[el_MAX+1]; INIT_GLOBAL u8 el_orArr[el_MAX*16 + el_MAX+1]; +INIT_GLOBAL DirectGet directGetU[el_MAX]; +INIT_GLOBAL DirectSet directSet[el_MAX]; +INIT_GLOBAL DirectSetRange directSetRange[el_MAX]; void mutF_init(void) { for (u8 i = 0; i <= el_MAX; i++) { for (u8 j = 0; j <= el_MAX; j++) { @@ -826,15 +893,26 @@ void mutF_init(void) { for (ux i = 0; i < t_COUNT; i++) reuseElType[i] = el_MAX; mutFns[el_bit].elType = el_bit; mutFns[el_bit].valType = t_bitarr; reuseElType[t_bitarr] = el_bit; - mutFns[el_i8 ].elType = el_i8 ; mutFns[el_i8 ].valType = t_i8arr; reuseElType[t_i8arr] = el_i8; + mutFns[el_i8 ].elType = el_i8 ; mutFns[el_i8 ].valType = t_i8arr; reuseElType[t_i8arr ] = el_i8; mutFns[el_i16].elType = el_i16; mutFns[el_i16].valType = t_i16arr; reuseElType[t_i16arr] = el_i16; mutFns[el_i32].elType = el_i32; mutFns[el_i32].valType = t_i32arr; reuseElType[t_i32arr] = el_i32; - mutFns[el_c8 ].elType = el_c8 ; mutFns[el_c8 ].valType = t_c8arr; reuseElType[t_c8arr] = el_c8; + mutFns[el_c8 ].elType = el_c8 ; mutFns[el_c8 ].valType = t_c8arr; reuseElType[t_c8arr ] = el_c8; mutFns[el_c16].elType = el_c16; mutFns[el_c16].valType = t_c16arr; reuseElType[t_c16arr] = el_c16; mutFns[el_c32].elType = el_c32; mutFns[el_c32].valType = t_c32arr; reuseElType[t_c32arr] = el_c32; mutFns[el_f64].elType = el_f64; mutFns[el_f64].valType = t_f64arr; reuseElType[t_f64arr] = el_f64; - mutFns[el_B ].elType = el_B ; mutFns[el_B ].valType = t_harr; reuseElType[t_harr] = el_B; + mutFns[el_B ].elType = el_B ; mutFns[el_B ].valType = t_harr; reuseElType[t_harr ] = el_B; /* and fillarr also to complete being able to reuse any target */ reuseElType[t_fillarr]= el_B; + + directGetU[el_bit] = directGetU_bit; directSet[el_bit] = directSet_bit; directSetRange[el_bit] = directSetRange_bit; + directGetU[el_i8 ] = directGetU_i8; directSet[el_i8 ] = directSet_i8; directSetRange[el_i8 ] = directSetRange_i8; + directGetU[el_i16] = directGetU_i16; directSet[el_i16] = directSet_i16; directSetRange[el_i16] = directSetRange_i16; + directGetU[el_i32] = directGetU_i32; directSet[el_i32] = directSet_i32; directSetRange[el_i32] = directSetRange_i32; + directGetU[el_c8 ] = directGetU_c8; directSet[el_c8 ] = directSet_c8; directSetRange[el_c8 ] = directSetRange_c8; + directGetU[el_c16] = directGetU_c16; directSet[el_c16] = directSet_c16; directSetRange[el_c16] = directSetRange_c16; + directGetU[el_c32] = directGetU_c32; directSet[el_c32] = directSet_c32; directSetRange[el_c32] = directSetRange_c32; + directGetU[el_f64] = directGetU_f64; directSet[el_f64] = directSet_f64; directSetRange[el_f64] = directSetRange_f64; + directGetU[el_B ] = directGetU_B; directSet[el_B ] = directSet_B; directSetRange[el_B ] = directSetRange_B; + mutFns[el_MAX].elType = el_MAX; mutFns[el_MAX].valType = t_COUNT; for (u8 i = 0; i < el_MAX; i++) copyFns[i] = mutFns[i].m_copyG; for (u8 i = 0; i < el_MAX; i++) fillFns[i] = mutFns[i].m_fillG; diff --git a/src/utils/mut.h b/src/utils/mut.h index ff45248f..c74a1259 100644 --- a/src/utils/mut.h +++ b/src/utils/mut.h @@ -281,3 +281,25 @@ ApdFn apd_tot_init, apd_sh_init, apd_reshape; #define APDD(M, A) ({ B av_ = (A); M.apd(&M, av_); dec(av_); }) // consumes A #define APD_SH_GET(M, TY) (M.end(&M, TY)) #define APD_TOT_GET(M) (M.obj) + + + +typedef struct { B obj; void* data; } DirectArr; +typedef B (*DirectGet)(void* data, ux i); +typedef void (*DirectSet)(void* data, ux i, B v); +typedef void (*DirectSetRange)(void* data, ux rs, B x, ux xs, ux l); +extern INIT_GLOBAL DirectGet directGetU[el_MAX]; +extern INIT_GLOBAL DirectSet directSet[el_MAX]; +extern INIT_GLOBAL DirectSetRange directSetRange[el_MAX]; +DirectArr toEltypeArr(B x, u8 re); +#define DIRECTARR_COPY(R, RE, X) \ + u8 R##_elt = RE; \ + DirectArr R = toEltypeArr(X, R##_elt); \ + DirectGet R##_getU = directGetU[R##_elt]; \ + DirectSet R##_set = directSet[R##_elt]; \ + DirectSetRange R##_setRange = directSetRange[R##_elt]; + +#define DIRECTARR_RM(R, I) if (R##_elt == el_B) dec(((B*)R.data)[I]); +#define DIRECTARR_GETU(R, I) R##_getU(R.data, I) +#define DIRECTARR_REPLACE(R, I, V) R##_set(R.data, I, V) +#define DIRECTARR_REPLACE_RANGE(R, RS, X, XS, L) R##_setRange(R.data, RS, X, XS, L) diff --git a/test/cases/under.bqn b/test/cases/under.bqn index cbb390fe..74cab646 100644 --- a/test/cases/under.bqn +++ b/test/cases/under.bqn @@ -173,6 +173,8 @@ n←500 ⋄ a←↕n ⋄ i←(-n)+↕2×n ⋄ r←⌽(2×n)⥊a ⋄ ! (⌽a) ≡ 10⊸+⌾(⟨1,0‿1⟩⊸/)↕2‿2 %% 2‿2⥊⟨0‿0,10‿11,1‿0,11‿11⟩ !"𝔽⌾(a⊸/): Incompatible result elements" % 1‿2⌾(2‿0⊸/)↕2 1⊸+⌾((↕10)⊸/) ↕10 %% ×⊸+ ↕10 +%USE eqvar ⋄ <‿≥‿> {𝕨⌾(1‿0‿0‿1‿1⊸/) 𝕩}_eqvar +‿-‿×‿÷‿⋆ %% <‿-‿×‿≥‿> +%USE eqvar ⋄ ["wx"‿"WX","yz"‿"YZ"] {𝕨⌾(1‿0‿0‿1⊸/) 𝕩}_eqvar (<"aA")+↕4‿2 %% 4‿2⥊⟨"wx","WX","bA","bB","cA","cB","yz","YZ"⟩ !"Integer out of range: 3.68934881474191e19" % 1¨⌾(a⊸/) a←100⥊2⋆65 !"Expected non-negative integer, got ¯10" % %USE evar ⋄ 1¨⌾(a⊸/)_evar a←¯10⌾(50⊸⊑) 100⥊10