diff options
author | dzaima <dzaimagit@gmail.com> | 2024-05-20 01:03:45 +0300 |
---|---|---|
committer | dzaima <dzaimagit@gmail.com> | 2024-05-20 01:03:57 +0300 |
commit | 52fb05fcd47364dede4b408f1b28836c44ba585a (patch) | |
tree | 1e4a746600e6be527b57671bca12becbfee5545e | |
parent | 60a28a40ca28f9943a39ee0d8c32b1d75d1889af (diff) |
unify ⌾(a⊸⊏) typed array paths, fix csz==0
-rw-r--r-- | src/builtins/select.c | 86 | ||||
-rw-r--r-- | test/cases/under.bqn | 8 |
2 files changed, 52 insertions, 42 deletions
diff --git a/src/builtins/select.c b/src/builtins/select.c index 3e00d1e0..f8b8e536 100644 --- a/src/builtins/select.c +++ b/src/builtins/select.c @@ -372,14 +372,15 @@ B select_c2(B t, B w, B x) { extern INIT_GLOBAL u8 reuseElType[t_COUNT]; -B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xl, usz xcsz) { // rep⌾(w⊏xl‿xcsz⥊⊢) x, assumes w is a typed (elNum) list of valid indices, only el_f64 if strictly necessary +B select_replace(u32 chr, B w, B x, B rep, usz wia, usz cam, usz csz) { // consumes all; (⥊rep)⌾(⥊w⊏cam‿csz⥊⊢) x; assumes csz>0, that w is a typed (elNum) list of valid indices (squeeze already attempted on el_f64), and that rep has the proper element count + assert(csz > 0); #if CHECK_VALID - TALLOC(bool, set, xl); - bool sparse = wia < xl/64; - if (!sparse) for (i64 i = 0; i < xl; i++) set[i] = false; + TALLOC(bool, set, cam); + bool sparse = wia < cam/64; + if (!sparse) for (i64 i = 0; i < cam; i++) set[i] = false; #define SPARSE_INIT(WI) \ if (sparse) for (usz i = 0; i < wia; i++) { \ - i64 cw = WI; if (RARE(cw<0)) cw+= (i64)xl; set[cw] = false; \ + i64 cw = WI; if (RARE(cw<0)) cw+= (i64)cam; set[cw] = false; \ } #define EQ(ITER,F) if (set[cw]) ITER if (F) thrF("𝔽⌾(a⊸%c): Incompatible result elements", chr); set[cw] = true; #define EQ1(F) EQ(,F) @@ -391,7 +392,7 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xl, usz xcsz) { // rep #define FREE_CHECK #endif - #define READ_W(N,I) i64 N = (i64)wp[I]; if (RARE(N<0)) N+= (i64)xl + #define READ_W(N,I) i64 N = (i64)wp[I]; if (RARE(N<0)) N+= (i64)cam u8 we = TI(w,elType); assert(elNum(we)); u8 xe = TI(x,elType); u8 re = el_or(xe, TI(rep,elType)); @@ -401,11 +402,11 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xl, usz xcsz) { // rep f64* wp = f64any_ptr(w); SPARSE_INIT((i64)wp[i]) - MAKE_MUT(r, xl*xcsz); + MAKE_MUT(r, cam*csz); mut_init_copy(r, x, re); NOGC_E; MUTG_INIT(r); SGet(rep) - if (xcsz==1) { + if (csz==1) { for (usz i = 0; i < wia; i++) { READ_W(cw, i); B cn = Get(rep, i); @@ -416,9 +417,9 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xl, usz xcsz) { // rep } else { for (usz i = 0; i < wia; i++) { READ_W(cw, i); - EQ(for (usz j = 0; j < xcsz; j++),!equal(mut_getU(r, cw*xcsz + j), Get(rep, i*xcsz + j))); - for (usz j = 0; j < xcsz; j++) mut_rm(r, cw*xcsz + j); - mut_copyG(r, cw*xcsz, rep, i*xcsz, xcsz); + EQ(for (usz j = 0; j < csz; j++), !equal(mut_getU(r, cw*csz + j), Get(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); } } ra = mut_fp(r); @@ -430,7 +431,7 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xl, usz xcsz) { // rep i32* wp = i32any_ptr(w); SPARSE_INIT(wp[i]) bool reuse = reusable(x) && re==reuseElType[TY(x)]; - SLOWIF(!reuse && xl>100 && wia<xl/50) SLOW2("⌾(𝕨⊸⊏)𝕩 or ⌾(𝕨⊸⊑)𝕩 because not reusable", w, x); + SLOWIF(!reuse && cam>100 && wia<cam/50) SLOW2("⌾(𝕨⊸⊏)𝕩 or ⌾(𝕨⊸⊑)𝕩 because not reusable", w, x); switch (re) { default: UD; case el_i8: rep = toI8Any(rep); ra = reuse? a(REUSE(x)) : cpyI8Arr(x); goto do_u8; case el_c8: rep = toC8Any(rep); ra = reuse? a(REUSE(x)) : cpyC8Arr(x); goto do_u8; @@ -443,7 +444,7 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xl, usz xcsz) { // rep TyArr* na = toBitArr(rep); rep = taga(na); u64* np = bitarrv_ptr(na); u64* rp = (void*)((TyArr*)ra)->a; - if (xcsz==1) { + if (csz==1) { for (usz i = 0; i < wia; i++) { READ_W(cw, i); bool cn = bitp_get(np, i); @@ -453,8 +454,8 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xl, usz xcsz) { // rep } else { for (usz i = 0; i < wia; i++) { READ_W(cw, i); - EQ(for (usz j = 0; j < xcsz; j++), bitp_get(np, i*xcsz + j) != bitp_get(rp, cw*xcsz + j)); - COPY_TO(rp, el_bit, cw*xcsz, rep, i*xcsz, xcsz); + EQ(for (usz j = 0; j < csz; j++), bitp_get(np, i*csz + j) != bitp_get(rp, cw*csz + j)); + COPY_TO(rp, el_bit, cw*csz, rep, i*csz, csz); } } goto dec_ret_ra; @@ -463,8 +464,7 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xl, usz xcsz) { // rep ra = reuse? a(REUSE(x)) : cpyHArr(x); B* rp = harrP_parts((HArr*)ra).a; SGet(rep) - if (xcsz==1) - { + if (csz==1) { for (usz i = 0; i < wia; i++) { READ_W(cw, i); B cn = Get(rep, i); @@ -475,34 +475,26 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xl, usz xcsz) { // rep } else { for (usz i = 0; i < wia; i++) { READ_W(cw, i); - EQ(for (usz j = 0; j < xcsz; j++), !equal(Get(rep, i*xcsz + j), rp[cw*xcsz + j])); - for (usz j = 0; j < xcsz; j++) dec(rp[cw*xcsz + j]); - COPY_TO(rp, el_B, cw*xcsz, rep, i*xcsz, xcsz); + EQ(for (usz j = 0; j < csz; j++), !equal(Get(rep, i*csz + j), rp[cw*csz + j])); + for (usz j = 0; j < csz; j++) dec(rp[cw*csz + j]); + COPY_TO(rp, el_B, cw*csz, rep, i*csz, csz); } } goto dec_ret_ra; } } - #define IMPL(T) do { \ - T* rp = (void*)((TyArr*)ra)->a; \ - T* np = tyany_ptr(rep); \ - if (xcsz==1) { \ - for (usz i = 0; i < wia; i++) { \ - READ_W(cw, i); \ - T cn = np[i]; \ - EQ1(cn != rp[cw]); \ - rp[cw] = cn; \ - } \ - } else { \ - EqFnObj eq = EQFN_GET(re,re); \ - for (usz i = 0; i < wia; i++) { \ - READ_W(cw, i); \ - EQ1(!EQFN_CALL(eq, rp+cw*xcsz, np+i*xcsz, xcsz)); \ - COPY_TO(rp, re, cw*xcsz, rep, i*xcsz, xcsz); \ - } \ - } \ - goto dec_ret_ra; \ + #define IMPL(T) do { \ + if (csz!=1) goto do_tycell; \ + T* rp = (void*)((TyArr*)ra)->a; \ + T* np = tyany_ptr(rep); \ + for (usz i = 0; i < wia; i++) { \ + READ_W(cw, i); \ + T cn = np[i]; \ + EQ1(cn != rp[cw]); \ + rp[cw] = cn; \ + } \ + goto dec_ret_ra; \ } while(0) do_u8: IMPL(u8); @@ -511,6 +503,18 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xl, usz xcsz) { // rep do_u64: IMPL(u64); #undef IMPL + do_tycell:; + u8 cwidth = csz * elWidth(re); + u8* rp = (u8*) ((TyArr*)ra)->a; + u8* np = tyany_ptr(rep); + EqFnObj eq = EQFN_GET(re,re); + for (usz i = 0; i < wia; i++) { + READ_W(cw, i); + EQ1(!EQFN_CALL(eq, rp + cw*cwidth, np + i*cwidth, csz)); + COPY_TO(rp, re, cw*csz, rep, i*csz, csz); + } + goto dec_ret_ra; + dec_ret_ra:; @@ -546,5 +550,7 @@ B select_ucw(B t, B o, B w, B x) { usz rr = RNK(rep); bool ok = !isAtm(rep) && xr+wr==rr+1 && eqShPart(SH(w),SH(rep),wr) && eqShPart(SH(x)+1,SH(rep)+wr,xr-1); if (!ok) thrF("𝔽⌾(a⊸⊏)𝕩: 𝔽 must return an array with the same shape as its input (%H ≡ shape of a, %2H ≡ shape of ⊏𝕩, %H ≡ shape of result of 𝔽)", w, xr-1, SH(x)+1, rep); - return select_replace(U'⊏', w, x, rep, wia, *SH(x), arr_csz(x)); + usz csz = arr_csz(x); + if (csz == 0) { decG(rep); decG(w); return x; } + return select_replace(U'⊏', w, x, rep, wia, *SH(x), csz); } diff --git a/test/cases/under.bqn b/test/cases/under.bqn index 20837e31..45c8d4c9 100644 --- a/test/cases/under.bqn +++ b/test/cases/under.bqn @@ -1,5 +1,6 @@ %DEF var V←•internal.Variation ⋄ LV←•internal.ListVariations ⋄ CLR←•internal.ClearRefs %DEF tvar %USE var ⋄ _tvar ← {F _𝕣 x: (CLR@) ⊢ {F 𝕩 V x}¨ LV 𝕩; w F _𝕣 x: (CLR@) ⊢ (LV 𝕨) {(𝕨 V w) F 𝕩 V x}⌜ LV 𝕩} +%DEF eqvar %USE tvar ⋄ _eqvar ← {r ← 𝕨 𝔽 _tvar 𝕩 ⋄ !∘≡⟜(⊑r)¨ r ⋄ ⊑r} %DEF evar %USE tvar ⋄ _evar ← {ok←{⇐} ⋄ r←⥊𝕨 ok∘𝔽⎊{𝕊: •CurrentError@} _tvar 𝕩 ⋄ {⊑ok∊r? !"TEST FAIL: variation didn't error"; ("TEST FAIL: varying error messages"⊸⋈ ! 1=≠)⍷r ⋄ !⊑r}} # ¨ & ˘ # !% ⊢⌾(⊢¨) 4 # TODO enable @@ -41,7 +42,7 @@ n←500 ⋄ a←↕n ⋄ i←(-n)+↕2×n ⋄ r←⌽(2×n)⥊a ⋄ ! (⌽a) ≡ 100⊸+⌾(1‿2‿¯4⊸⊏) <¨↕10 %% <¨ 0‿101‿102‿3‿4‿5‿106‿7‿8‿9 100⊸+⌾(1‿2‿¯4⊸⊏) ↕10 %% 0‿101‿102‿3‿4‿5‿106‿7‿8‿9 ⟨10⊸+⌾(1‿2⊸⊏) 0↓a←↕4, a⟩ %% ⟨0‿11‿12‿3,0‿1‿2‿3⟩ -%USE tvar ⋄ !∘≡¨⟜⊏⊸⊢⟜⊑ 0‿0‿1‿1 {𝕨⌾(1‿2‿4‿5⊸⊏) 𝕩} _tvar 1‿0‿1‿0‿1‿0‿1‿1‿0 %% 1‿0‿0‿0‿1‿1‿1‿1‿0 +%USE eqvar ⋄ 0‿0‿1‿1 {𝕨⌾(1‿2‿4‿5⊸⊏) 𝕩} _eqvar 1‿0‿1‿0‿1‿0‿1‿1‿0 %% 1‿0‿0‿0‿1‿1‿1‿1‿0 !"𝔽⌾(a⊸⊏)𝕩: 𝔽 must return an array with the same shape as its input (⟨2⟩ ≡ shape of a, ⟨⟩ ≡ shape of ⊏𝕩, ⟨3⟩ ≡ shape of result of 𝔽)" % 10‿20‿30⌾(2‿3⊸⊏) ↕10 !"𝔽⌾(a⊸⊏)𝕩: 𝔽 must return an array with the same shape as its input (⟨2⟩ ≡ shape of a, ⟨⟩ ≡ shape of ⊏𝕩, ⟨3⟩ ≡ shape of result of 𝔽)" % 1⊸∾⌾(2‿3⊸⊏) ↕10 !"𝔽⌾(a⊸⊏)𝕩: 𝔽 must return an array with the same shape as its input (⟨3⟩ ≡ shape of a, ⟨10⟩ ≡ shape of ⊏𝕩, 2‿10 ≡ shape of result of 𝔽)" % %USE evar ⋄ 1⊸↓⌾(2‿3‿4⊸⊏)_evar 10‿10⥊0 @@ -55,11 +56,14 @@ n←500 ⋄ a←↕n ⋄ i←(-n)+↕2×n ⋄ r←⌽(2×n)⥊a ⋄ ! (⌽a) ≡ !"𝔽⌾(a⊸⊏): Incompatible result elements" % 3‿4⌾(("Ah"•internal.Variation 1‿1)⊸⊏) <¨↕10 !"𝔽⌾(a⊸⊏): Incompatible result elements" % %USE evar ⋄ (27≠↕30) {𝕨⌾((30⥊↕10)⊸⊏) 𝕩} _evar 100⥊1 !"𝔽⌾(a⊸⊏): Incompatible result elements" % %USE evar ⋄ !∘≡¨⟜⊏⊸⊢⟜⊑ {{¬⌾(31‿4⊸⊑)𝕩}∘•internal.Keep⌾((∾10⥊<↕≠𝕩)⊸⊏) 𝕩} _evar 10‿5⥊1‿1‿0‿0‿1‿1 -%USE tvar ⋄ !∘≡¨⟜⊏⊸⊢⟜⊑ {¬⌾((∾10⥊<↕≠𝕩)⊸⊏) 𝕩} _tvar 10‿5⥊1‿1‿0‿0‿1‿1 %% 10‿5⥊0‿0‿1‿1‿0‿0 +%USE eqvar ⋄ {¬⌾((∾10⥊<↕≠𝕩)⊸⊏) 𝕩} _eqvar 10‿5⥊1‿1‿0‿0‿1‿1 %% 10‿5⥊0‿0‿1‿1‿0‿0 20‿20⌾(1‿1⊸⊏) ↕10 %% 0‿20∾2+↕8 100⊸+⌾(1‿2‿¯1⊸⊏) ↕5 %% 0‿101‿102‿3‿104 100⊸+⌾(1‿2‿¯1⊸⊏) <¨↕5 %% <¨ 0‿101‿102‿3‿104 1⊸+⌾(((100⥊↕10)∾10/↕10)⊸⊏) ↕10 %% 1+↕10 +%USE eqvar ⋄ 1⊸+⌾((2/↕5)⊸⊏) _eqvar ↕10 %% <⟜5⊸+ ↕10 +%USE eqvar ⋄ 1⊸+⌾((2/↕5)⊸⊏) _eqvar ≍˘ ↕10 %% ≍˘ <⟜5⊸+ ↕10 +%USE eqvar ⋄ •internal.Keep⌾((2/↕5)⊸⊏) _eqvar 10‿0‿4⥊0 %% 10‿0‿4⥊0 # ⥊ |