From f0c1962596f096ee50c4b25712cc01c0dada6627 Mon Sep 17 00:00:00 2001 From: dzaima Date: Tue, 19 Dec 2023 17:41:17 +0200 Subject: [PATCH] =?UTF-8?q?more=20typed=20=E2=8C=BE(list=E2=8A=B8=E2=8A=8F?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/select.c | 194 +++++++++++++++++++----------------------- src/builtins/sfns.c | 4 +- src/builtins/slash.c | 24 +++--- src/utils/mut.c | 51 +++++++---- src/utils/mut.h | 1 + test/cases/perf.bqn | 4 +- test/cases/under.bqn | 12 ++- test/run.bqn | 2 +- 8 files changed, 150 insertions(+), 142 deletions(-) diff --git a/src/builtins/select.c b/src/builtins/select.c index c7b2b62b..e552f655 100644 --- a/src/builtins/select.c +++ b/src/builtins/select.c @@ -369,7 +369,8 @@ B select_c2(B t, B w, B x) { -B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xia) { // rep⌾(w⊏⥊) x +extern 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 #if CHECK_VALID TALLOC(bool, set, xia); bool sparse = wia < xia/64; @@ -380,126 +381,103 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xia) { // rep⌾(w⊏⥊ } #define EQ(F) if (set[cw] && (F)) thrF("𝔽⌾(a⊸%c): Incompatible result elements", chr); set[cw] = true; #define FREE_CHECK TFREE(set) - SLOWIF(xia>100 && wia100 && wiare?xe:re; - bool reuse = reusable(x); - if (me==el_i32) { - I32Arr* xn = reuse? toI32Arr(REUSE(x)) : (I32Arr*)cpyI32Arr(x); - i32* xp = i32arrv_ptr(xn); - rep = toI32Any(rep); i32* rp = i32any_ptr(rep); - for (usz i = 0; i < wia; i++) { - i64 cw = wp[i]; if (RARE(cw<0)) cw+= (i64)xia; // we're free to assume w is valid - i32 cr = rp[i]; - EQ(cr != xp[cw]); - xp[cw] = cr; - } - decG(w); decG(rep); FREE_CHECK; return taga(xn); - } else if (me==el_i8) { - I8Arr* xn = reuse? toI8Arr(REUSE(x)) : (I8Arr*)cpyI8Arr(x); - i8* xp = i8arrv_ptr(xn); - rep = toI8Any(rep); i8* rp = i8any_ptr(rep); - for (usz i = 0; i < wia; i++) { - i64 cw = wp[i]; if (RARE(cw<0)) cw+= (i64)xia; - i8 cr = rp[i]; - EQ(cr != xp[cw]); - xp[cw] = cr; - } - decG(w); decG(rep); FREE_CHECK; return taga(xn); - } else if (me==el_i16) { - I16Arr* xn = reuse? toI16Arr(REUSE(x)) : (I16Arr*)cpyI16Arr(x); - i16* xp = i16arrv_ptr(xn); - rep = toI16Any(rep); i16* rp = i16any_ptr(rep); - for (usz i = 0; i < wia; i++) { - i64 cw = wp[i]; if (RARE(cw<0)) cw+= (i64)xia; - i16 cr = rp[i]; - EQ(cr != xp[cw]); - xp[cw] = cr; - } - decG(w); decG(rep); FREE_CHECK; return taga(xn); - } else if (me==el_bit) { - BitArr* xn = reuse? toBitArr(REUSE(x)) : (BitArr*)cpyBitArr(x); - u64* xp = bitarrv_ptr(xn); - rep = taga(toBitArr(rep)); u64* rp = bitarr_ptr(rep); - for (usz i = 0; i < wia; i++) { - i64 cw = wp[i]; if (RARE(cw<0)) cw+= (i64)xia; - bool cr = bitp_get(rp, i); - EQ(cr != bitp_get(xp,cw)); - bitp_set(xp,cw,cr); - } - decG(w); decG(rep); FREE_CHECK; return taga(xn); - } else if (me==el_f64) { - F64Arr* xn = reuse? toF64Arr(REUSE(x)) : (F64Arr*)cpyF64Arr(x); - f64* xp = f64arrv_ptr(xn); - rep = toF64Any(rep); f64* rp = f64any_ptr(rep); - for (usz i = 0; i < wia; i++) { - i64 cw = wp[i]; if (RARE(cw<0)) cw+= (i64)xia; - f64 cr = rp[i]; - EQ(cr != xp[cw]); - xp[cw] = cr; - } - decG(w); decG(rep); FREE_CHECK; return taga(xn); - } else UD; - } - if (reusable(x) && xe==re) { - if (TY(x)==t_harr) { - B* xp = harr_ptr(REUSE(x)); - SGet(rep) - for (usz i = 0; i < wia; i++) { - i64 cw = wp[i]; if (RARE(cw<0)) cw+= (i64)xia; - B cr = Get(rep, i); - EQ(!equal(cr,xp[cw])); - dec(xp[cw]); - xp[cw] = cr; - } - decG(w); decG(rep); FREE_CHECK; - return x; - } - } - MAKE_MUT_INIT(r, xia, el_or(xe, re)); - MUTG_INIT(r); - mut_copyG(r, 0, x, 0, xia); + u8 re = el_or(xe, TI(rep,elType)); + Arr* ra; + // w = taga(cpyF64Arr(w)); we = el_f64; // test the float path + if (we==el_f64) { + f64* wp = f64any_ptr(w); + SPARSE_INIT((i64)wp[i]) + + MAKE_MUT(r, xia); + mut_init_copy(r, x, re); NOGC_E; - SGet(rep) + MUTG_INIT(r); SGet(rep) for (usz i = 0; i < wia; i++) { - i64 cw = wp[i]; if (RARE(cw<0)) cw+= (i64)xia; - B cr = Get(rep, i); - EQ(!equal(mut_getU(r, cw), cr)); + READ_W(cw, i); + B cn = Get(rep, i); + EQ(!equal(mut_getU(r, cw), cn)); mut_rm(r, cw); - mut_setG(r, cw, cr); + mut_setG(r, cw, cn); } - decG(w); decG(rep); FREE_CHECK; - return mut_fcd(r, x); + ra = mut_fp(r); + goto dec_ret_ra; } - MAKE_MUT_INIT(r, xia, el_or(xe, re)); - MUTG_INIT(r); - mut_copyG(r, 0, x, 0, xia); - NOGC_E; - SGet(rep) SGetU(w) - SPARSE_INIT(o2i64G(GetU(w, i))) - for (usz i = 0; i < wia; i++) { - i64 cw = o2i64G(GetU(w, i)); if (RARE(cw<0)) cw+= (i64)xia; - B cr = Get(rep, i); - EQ(!equal(mut_getU(r, cw), cr)); - mut_rm(r, cw); - mut_setG(r, cw, cr); + assert(elInt(we)); + + w = toI32Any(w); + i32* wp = i32any_ptr(w); + SPARSE_INIT(wp[i]) + bool reuse = reusable(x) && re==reuseElType[TY(x)]; + SLOWIF(!reuse && xia>100 && wiaa; + 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); + } + goto dec_ret_ra; + } + case el_B: { + 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; + } + goto dec_ret_ra; + } } - decG(w); decG(rep); FREE_CHECK; - return mut_fcd(r, x); + + #define IMPL(T) do { \ + 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]); \ + rp[cw] = cn; \ + } \ + goto dec_ret_ra; \ + } while(0) + + do_u8: IMPL(u8); + do_u16: IMPL(u16); + do_u32: IMPL(u32); + do_u64: IMPL(u64); + #undef IMPL + + + + dec_ret_ra:; + decG(w); decG(rep); + FREE_CHECK; + return taga(ra); + #undef SPARSE_INIT #undef EQ #undef FREE_CHECK diff --git a/src/builtins/sfns.c b/src/builtins/sfns.c index e13a5d06..395ba325 100644 --- a/src/builtins/sfns.c +++ b/src/builtins/sfns.c @@ -382,7 +382,7 @@ static B recPick(B w, B x) { // doesn't consume if (isAtm(c)) thrM("⊑: 𝕨 contained list with mixed-type elements"); HARR_ADD(r, i, recPick(c, x)); } - return HARR_FC(r, w); + return any_squeeze(HARR_FC(r, w)); } } } @@ -1322,7 +1322,7 @@ B pick_ucw(B t, B o, B w, B x) { if (RARE(c==USZ_MAX)) { mut_pfree(r, i); goto def; } mut_setG(r, i, m_usz(c)); } - w = mut_fcd(r, w); + 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); diff --git a/src/builtins/slash.c b/src/builtins/slash.c index 49f2f8c9..d1dcc5d0 100644 --- a/src/builtins/slash.c +++ b/src/builtins/slash.c @@ -1010,6 +1010,16 @@ B slash_ucw(B t, B o, B w, B x) { if (wb && re!=el_B) { u64* d = bitarr_ptr(w); void* rp = r->a; + switch (re) { default: UD; + case el_bit: + case el_i8: x = toI8Any(x); rep = toI8Any(rep); goto bit_u8; + case el_c8: x = toC8Any(x); rep = toC8Any(rep); goto bit_u8; + case el_i16: x = toI16Any(x); rep = toI16Any(rep); goto bit_u16; + case el_c16: x = toC16Any(x); rep = toC16Any(rep); goto bit_u16; + case el_i32: x = toI32Any(x); rep = toI32Any(rep); goto bit_u32; + case el_c32: x = toC32Any(x); rep = toC32Any(rep); goto bit_u32; + case el_f64: x = toF64Any(x); rep = toF64Any(rep); goto bit_u64; + } #define IMPL(T) do { \ T* xp = tyany_ptr(x); \ @@ -1022,24 +1032,12 @@ B slash_ucw(B t, B o, B w, B x) { goto dec_ret; \ } while(0) - #define WIDEN_GO(UT, T, B) x = to##UT##Any(x); rep = to##UT##Any(rep); goto bit_##B - - switch (re) { - case el_bit: - case el_i8: x = toI8Any(x); rep = toI8Any(rep); goto bit_u8; - case el_c8: x = toC8Any(x); rep = toC8Any(rep); goto bit_u8; - case el_i16: x = toI16Any(x); rep = toI16Any(rep); goto bit_u16; - case el_c16: x = toC16Any(x); rep = toC16Any(rep); goto bit_u16; - case el_i32: x = toI32Any(x); rep = toI32Any(rep); goto bit_u32; - case el_c32: x = toC32Any(x); rep = toC32Any(rep); goto bit_u32; - case el_f64: x = toF64Any(x); rep = toF64Any(rep); goto bit_u64; - } bit_u8: IMPL(u8); bit_u16: IMPL(u16); bit_u32: IMPL(u32); bit_u64: IMPL(u64); #undef IMPL - #undef WIDEN_GO + } else { SGet(x) SGet(rep) MUTG_INIT(r); if (wb) { diff --git a/src/utils/mut.c b/src/utils/mut.c index 60682a68..95255c82 100644 --- a/src/utils/mut.c +++ b/src/utils/mut.c @@ -2,9 +2,9 @@ #include "mut.h" typedef struct { Arr* arr; void* els; } MadeArr; -FORCE_INLINE MadeArr mut_make_arr(usz ia, u8 type, u8 n) { +FORCE_INLINE MadeArr mut_make_arr(usz ia, u8 type, u8 el) { u64 sz; - switch(n) { default: UD; + switch(el) { default: UD; case el_bit: sz = BITARR_SZ( ia); break; case el_i8: case el_c8: sz = TYARR_SZ(I8, ia); break; case el_i16: case el_c16: sz = TYARR_SZ(I16,ia); break; @@ -18,9 +18,9 @@ FORCE_INLINE MadeArr mut_make_arr(usz ia, u8 type, u8 n) { return (MadeArr){a, ((TyArr*)a)->a}; } -FORCE_INLINE void mut_init(Mut* m, u8 n) { - m->fns = &mutFns[n]; - MadeArr a = mut_make_arr(m->ia, m->fns->valType, n); +FORCE_INLINE void mut_init(Mut* m, u8 el) { + m->fns = &mutFns[el]; + MadeArr a = mut_make_arr(m->ia, m->fns->valType, el); m->val = a.arr; m->a = a.els; } @@ -39,6 +39,25 @@ NOINLINE Mut make_mut_init(ux ia, u8 el) { } #endif +static void* arr_ptr(Arr* t, u8 el) { + return el==el_B? (void*)((HArr*)t)->a : (void*)((TyArr*)t)->a; +} + +u8 reuseElType[t_COUNT]; +void mut_init_copy(Mut* m, B x, u8 el) { + assert(m->fns == &mutFns[el_MAX]); + if (reusable(x) && reuseElType[TY(x)]==el) { + m->fns = &mutFns[el]; + Arr* a = m->val = a(REUSE(x)); + m->a = arr_ptr(a, el); + } else { + mut_to(m, el); + mut_copy(m, 0, x, 0, IA(x)); + arr_shCopy(m->val, x); + decG(x); + } +} + static Arr* (*cpyFns[])(B) = { [el_bit] = cpyBitArr, [el_i8] = cpyI8Arr, [el_c8] = cpyC8Arr, @@ -67,7 +86,7 @@ NOINLINE void mut_to(Mut* m, u8 n) { #endif Arr* t = cpyFns[n](taga(m->val)); m->val = t; - m->a = n==el_B? (void*)((HArr*)t)->a : (void*)((TyArr*)t)->a; + m->a = arr_ptr(t, n); } } @@ -703,15 +722,17 @@ void mutF_init(void) { FOR_TY(G) #undef G #undef F - mutFns[el_bit].elType = el_bit; mutFns[el_bit].valType = t_bitarr; - mutFns[el_i8 ].elType = el_i8 ; mutFns[el_i8 ].valType = t_i8arr; - mutFns[el_i16].elType = el_i16; mutFns[el_i16].valType = t_i16arr; - mutFns[el_i32].elType = el_i32; mutFns[el_i32].valType = t_i32arr; - mutFns[el_c8 ].elType = el_c8 ; mutFns[el_c8 ].valType = t_c8arr; - mutFns[el_c16].elType = el_c16; mutFns[el_c16].valType = t_c16arr; - mutFns[el_c32].elType = el_c32; mutFns[el_c32].valType = t_c32arr; - mutFns[el_f64].elType = el_f64; mutFns[el_f64].valType = t_f64arr; - mutFns[el_B ].elType = el_B ; mutFns[el_B ].valType = t_harr; + 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_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_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_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 4db3d3b5..af170e2c 100644 --- a/src/utils/mut.h +++ b/src/utils/mut.h @@ -43,6 +43,7 @@ void mut_to(Mut* m, u8 n); #define MAKE_MUT_INIT(N, IA, EL) Mut N##_val = make_mut_init(IA, EL); Mut* N = &N##_val; #endif #define MAKE_MUT(N, IA) Mut N##_val; N##_val.fns = &mutFns[el_MAX]; N##_val.ia = (IA); Mut* N = &N##_val; +void mut_init_copy(Mut* m, B x, u8 el); // consumes x; initialize m to to a type-el array, copying in all elements of x; assumes el fits x; expects no further changes to type & to be completed with mut_fp, at which point it returns an array of the same shape as x static B mut_fv(Mut* m) { assert(m->fns->elType!=el_MAX); NOGC_E; assert(m->ia == m->val->ia); diff --git a/test/cases/perf.bqn b/test/cases/perf.bqn index 26c0a425..fec72971 100644 --- a/test/cases/perf.bqn +++ b/test/cases/perf.bqn @@ -30,7 +30,9 @@ %USE fastone ⋄ a←5+↕1e6 ⋄ n←{𝕊: a 1⊸+⌾⊑↩}_fastone 4 ⋄ ! (10↑a) ≡ (5+n)∾6+↕9 # in-place ⌾(l⊸⊏) -%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 ⋄ 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 ∾⟜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'⟩ diff --git a/test/cases/under.bqn b/test/cases/under.bqn index b171bc1f..e3b8fff1 100644 --- a/test/cases/under.bqn +++ b/test/cases/under.bqn @@ -1,3 +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 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 @@ -30,16 +33,21 @@ 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 -!"𝔽⌾(a⊸⊏)𝕩: Indexing out-of-bounds (¯11∊a, ⟨10⟩≡≢𝕩)" % 1‿2⌾(5‿¯11⊸⊏) ↕10 -!"𝔽⌾(a⊸⊏)𝕩: Indexing out-of-bounds (10∊a, ⟨10⟩≡≢𝕩)" % 1‿2⌾(9‿10⊸⊏) ↕10 +!"𝔽⌾(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" 100⊸+⌾(⟨1‿2‿4⟩⊸⊏) <¨↕10 %% <¨ 0‿101‿102‿3‿104‿5‿6‿7‿8‿9 100⊸+⌾(1‿2‿4⊸⊏) <¨↕10 %% <¨ 0‿101‿102‿3‿104‿5‿6‿7‿8‿9 100⊸+⌾(1‿2‿4⊸⊏) ↕10 %% 0‿101‿102‿3‿104‿5‿6‿7‿8‿9 100⊸+¨⌾(1‿2‿4⊸⊏) ↕10 %% 0‿101‿102‿3‿104‿5‿6‿7‿8‿9 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 !"𝔽⌾(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 +!"𝔽⌾(a⊸⊏): Incompatible result elements" % %USE evar ⋄ "ab" {𝕨⌾(1‿¯9⊸⊏) 𝕩}_evar 'a'+↕10 !"𝔽⌾(a⊸⊏): Incompatible result elements" % 3‿4‿5⌾(1‿1‿2⊸⊏) ↕10 !"𝔽⌾(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 diff --git a/test/run.bqn b/test/run.bqn index 7c863925..47771341 100644 --- a/test/run.bqn +++ b/test/run.bqn @@ -175,7 +175,7 @@ Run ← { 𝕊 testname: }∘{currLn↩(⊑𝕩).ln ⋄ 1↓𝕩}¨ toRun {𝕊: - res‿desc ← ({@≡𝕩? 0; ¬⊑(@+10)∊𝕩}¨ results)⊸/¨ results‿toRun + res‿desc ← ({@≡𝕩? 0; (¬⊑(@+10)∊𝕩) ∧ ¬∨´"TEST FAIL"⍷𝕩}¨ results)⊸/¨ results‿toRun 0≠≠res? •Out ∾⟨"Update ", •Repr≠res, " entr", (1<≠res)⊑"y"‿"ies", " in ", filename, "?"⟩ {