diff options
-rw-r--r-- | src/builtins/compare.c | 7 | ||||
-rw-r--r-- | src/builtins/select.c | 117 | ||||
-rw-r--r-- | src/builtins/sfns.c | 4 | ||||
-rw-r--r-- | src/singeli/src/equal.singeli | 1 | ||||
-rw-r--r-- | src/singeli/src/mask.singeli | 1 | ||||
-rw-r--r-- | src/utils/calls.h | 3 | ||||
-rw-r--r-- | test/cases/perf.bqn | 7 | ||||
-rw-r--r-- | test/cases/under.bqn | 24 |
8 files changed, 114 insertions, 50 deletions
diff --git a/src/builtins/compare.c b/src/builtins/compare.c index a8b5268f..f55831cf 100644 --- a/src/builtins/compare.c +++ b/src/builtins/compare.c @@ -107,13 +107,14 @@ u8 const eqFnData[] = { // for the main diagonal, amount to shift length by; oth #else #define F(X) equal_##X bool F(1_1)(void* w, void* x, u64 l, u64 d) { + assert(l>0); u64* wp = w; u64* xp = x; usz q = l/64; for (usz i=0; i<q; i++) if (wp[i] != xp[i]) return false; usz r = (-l)%64; return r==0 || (wp[q]^xp[q])<<r == 0; } #define DEF_EQ_U1(N, T) \ - bool F(1_##N)(void* w, void* x, u64 l, u64 d) { \ + bool F(1_##N)(void* w, void* x, u64 l, u64 d) { assert(l>0); \ if (d!=0) { void* t=w; w=x; x=t; } \ u64* wp = w; T* xp = x; \ for (usz i=0; i<l; i++) if (bitp_get(wp,i)!=xp[i]) return false; \ @@ -127,7 +128,7 @@ u8 const eqFnData[] = { // for the main diagonal, amount to shift length by; oth #define DEF_EQ_I(NAME, S, T, INIT) \ bool F(NAME)(void* w, void* x, u64 l, u64 d) { \ - INIT \ + assert(l>0); INIT \ S* wp = w; T* xp = x; \ for (usz i=0; i<l; i++) if (wp[i]!=xp[i]) return false; \ return true; \ @@ -143,7 +144,7 @@ u8 const eqFnData[] = { // for the main diagonal, amount to shift length by; oth #undef DEF_EQ_I #undef DEF_EQ #endif -bool notEq(void* a, void* b, u64 l, u64 data) { return false; } +bool notEq(void* a, void* b, u64 l, u64 data) { assert(l>0); return false; } INIT_GLOBAL EqFn eqFns[] = { F(1_1), F(1_8), F(1_16), F(1_32), F(1_f64), notEq, notEq, notEq, F(1_8), F(8_8), F(s8_16), F(s8_32), F(s8_f64), notEq, notEq, notEq, diff --git a/src/builtins/select.c b/src/builtins/select.c index 3665dbaa..f8b8e536 100644 --- a/src/builtins/select.c +++ b/src/builtins/select.c @@ -372,24 +372,27 @@ 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 xia) { // rep⌾(w⊏⥊) 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, xia); - bool sparse = wia < xia/64; - if (!sparse) for (i64 i = 0; i < xia; 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)xia; set[cw] = false; \ + if (sparse) for (usz i = 0; i < wia; i++) { \ + i64 cw = WI; if (RARE(cw<0)) cw+= (i64)cam; set[cw] = false; \ } - #define EQ(F) if (set[cw] && (F)) thrF("𝔽⌾(a⊸%c): Incompatible result elements", chr); set[cw] = true; + #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) #define FREE_CHECK TFREE(set) #else #define SPARSE_INIT(GET) - #define EQ(F) + #define EQ(ITER,F) + #define EQ1(F) #define FREE_CHECK #endif - #define READ_W(N,I) i64 N = (i64)wp[I]; if (RARE(N<0)) N+= (i64)xia + #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)); @@ -399,16 +402,25 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xia) { // rep⌾(w⊏⥊ f64* wp = f64any_ptr(w); SPARSE_INIT((i64)wp[i]) - MAKE_MUT(r, xia); + MAKE_MUT(r, cam*csz); mut_init_copy(r, x, re); NOGC_E; MUTG_INIT(r); SGet(rep) - for (usz i = 0; i < wia; i++) { - READ_W(cw, i); - B cn = Get(rep, i); - EQ(!equal(mut_getU(r, cw), cn)); - mut_rm(r, cw); - mut_setG(r, cw, cn); + if (csz==1) { + for (usz i = 0; i < wia; i++) { + READ_W(cw, i); + B cn = Get(rep, i); + EQ1(!equal(mut_getU(r, cw), cn)); + mut_rm(r, cw); + mut_setG(r, cw, cn); + } + } else { + for (usz i = 0; i < wia; i++) { + READ_W(cw, i); + 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); goto dec_ret_ra; @@ -419,7 +431,7 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xia) { // rep⌾(w⊏⥊ i32* wp = i32any_ptr(w); SPARSE_INIT(wp[i]) bool reuse = reusable(x) && re==reuseElType[TY(x)]; - SLOWIF(!reuse && xia>100 && wia<xia/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; @@ -432,11 +444,19 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xia) { // rep⌾(w⊏⥊ TyArr* na = toBitArr(rep); rep = taga(na); u64* np = bitarrv_ptr(na); u64* rp = (void*)((TyArr*)ra)->a; - for (usz i = 0; i < wia; i++) { - READ_W(cw, i); - bool cn = bitp_get(np, i); - EQ(cn != bitp_get(rp, cw)); - bitp_set(rp, cw, cn); + if (csz==1) { + for (usz i = 0; i < wia; i++) { + READ_W(cw, i); + bool cn = bitp_get(np, i); + EQ1(cn != bitp_get(rp, cw)); + bitp_set(rp, cw, cn); + } + } else { + for (usz i = 0; i < wia; i++) { + READ_W(cw, i); + 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; } @@ -444,27 +464,37 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xia) { // rep⌾(w⊏⥊ ra = reuse? a(REUSE(x)) : cpyHArr(x); B* rp = harrP_parts((HArr*)ra).a; SGet(rep) - for (usz i = 0; i < wia; i++) { - READ_W(cw, i); - B cn = Get(rep, i); - EQ(!equal(cn,rp[cw])); - dec(rp[cw]); - rp[cw] = cn; + if (csz==1) { + for (usz i = 0; i < wia; i++) { + READ_W(cw, i); + B cn = Get(rep, i); + EQ1(!equal(cn,rp[cw])); + dec(rp[cw]); + rp[cw] = cn; + } + } else { + for (usz i = 0; i < wia; i++) { + READ_W(cw, i); + 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 { \ + 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]; \ - EQ(cn != rp[cw]); \ + EQ1(cn != rp[cw]); \ rp[cw] = cn; \ } \ - goto dec_ret_ra; \ + goto dec_ret_ra; \ } while(0) do_u8: IMPL(u8); @@ -473,6 +503,18 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xia) { // rep⌾(w⊏⥊ 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:; @@ -482,11 +524,12 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xia) { // rep⌾(w⊏⥊ #undef SPARSE_INIT #undef EQ + #undef EQ1 #undef FREE_CHECK } B select_ucw(B t, B o, B w, B x) { - if (isAtm(x) || RNK(x)!=1 || isAtm(w)) { def: return def_fn_ucw(t, o, w, x); } + if (isAtm(x) || isAtm(w)) { def: return def_fn_ucw(t, o, w, x); } usz xia = IA(x); usz wia = IA(w); u8 we = TI(w,elType); @@ -495,13 +538,19 @@ B select_ucw(B t, B o, B w, B x) { if (!elNum(we)) goto def; } B rep; - if (isArr(o)) { + if (isArr(o) && RNK(x)>0) { i64 buf[2]; if (wia!=0 && (!getRange_fns[we](tyany_ptr(w), buf, wia) || buf[0]<-(i64)xia || buf[1]>=xia)) thrF("𝔽⌾(a⊸⊏)𝕩: Indexing out-of-bounds (%l∊a, %H≡≢𝕩)", buf[1]>=xia?buf[1]:buf[0], x); rep = incG(o); } else { rep = c1(o, C2(select, incG(w), incG(x))); } - if (isAtm(rep) || !eqShape(w, rep)) thrF("𝔽⌾(a⊸⊏)𝕩: 𝔽 must return an array with the same shape as its input (expected %H, got %H)", w, rep); - return select_replace(U'⊏', w, x, rep, wia, xia); + usz xr = RNK(x); + usz wr = RNK(w); + 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); + 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/src/builtins/sfns.c b/src/builtins/sfns.c index 0a9109a5..952b27f9 100644 --- a/src/builtins/sfns.c +++ b/src/builtins/sfns.c @@ -1302,7 +1302,7 @@ B pick_uc1(B t, B o, B x) { -B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xia); +B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xl, usz xcia); B select_ucw(B t, B o, B w, B x); B select_c2(B,B,B); B pick_ucw(B t, B o, B w, B x) { @@ -1329,7 +1329,7 @@ B pick_ucw(B t, B o, B w, B x) { w = num_squeeze(mut_fcd(r, w)); B rep = isArr(o)? incG(o) : c1(o, C2(select, incG(w), C1(shape, incG(x)))); if (isAtm(rep) || !eqShape(w, rep)) thrF("𝔽⌾(a⊸⊑)𝕩: 𝔽 must return an array with the same shape as its input (expected %H, got %H)", w, rep); - return select_replace(U'⊑', w, x, rep, wia, xia); + return select_replace(U'⊑', w, x, rep, wia, xia, 1); } decG(w); } diff --git a/src/singeli/src/equal.singeli b/src/singeli/src/equal.singeli index b80eb02d..3bdd7ff2 100644 --- a/src/singeli/src/equal.singeli +++ b/src/singeli/src/equal.singeli @@ -15,6 +15,7 @@ fn equal{W, X}(w:*void, x:*void, l:u64, d:u64) : u1 = { def vw = arch_defvw def bulk = vw / width{X} if (W!=X) if (d!=0) swap{w,x} + assert{l>0} if (W==u1) { if (X==u1) { # bitarr ≡ bitarr diff --git a/src/singeli/src/mask.singeli b/src/singeli/src/mask.singeli index d9979b7d..adc575e2 100644 --- a/src/singeli/src/mask.singeli +++ b/src/singeli/src/mask.singeli @@ -103,6 +103,7 @@ def maskedLoop{bulk} = maskedLoop{bulk,0} def maskedLoopPositive{bulk}{vars,begin==0,end:L,iter} = { + assert{end > 0} i:L = 0 while(i < (end-1)/bulk) { mlExec{i, iter, vars, bulk, maskNone} diff --git a/src/utils/calls.h b/src/utils/calls.h index d38cf376..137b8810 100644 --- a/src/utils/calls.h +++ b/src/utils/calls.h @@ -26,14 +26,13 @@ CMP_DEF(le, AS); #define CMP_AA_IMM(FN, ELT, WHERE, WP, XP, LEN) CMP_AA_CALL(CMP_AA_FN(FN, ELT), WHERE, WP, XP, LEN) #define CMP_AS_IMM(FN, ELT, WHERE, WP, X, LEN) CMP_AS_CALL(CMP_AS_FN(FN, ELT), WHERE, WP, X, LEN) -// Check if the l elements starting at a and b match typedef bool (*EqFn)(void* a, void* b, u64 l, u64 data); extern INIT_GLOBAL EqFn eqFns[]; extern u8 const eqFnData[]; #define EQFN_INDEX(W_ELT, X_ELT) ((W_ELT)*8 + (X_ELT)) typedef struct { EqFn fn; u8 data; } EqFnObj; #define EQFN_GET(W_ELT, X_ELT) ({ u8 eqfn_i_ = EQFN_INDEX(W_ELT, X_ELT); (EqFnObj){.fn=eqFns[eqfn_i_], .data=eqFnData[eqfn_i_]}; }) -#define EQFN_CALL(FN, W, X, L) (FN).fn(W, X, L, (FN).data) +#define EQFN_CALL(FN, W, X, L) (FN).fn(W, X, L, (FN).data) // check if L elements starting at a and b match; assumes L≥1 typedef bool (*RangeFn)(void* xp, i64* res, u64 len); // writes min,max in res, assumes len≥1; returns 0 and leaves res undefined if either any (floor(x)≠x or abs>2⋆53), or (x≠(i64)x) extern INIT_GLOBAL RangeFn getRange_fns[el_f64+1]; // limited to ≤el_f64 diff --git a/test/cases/perf.bqn b/test/cases/perf.bqn index fec72971..0a1ca625 100644 --- a/test/cases/perf.bqn +++ b/test/cases/perf.bqn @@ -29,11 +29,16 @@ # in-place ⌾⊑ %USE fastone ⋄ a←5+↕1e6 ⋄ n←{𝕊: a 1⊸+⌾⊑↩}_fastone 4 ⋄ ! (10↑a) ≡ (5+n)∾6+↕9 -# in-place ⌾(l⊸⊏) +# in-place ⌾(l⊸⊏) list %USE fastone ⋄ a←⋈¨5+↕1e6 ⋄ n←{𝕊: a 1⊸+⌾(1‿3‿3‿¯1⊸⊏)↩}_fastone 4 ⋄ ! (⋈¨5‿6‿7‿8‿9‿1000000‿1000001‿1000002‿1000003‿1000004+0‿n‿0‿n‿0‿0‿0‿0‿0‿n) ≡ (5↑a)∾¯5↑a #%NDEBUG %USE fastone ⋄ a←5+↕1e6 ⋄ n←{𝕊: a 1⊸+⌾(1‿3‿3‿¯1⊸⊏)↩}_fastone 4 ⋄ ! ( 5‿6‿7‿8‿9‿1000000‿1000001‿1000002‿1000003‿1000004+0‿n‿0‿n‿0‿0‿0‿0‿0‿n) ≡ (5↑a)∾¯5↑a #%NDEBUG %USE fastone ⋄ a←5+1e6⥊@+↕10000 ⋄ n←{𝕊: a 1⊸+⌾(1‿3‿3‿¯1⊸⊏)↩}_fastone 4 ⋄ ! (@+5‿6‿7‿8‿9‿10000‿10001‿10002‿10003‿10004 +0‿n‿0‿n‿0‿0‿0‿0‿0‿n) ≡ (5↑a)∾¯5↑a #%NDEBUG +# in-place ⌾(l⊸⊏) highrank +%USE fastone ⋄ a←∘‿2‿2⥊⋈¨5+↕1e6 ⋄ n←{𝕊: a 1⊸+⌾(1‿3‿3‿¯1⊸⊏)↩}_fastone 4 ⋄ ! a ≡ (n×⟨1,3,¯1+≠a⟩∊˜↕≠a) + ∘‿2‿2⥊⋈¨5+↕1e6 #%NDEBUG +%USE fastone ⋄ a←∘‿2‿2⥊5+↕1e6 ⋄ n←{𝕊: a 1⊸+⌾(1‿3‿3‿¯1⊸⊏)↩}_fastone 4 ⋄ ! a ≡ (n×⟨1,3,¯1+≠a⟩∊˜↕≠a) + ∘‿2‿2⥊5+↕1e6 #%NDEBUG +%USE fastone ⋄ a←∘‿2‿2⥊5+1e6⥊@+↕10000 ⋄ n←{𝕊: a 1⊸+⌾(1‿3‿3‿¯1⊸⊏)↩}_fastone 4 ⋄ ! a ≡ (n×⟨1,3,¯1+≠a⟩∊˜↕≠a) + ∘‿2‿2⥊5+1e6⥊@+↕10000 #%NDEBUG + # in-place ∾⟜atom & ∾⟜list %USE fastone ⋄ %USE tvar2 ⋄ {𝕊v: j←<⍟(×≡) v ⋄ {a←𝕩 ⋄ n←{𝕊: a∾↩j}_fastone 4 ⋄ !( n +≠𝕩)≡≠a ⋄ !a≡v¨a}_tvar2_"f" 1e6 ⥊<𝕩}¨ ⟨1, 1‿2, 'a'⟩ %USE fastone ⋄ %USE tvar2 ⋄ {𝕊v: j←10⥊<v ⋄ {a←𝕩 ⋄ n←{𝕊: a∾↩j}_fastone 4 ⋄ !((10×n)+≠𝕩)≡≠a ⋄ !a≡v¨a}_tvar2_"f" 1e6 ⥊<𝕩}¨ ⟨1, 1‿2, 'a'⟩ diff --git a/test/cases/under.bqn b/test/cases/under.bqn index e3b8fff1..45c8d4c9 100644 --- a/test/cases/under.bqn +++ b/test/cases/under.bqn @@ -1,20 +1,17 @@ %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 # !% ⊢⌾(⊢˘) 4 # TODO enable -# ⊏ & ⊑ -!"𝔽⌾(a⊸⊑): Incompatible result elements" % 10‿20⌾(⟨1‿2,1‿2⟩⊸⊑) 4‿5⥊↕9 -!"𝔽⌾(a⊸⊏): Incompatible result elements" % 10‿20⌾(3‿3⊸⊏) ↕10 -!"𝔽⌾(a⊸⊏)𝕩: 𝔽 must return an array with the same shape as its input (expected ⟨2⟩, got ⟨3⟩)" % 10‿20‿30⌾(2‿3⊸⊏) ↕10 -!"𝔽⌾(a⊸⊏)𝕩: 𝔽 must return an array with the same shape as its input (expected ⟨2⟩, got ⟨3⟩)" % 1⊸∾⌾(2‿3⊸⊏) ↕10 -!"𝔽⌾(a⊸⊑)𝕩: 𝔽 must return an array with the same shape as its input (expected ⟨2⟩, got ⟨3⟩)" % 10‿20‿30⌾(⟨1‿2,2‿1⟩⊸⊑) 4‿4⥊↕16 -!"𝔽⌾(a⊸⊑)𝕩: 𝔽 must return an array with the same shape as its input (expected ⟨2⟩, got ⟨3⟩)" % 1⊸∾⌾(⟨1‿2,2‿1⟩⊸⊑) 4‿4⥊↕16 # ⊑ +!"𝔽⌾(a⊸⊑): Incompatible result elements" % 10‿20⌾(⟨1‿2,1‿2⟩⊸⊑) 4‿5⥊↕9 +!"𝔽⌾(a⊸⊑)𝕩: 𝔽 must return an array with the same shape as its input (expected ⟨2⟩, got ⟨3⟩)" % 10‿20‿30⌾(⟨1‿2,2‿1⟩⊸⊑) 4‿4⥊↕16 +!"𝔽⌾(a⊸⊑)𝕩: 𝔽 must return an array with the same shape as its input (expected ⟨2⟩, got ⟨3⟩)" % 1⊸∾⌾(⟨1‿2,2‿1⟩⊸⊑) 4‿4⥊↕16 !"𝔽⌾(n⊸⊑)𝕩: reading out-of-bounds (n≡¯10, 3≡≠𝕩)" % 1⊸+⌾(¯10⊸⊑) ↕3 !"⊑: 𝕨 contained list with mixed-type elements" % 'a'⌾(1‿'a'⊸⊑) 4‿5⥊↕9 !"⊑: Indexing out-of-bounds (index 1‿5 in array of shape 4‿5)" % 'a'⌾(1‿5⊸⊑) 4‿5⥊↕9 @@ -33,6 +30,8 @@ a←10‿10‿10⥊↕1000 ⋄ ! a ≡ a⌾((↕≢a)⊸⊑) a # ⊏ n←500 ⋄ a←↕n ⋄ i←(-n)+↕2×n ⋄ r←⌽(2×n)⥊a ⋄ ! (⌽a) ≡ r⌾(i⊸⊏) a +!"⊏: 𝕩 cannot be a unit" % 0‿0⌾(0‿0⊸⊏) <0 +!"⊏: 𝕩 cannot be a unit" % %USE evar ⋄ (↕0) {⊢⌾(𝕨⊸⊏)𝕩}_evar <0 !"𝔽⌾(a⊸⊏)𝕩: Indexing out-of-bounds (¯11∊a, ⟨10⟩≡≢𝕩)" % %USE evar ⋄ 5‿¯11 {0‿1⌾(𝕨⊸⊏)𝕩}_evar 10⥊1‿0‿1 !"𝔽⌾(a⊸⊏)𝕩: Indexing out-of-bounds (10∊a, ⟨10⟩≡≢𝕩)" % %USE evar ⋄ 9‿10 {0‿1⌾(𝕨⊸⊏)𝕩}_evar 10⥊1‿0‿1 !"𝔽⌾(a⊸⊏)𝕩: Indexing out-of-bounds (10∊a, ⟨10⟩≡≢𝕩)" % %USE evar ⋄ "ab" {𝕨⌾(9‿10⊸⊏)𝕩}_evar 10⥊"foo" @@ -43,7 +42,10 @@ 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 !"𝔽⌾(a⊸⊏): Incompatible result elements" % 3‿4⌾(1‿1⊸⊏) ↕10 !"𝔽⌾(a⊸⊏): Incompatible result elements" % 3‿4⌾(1‿¯9⊸⊏) ↕10 !"𝔽⌾(a⊸⊏): Incompatible result elements" % %USE evar ⋄ 3‿4 {𝕨⌾(1‿¯9⊸⊏) 𝕩}_evar ↕10 @@ -52,10 +54,16 @@ n←500 ⋄ a←↕n ⋄ i←(-n)+↕2×n ⋄ r←⌽(2×n)⥊a ⋄ ! (⌽a) ≡ !"𝔽⌾(a⊸⊏): Incompatible result elements" % 3‿4‿5⌾(1‿1‿2⊸⊏) <¨↕10 !"𝔽⌾(a⊸⊏): Incompatible result elements" % 3‿4‿5⌾(1‿1‿2⊸⊏) a←<¨↕10 ⋄ •internal.Keep 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 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 # ⥊ |