From ab15eaeeebad5a5936446ae4df0e71b288567271 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Sat, 22 Jun 2024 09:38:38 -0400 Subject: [PATCH 01/15] Length-1 reverse is a no-op --- src/builtins/sfns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/builtins/sfns.c b/src/builtins/sfns.c index 72e157db..5877da7a 100644 --- a/src/builtins/sfns.c +++ b/src/builtins/sfns.c @@ -1059,7 +1059,7 @@ static u64 bit_reverse(u64 x) { B reverse_c1(B t, B x) { if (isAtm(x) || RNK(x)==0) thrM("⌽: Argument cannot be a unit"); usz n = *SH(x); - if (n==0) return x; + if (n<=1) return x; u8 xl = cellWidthLog(x); u8 xt = arrNewType(TY(x)); if (xl<=6 && (xl>=3 || xl==0)) { From 8766810db81290ae07db1d612d113e2dcd198273 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Sat, 22 Jun 2024 09:39:02 -0400 Subject: [PATCH 02/15] Rank-agnostic select_cells --- src/builtins/cells.c | 66 ++++++++++++++++++++++++-------------------- src/core/arrFns.h | 14 ++++++---- 2 files changed, 45 insertions(+), 35 deletions(-) diff --git a/src/builtins/cells.c b/src/builtins/cells.c index 68d36f30..2884cae8 100644 --- a/src/builtins/cells.c +++ b/src/builtins/cells.c @@ -178,52 +178,58 @@ NOINLINE B leading_axis_arith(FC2 fc2, B w, B x, usz* wsh, usz* xsh, ur mr) { // // fast special-case implementations extern void (*const si_select_cells_bit_lt64)(uint64_t*,uint64_t*,uint32_t,uint32_t,uint32_t); // from fold.c (fold.singeli) -static NOINLINE B select_cells(usz n, B x, usz cam, usz k, bool leaf) { // n {leaf? <∘⊑; ⊏}⎉¯k x; TODO probably can share some parts with takedrop_highrank and/or call ⊏? +static NOINLINE B select_cells(usz ind, B x, usz cam, usz k, bool leaf) { // ind {leaf? <∘⊑; ⊏}⎉¯k x; TODO probably can share some parts with takedrop_highrank and/or call ⊏? ur xr = RNK(x); assert(xr>1 && k=7 || (xl<3 && xl>0)) { // generic case + MAKE_MUT_INIT(rm, ria, TI(x,elType)); MUTG_INIT(rm); + usz jump = l * csz; + usz xi = take*ind; + usz ri = 0; + for (usz i = 0; i < cam; i++) { + mut_copyG(rm, ri, x, xi, take); + xi+= jump; + ri+= take; + } + ra = mut_fp(rm); + } else if (xe==el_B) { + assert(take == 1); SGet(x) - HArr_p rp = m_harrUv(cam); - for (usz i = 0; i < cam; i++) rp.a[i] = Get(x, i*jump+n); + HArr_p rp = m_harrUv(ria); + for (usz i = 0; i < cam; i++) rp.a[i] = Get(x, i*l+ind); NOGC_E; ra = (Arr*)rp.c; } else { - void* rp = m_tyarrlbp(&ra, elwBitLog(xe), cam, el2t(xe)); + void* rp = m_tyarrlbp(&ra, ewl, ria, el2t(xe)); void* xp = tyany_ptr(x); - switch(xe) { - case el_bit: + switch(xl) { + case 0: #if SINGELI - if (jump < 64) si_select_cells_bit_lt64(xp, rp, cam, jump, n); + if (l < 64) si_select_cells_bit_lt64(xp, rp, cam, l, ind); else #endif - for (usz i=0; if; goto const_f; } usz *sh = SH(x); if (((rtid==n_fold && cr==1) || rtid==n_insert) && TI(x,elType)!=el_B - && isFun(fd->f) && 1==shProd(sh, k+1, xr) && sh[k] > 0) { + && isFun(fd->f) && sh[k] > 0) { usz m = sh[k]; u8 frtid = v(fd->f)->flags-1; if (m==1 || frtid==n_ltack) return select_cells(0 , x, cam, k, false); if ( frtid==n_rtack) return select_cells(m-1, x, cam, k, false); - if (isPervasiveDyExt(fd->f)) { + if (isPervasiveDyExt(fd->f) && 1==shProd(sh, k+1, xr)) { if (TI(x,elType)==el_bit) { incG(x); // keep shape alive B r = fold_rows_bit(fd, x, shProd(sh, 0, k), m); diff --git a/src/core/arrFns.h b/src/core/arrFns.h index 1257c9e0..b020be2c 100644 --- a/src/core/arrFns.h +++ b/src/core/arrFns.h @@ -73,11 +73,15 @@ SHOULD_INLINE void arr_check_size(u64 sz, u8 type, usz ia) { #endif } // Log of width in bits: max of 7, and also return 7 if not power of 2 -SHOULD_INLINE u8 cellWidthLog(B x) { +SHOULD_INLINE u8 multWidthLog(usz n, u8 lw) { // Of n elements, 1<>lw); // Max of 7; also handle n==0 +} +SHOULD_INLINE u8 kCellWidthLog(B x, ur k) { assert(isArr(x) && RNK(x)>=1); u8 lw = arrTypeBitsLog(TY(x)); - if (LIKELY(RNK(x)==1)) return lw; - usz csz = arr_csz(x); - if (csz & (csz-1)) return 7; // Not power of 2 - return lw + CTZ(csz | 128>>lw); // Max of 7; also handle csz==0 + ur xr = RNK(x); + if (LIKELY(xr <= k)) return lw; + return multWidthLog(shProd(SH(x), k, xr), lw); } +SHOULD_INLINE u8 cellWidthLog(B x) { return kCellWidthLog(x, 1); } From a19b5401f75e37fdd35e897b1c30631508204519 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Sat, 22 Jun 2024 14:55:07 -0400 Subject: [PATCH 03/15] =?UTF-8?q?Fast=20cases=20for=20monadic=20rank=20wit?= =?UTF-8?q?h=20cell=20length=20=E2=89=A41?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/cells.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/builtins/cells.c b/src/builtins/cells.c index 2884cae8..2780f379 100644 --- a/src/builtins/cells.c +++ b/src/builtins/cells.c @@ -459,6 +459,23 @@ B for_cells_c1(B f, u32 xr, u32 cr, u32 k, B x, u32 chr) { // F⎉cr x, with arr case n_transp: { return cr<=1? x : transp_cells(xr-1, k, x); } + // trivial cases for unhandled functions + case n_reverse: case n_and: case n_or: case n_find: + if (cr == 0) break; + if (xsh[k] <= 1) return x; + break; + case n_gradeUp: case n_gradeDown: case n_indexOf: case n_memberOf: case n_count: { + if (cr == 0) break; + usz l = xsh[k]; + if (l <= 1) { + usz ia = l*cam; + Arr* r = rtid==n_memberOf? allOnes(ia) : allZeroes(ia); + usz* rsh = arr_shAlloc(r, k+1); + shcpy(rsh, xsh, k+1); + decG(x); return taga(r); + } + break; + } } if (TY(f) == t_md1D) { From 5d4391a3fdead020a4c42a0fb8e35b268c8bfc0e Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Sun, 23 Jun 2024 10:10:00 -0400 Subject: [PATCH 04/15] =?UTF-8?q?Combine=20monadic=20=CB=98=20with=20outer?= =?UTF-8?q?=20=CB=98=20or=20=E2=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/cells.c | 69 +++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/src/builtins/cells.c b/src/builtins/cells.c index 2780f379..c484ddd0 100644 --- a/src/builtins/cells.c +++ b/src/builtins/cells.c @@ -481,42 +481,45 @@ B for_cells_c1(B f, u32 xr, u32 cr, u32 k, B x, u32 chr) { // F⎉cr x, with arr if (TY(f) == t_md1D) { Md1D* fd = c(Md1D,f); u8 rtid = fd->m1->flags-1; - if (rtid==n_const) { f=fd->f; goto const_f; } - usz *sh = SH(x); - if (((rtid==n_fold && cr==1) || rtid==n_insert) && TI(x,elType)!=el_B - && isFun(fd->f) && sh[k] > 0) { - usz m = sh[k]; - u8 frtid = v(fd->f)->flags-1; - if (m==1 || frtid==n_ltack) return select_cells(0 , x, cam, k, false); - if ( frtid==n_rtack) return select_cells(m-1, x, cam, k, false); - if (isPervasiveDyExt(fd->f) && 1==shProd(sh, k+1, xr)) { - if (TI(x,elType)==el_bit) { - incG(x); // keep shape alive - B r = fold_rows_bit(fd, x, shProd(sh, 0, k), m); - if (!q_N(r)) { - if (xr > 2) { - usz* rsh = arr_shAlloc(a(r), xr-1); - shcpy(rsh, sh, k); - shcpy(rsh+k, sh+k+1, xr-1-k); + switch(rtid) { + case n_const: f=fd->f; goto const_f; + case n_cell: cr-= cr>0; return for_cells_c1(fd->f, xr, cr, xr-cr, x, U'˘'); + case n_fold: if (cr != 1) break; // else fall through + case n_insert: if (TI(x,elType)!=el_B && isFun(fd->f) && xsh[k]>0) { + usz m = xsh[k]; + u8 frtid = v(fd->f)->flags-1; + if (m==1 || frtid==n_ltack) return select_cells(0 , x, cam, k, false); + if ( frtid==n_rtack) return select_cells(m-1, x, cam, k, false); + if (isPervasiveDyExt(fd->f) && 1==shProd(xsh, k+1, xr)) { + if (TI(x,elType)==el_bit) { + incG(x); // keep shape alive + B r = fold_rows_bit(fd, x, cam, m); + if (!q_N(r)) { + if (xr > 2) { + usz* rsh = arr_shAlloc(a(r), xr-1); + shcpy(rsh, xsh, k); + shcpy(rsh+k, xsh+k+1, xr-1-k); + } + decG(x); return r; } - decG(x); return r; + decG(x); } - decG(x); + // TODO extend to any rank + if (xr==2 && k==1 && m<=64 && mf)) goto base; - u8 frtid = v(fd->f)->flags-1; - if (frtid==n_rtack) return x; - if (TI(x,elType)==el_bit && (isPervasiveDyExt(fd->f)||frtid==n_ltack) - && 1==shProd(sh, k+1, xr)) { - B r = scan_rows_bit(frtid, x, m); if (!q_N(r)) return r; + } break; + case n_scan: { + if (cr==0) break; + usz m = xsh[k]; + if (m<=1 || IA(x)==0) return x; + if (!isFun(fd->f)) break; + u8 frtid = v(fd->f)->flags-1; + if (frtid==n_rtack) return x; + if (TI(x,elType)==el_bit && (isPervasiveDyExt(fd->f)||frtid==n_ltack) + && 1==shProd(xsh, k+1, xr)) { + B r = scan_rows_bit(frtid, x, m); if (!q_N(r)) return r; + } + break; } } } else if (TY(f) == t_md2D) { From 9d5caad9a9643f03f900ae33f1345e4ccdf21698 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Sun, 23 Jun 2024 10:51:01 -0400 Subject: [PATCH 05/15] Compute Insert identity natively --- src/builtins/fold.c | 27 ++++++++++++++++++++++----- src/load.c | 5 ++--- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/builtins/fold.c b/src/builtins/fold.c index ccf88581..1030c1cd 100644 --- a/src/builtins/fold.c +++ b/src/builtins/fold.c @@ -381,22 +381,39 @@ static B m1c1(B t, B f, B x) { // consumes x decG(fn); return r; } -extern GLOBAL B rt_insert; extern B insert_base(B f, B x, bool has_w, B w); // from cells.c B insert_c1(Md1D* d, B x) { B f = d->f; - if (isAtm(x) || RNK(x)==0) thrM("˝: 𝕩 must have rank at least 1"); + ur xr; + if (isAtm(x) || (xr=RNK(x))==0) thrM("˝: 𝕩 must have rank at least 1"); usz len = *SH(x); - if (len==0) { SLOW2("!𝕎˝𝕩", f, x); return m1c1(rt_insert, f, x); } + if (len==0) { + if (isFun(f)) { + B id = TI(f,identity)(f); + if (!q_N(id)) { + if (isArr(id)) { decG(x); return id; } // arithmetic with table + usz* xsh = SH(x); + Arr* r = reshape_one(shProd(xsh, 1, xr), id); + if (xr == 2) arr_shVec(r); else { + usz* rsh = arr_shAlloc(r, xr-1); + shcpy(rsh, xsh+1, xr-1); + } + decG(x); return taga(r); + } else if (v(f)->flags == n_join+1) { + if (xr <= 1) thrM("˝: Identity does not exist"); + goto join; + } + } + thrM("˝: Identity not found"); + } if (len==1) return C1(select, x); if (RARE(!isFun(f))) { decG(x); if (isMd(f)) thrM("Calling a modifier"); return inc(f); } - ur xr = RNK(x); if (xr==1 && isPervasiveDyExt(f)) return m_unit(fold_c1(d, x)); if (v(f)->flags) { u8 rtid = v(f)->flags-1; if (rtid==n_ltack) return C1(select, x); if (rtid==n_rtack) return C2(select, m_f64(-1), x); - if (rtid==n_join) { + if (rtid==n_join) { join:; if (xr==1) return x; ShArr* rsh; if (xr>2) { diff --git a/src/load.c b/src/load.c index 5df99209..2d8ace52 100644 --- a/src/load.c +++ b/src/load.c @@ -129,7 +129,7 @@ NOINLINE B load_fullpath(B path, B name) { GLOBAL HArr* comps_curr; -GLOBAL B rt_undo, rt_select, rt_slash, rt_insert, rt_depth, +GLOBAL B rt_undo, rt_select, rt_slash, rt_depth, rt_group, rt_under, rt_find; Block* load_buildBlock(B x, B src, B path, B name, Scope* sc, i32 nsResult) { // consumes x,src B fullpath = load_fullpath(path, name); @@ -500,7 +500,6 @@ void load_init() { // very last init function gc_add(rt_under = Get(rtObjRaw, n_under )); gc_add(rt_find = Get(rtObjRaw, n_find )); gc_add(rt_depth = Get(rtObjRaw, n_depth )); - gc_add(rt_insert = Get(rtObjRaw, n_insert)); for (usz i = 0; i < RT_LEN; i++) { #ifdef RT_WRAP @@ -542,7 +541,7 @@ void load_init() { // very last init function load_rt = frtObj; rt_select = rt_slash = rt_group = rt_find = bi_invalidFn; - rt_undo = rt_insert = bi_invalidMd1; + rt_undo = bi_invalidMd1; rt_under = rt_depth = bi_invalidMd2; rt_invFnRegFn = rt_invFnSwapFn = invalidFn_c1; From 6eca24ce0a263192793eebbe03ea8429a77c92bc Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Wed, 26 Jun 2024 08:40:49 -0400 Subject: [PATCH 06/15] =?UTF-8?q?Special=20code=20for=20=E2=88=BE=CB=9D?= =?UTF-8?q?=CB=98=20and=20fold-cells=20of=20empty?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/cells.c | 16 ++++++++++++---- src/builtins/fold.c | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/src/builtins/cells.c b/src/builtins/cells.c index c484ddd0..c6ddcca4 100644 --- a/src/builtins/cells.c +++ b/src/builtins/cells.c @@ -7,8 +7,13 @@ B fne_c1(B, B); B shape_c2(B, B, B); B transp_c2(B, B, B); -B fold_rows(Md1D* d, B x); // from fold.c -B fold_rows_bit(Md1D* d, B x, usz n, usz m); // from fold.c + +// from fold.c: +B fold_rows(Md1D* d, B x); +B fold_rows_bit(Md1D* d, B x, usz n, usz m); +B insert_cells_join(B x, usz* xsh, ur cr, ur k); +B insert_cells_identity(B x, B f, usz* xsh, ur xr, ur k, u8 rtid); + B scan_rows_bit(u8, B x, usz m); // from scan.c B takedrop_highrank(bool take, B w, B x); // from sfns.c B try_interleave_cells(B w, B x, ur xr, ur xk, usz* xsh); // from transpose.c @@ -485,9 +490,12 @@ B for_cells_c1(B f, u32 xr, u32 cr, u32 k, B x, u32 chr) { // F⎉cr x, with arr case n_const: f=fd->f; goto const_f; case n_cell: cr-= cr>0; return for_cells_c1(fd->f, xr, cr, xr-cr, x, U'˘'); case n_fold: if (cr != 1) break; // else fall through - case n_insert: if (TI(x,elType)!=el_B && isFun(fd->f) && xsh[k]>0) { - usz m = xsh[k]; + case n_insert: if (cr>0 && isFun(fd->f)) { u8 frtid = v(fd->f)->flags-1; + if (frtid==n_join && rtid==n_insert) return insert_cells_join(x, xsh, cr, k); + usz m = xsh[k]; + if (m==0) return insert_cells_identity(x, fd->f, xsh, xr, k, rtid); + if (TI(x,elType)==el_B) break; if (m==1 || frtid==n_ltack) return select_cells(0 , x, cam, k, false); if ( frtid==n_rtack) return select_cells(m-1, x, cam, k, false); if (isPervasiveDyExt(fd->f) && 1==shProd(xsh, k+1, xr)) { diff --git a/src/builtins/fold.c b/src/builtins/fold.c index 1030c1cd..251b0683 100644 --- a/src/builtins/fold.c +++ b/src/builtins/fold.c @@ -14,7 +14,8 @@ // Insert with rank (˝˘ or ˝⎉k), or fold on flat array // SHOULD optimize dyadic insert with rank // Length 1, ⊣⊢: implemented as ⊏˘ -// SHOULD reshape identity for fast ˝˘ on empty rows +// ∾˝ with rank: reshape argument +// Arithmetic on empty: reshape identity // Boolean operand, cell size 1: // +: popcount // Rows length ≤64: extract rows, popcount each @@ -451,6 +452,38 @@ B insert_c2(Md1D* d, B w, B x) { B f = d->f; return insert_base(f, x, 1, w); } +B insert_cells_join(B x, usz* xsh, ur cr, ur k) { + assert(k > 0); + if (cr <= 1) { + if (xsh[k]==0) thrM("˝: Identity does not exist"); + return x; + } + ur rr = k+cr-1; // result rank (>1) + ShArr* rsh; + rsh = m_shArr(rr); + shcpy(rsh->a, xsh, k); + rsh->a[k] = xsh[k] * xsh[k+1]; + shcpy(rsh->a+k+1, xsh+k+2, cr-2); + Arr* r = TI(x,slice)(x, 0, IA(x)); + arr_shSetUG(r, rr, rsh); + decG(x); return taga(r); +} +B insert_cells_identity(B x, B f, usz* xsh, ur xr, ur k, u8 rtid) { + B id; + if (!isFun(f) || q_N(id = TI(f,identity)(f))) thrF("%c: Identity not found", rtid==n_fold? U'´' : U'˝'); + bool cs = !isArr(id); // if x cell shape is used (not table) + usz ria = shProd(xsh, 0, k); + if (cs) ria*= shProd(xsh, k+1, xr); + Arr* r = reshape_one(ria, id); + ur rr = cs? xr-1 : k; + if (rr == 1) arr_shVec(r); else { + usz* rsh = arr_shAlloc(r, rr); + shcpy(rsh, xsh, k); + if (cs) shcpy(rsh+k, xsh+k+1, rr-k); + } + decG(x); return taga(r); +} + // Arithmetic fold/insert on rows of flat rank-2 array x B transp_c1(B, B); B join_c2(B, B, B); From d89a6da2da854200802b02e899e6692ac134d21b Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Wed, 26 Jun 2024 14:42:57 -0400 Subject: [PATCH 07/15] =?UTF-8?q?Evaluate=20monadic=20=C2=AB=C2=BB=20on=20?= =?UTF-8?q?a=20length-1=20argument=20by=20reshaping=20the=20fill?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/sfns.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/builtins/sfns.c b/src/builtins/sfns.c index 5877da7a..47e82232 100644 --- a/src/builtins/sfns.c +++ b/src/builtins/sfns.c @@ -998,7 +998,10 @@ B shiftb_c1(B t, B x) { if (ia==0) return x; B xf = getFillE(x); usz csz = arr_csz(x); - + if (ia==csz) { // length 1 + Arr* r = arr_shCopy(reshape_one(ia, xf), x); + decG(x); return taga(r); + } MAKE_MUT_INIT(r, ia, el_or(TI(x,elType), selfElType(xf))); MUTG_INIT(r); mut_copyG(r, csz, x, 0, ia-csz); mut_fillG(r, 0, xf, csz); @@ -1025,6 +1028,10 @@ B shifta_c1(B t, B x) { if (ia==0) return x; B xf = getFillE(x); usz csz = arr_csz(x); + if (ia==csz) { // length 1 + Arr* r = arr_shCopy(reshape_one(ia, xf), x); + decG(x); return taga(r); + } MAKE_MUT_INIT(r, ia, el_or(TI(x,elType), selfElType(xf))); MUTG_INIT(r); mut_copyG(r, 0, x, csz, ia-csz); mut_fillG(r, ia-csz, xf, csz); From 4450d3618790d01680655020fe67aee6de3f62d7 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Wed, 26 Jun 2024 14:59:45 -0400 Subject: [PATCH 08/15] =?UTF-8?q?Better=20handling=20for=20=C2=AB=CB=98=20?= =?UTF-8?q?and=20=C2=BB=CB=98=20trivial=20cases?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/cells.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/builtins/cells.c b/src/builtins/cells.c index c6ddcca4..13a47fb6 100644 --- a/src/builtins/cells.c +++ b/src/builtins/cells.c @@ -455,8 +455,12 @@ B for_cells_c1(B f, u32 xr, u32 cr, u32 k, B x, u32 chr) { // F⎉cr x, with arr return taga(arr_shReplace(r, k+1, rsh)); } case n_shifta: case n_shiftb: { - if (IA(x)==0) goto noSpecial; - if (cr!=1) goto base; + if (IA(x)==0) return x; + if (cr!=1) { + if (cr==0) goto base; + if (!(xsh[k]==1 // handled by fill case + || shProd(xsh, k+1, xr)==1)) goto base; + } B xf = getFillR(x); if (noFill(xf)) goto base; return shift_cells(xf, x, cam, xsh[k], TI(x,elType), rtid); From 76a40491e9be725cd7d8bda86411ccbf5e9b0424 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Wed, 26 Jun 2024 19:50:56 -0400 Subject: [PATCH 09/15] Remove some rank restrictions from for_cells_SA --- src/builtins/cells.c | 66 +++++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/src/builtins/cells.c b/src/builtins/cells.c index 13a47fb6..4b2ee713 100644 --- a/src/builtins/cells.c +++ b/src/builtins/cells.c @@ -656,38 +656,52 @@ NOINLINE B for_cells_SA(B f, B w, B x, ur xcr, ur xr, u32 chr) { usz* xsh=SH(x); usz cam=shProd(xsh,0,xk); if (cam==0) return rank2_empty(f, w, 0, x, xk, chr); if (isFun(f)) { - if (IA(x)==0) goto generic; u8 rtid = v(f)->flags-1; - if (rtid==n_rtack) { dec(w); return x; } - if (rtid==n_ltack) return const_cells(x, xk, xsh, w, chr); - if (rtid==n_select && xk==1 && isF64(w) && xr==2) return select_cells(WRAP(o2i64(w), SH(x)[1], thrF("⊏: Indexing out-of-bounds (𝕨≡%R, %s≡≠𝕩)", w, cam)), x, cam, 1, false); - if (rtid==n_pick && xk==1 && TI(x,arrD1) && xr==2 && isF64(w)) return select_cells(WRAP(o2i64(w), SH(x)[1], thrF("⊑: Indexing out-of-bounds (𝕨≡%R, %s≡≠𝕩)", w, cam)), x, cam, 1, true); - if ((rtid==n_shifta || rtid==n_shiftb) && xk==1 && xr==2 && isAtm(w)) { - if (isArr(w)) { B w0=w; w = IGet(w,0); decG(w0); } - return shift_cells(w, x, SH(x)[0], SH(x)[1], el_or(TI(x,elType), selfElType(w)), rtid); - } - if (rtid==n_take || rtid==n_drop) { - if (xcr==0 || !isF64(w)) goto generic; - bool take = rtid==n_take; - f64* ap; - B a = m_f64arrv(&ap, xk+1); - if (!take) { FILL_TO(ap, el_f64, 0, m_f64(0), xk); } - else { usz* xsh=SH(x); PLAINLOOP for (usz i=0; i(2048*8)>>arrTypeBitsLog(TY(w)) && IA(w)!=IA(x))) goto generic; - return c2(f, C2(shape, C1(fne, incG(x)), w), x); + switch(rtid) { + case n_rtack: dec(w); return x; + case n_ltack: return const_cells(x, xk, xsh, w, chr); + case n_select: if (isF64(w) && xcr>=1) { + usz l = xsh[xk]; + return select_cells(WRAP(o2i64(w), l, thrF("⊏: Indexing out-of-bounds (𝕨≡%R, %s≡≠𝕩)", w, l)), x, cam, xk, false); + } break; + case n_pick: if (isF64(w) && xcr==1 && TI(x,arrD1)) { + usz l = xsh[xk]; + return select_cells(WRAP(o2i64(w), l, thrF("⊑: Indexing out-of-bounds (𝕨≡%R, %s≡≠𝕩)", w, l)), x, cam, xk, true); + } break; + case n_shifta: case n_shiftb: if (isAtm(w)) { + if (IA(x)==0) return x; + if (xcr!=1) { + if (xcr==0) break; + if (!(xsh[xk]==1 || shProd(xsh, xk+1, xr)==1)) break; + } + if (isArr(w)) { B w0=w; w = IGet(w,0); decG(w0); } + return shift_cells(w, x, cam, xsh[xk], el_or(TI(x,elType), selfElType(w)), rtid); + } break; + case n_take: case n_drop: { + if (xcr==0 || !isF64(w)) break; + bool take = rtid==n_take; + f64* ap; + B a = m_f64arrv(&ap, xk+1); + if (!take) { FILL_TO(ap, el_f64, 0, m_f64(0), xk); } + else { PLAINLOOP for (usz i=0; i(2048*8)>>arrTypeBitsLog(TY(w)) && IA(w)!=IA(x))) break; + return c2(f, C2(shape, C1(fne, incG(x)), w), x); + } } } else if (!isMd(f)) { dec(w); return const_cells(x, xk, xsh, inc(f), chr); } - generic:; S_KSLICES(x, xsh, xk, cam, 1) incBy(w, cam-1); M_APD_SH(r, xk, xsh); FC2 fc2 = c2fn(f); for (usz i=0,xp=0; i Date: Wed, 3 Jul 2024 22:17:06 -0400 Subject: [PATCH 10/15] Specialize ApdMut to reshape if there's only one append --- src/builtins/cells.c | 10 +++++----- src/core/stuff.c | 2 +- src/utils/mut.c | 31 +++++++++++++++++++++++++++++++ src/utils/mut.h | 3 ++- 4 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/builtins/cells.c b/src/builtins/cells.c index 4b2ee713..304d819e 100644 --- a/src/builtins/cells.c +++ b/src/builtins/cells.c @@ -170,7 +170,7 @@ NOINLINE B leading_axis_arith(FC2 fc2, B w, B x, usz* wsh, usz* xsh, ur mr) { // if (mr==wr) w=s; else x=s; return fc2(m_f64(0), w, x); } else { - M_APD_SH(r, mr, bsh); + M_APD_SH_N(r, mr, bsh, cam); S_KSLICES(b, bsh, mr, cam, 1) usz bp=0; if (mr==wr) { SGetU(w); for (usz i=0; iapd(m, x); if (xe==el_B) NOGC_E; } +// used if this is the only append: only need to add leading 1s to shape +NOINLINE void apd_reshape(ApdMut* m, B x) { + ur rr0 = m->rr0; // need to be read before union fields are written + for (ur i=0; irsh0[i] == 1); + + inc(x); + if (isAtm(x)) x = m_unit(x); + + if (rr0 > 0) { + ur xr = RNK(x); + if (rr0 + xr > UR_MAX) { + m->failEl = x; + m->end = apd_rnk_err; + return; + } + ur rr = rr0 + xr; + Arr* r = cpyWithShape(x); + if (rr <= 1) { + arr_shErase(r, rr); + } else { + usz* xsh = PSH(r); + ShArr* rsh = m_shArr(rr); + PLAINLOOP for (ur i=0; ia[i] = 1; + shcpy(rsh->a + rr0, xsh, xr); + arr_shReplace(r, rr, rsh); + } + x = taga(r); + } + m->obj = a(x); + m->end = apd_ret_end; +} NOINLINE void apd_widen(ApdMut* m, B x, ApdFn* const* fns) { u8 xe = isArr(x)? TI(x,elType) : selfElType(x); diff --git a/src/utils/mut.h b/src/utils/mut.h index ebeef513..701f6dd1 100644 --- a/src/utils/mut.h +++ b/src/utils/mut.h @@ -265,7 +265,7 @@ struct ApdMut { }; }; -ApdFn apd_tot_init, apd_sh_init; +ApdFn apd_tot_init, apd_sh_init, apd_reshape; #if DEBUG ApdFn apd_dbg_apd; ApdEnd apd_dbg_end; @@ -275,6 +275,7 @@ ApdFn apd_tot_init, apd_sh_init; #endif #define M_APD_TOT(M, IA) M_APD_BASE(M) M.apd = apd_tot_init; M.ia0 = (IA); // end gives uninitialized shape #define M_APD_SH(M, RR, RSH) M_APD_BASE(M) M.apd = apd_sh_init; M.rsh0 = (RSH); M.rr0 = (RR); // end gives full shape; will error on invalid at the end; rsh must be alive until at least the first APD call +#define M_APD_SH_N(M, RR, RSH, N) M_APD_BASE(M) M.apd = N==1? apd_reshape : apd_sh_init; M.rsh0 = (RSH); M.rr0 = (RR); // same, with known number of appends #define M_APD_SH1(M, RIA) usz M##_sh0 = (RIA); M_APD_SH(M, 1, &M##_sh0); #define APD(M, A) M.apd(&M, A) // doesn't consume A #define APDD(M, A) ({ B av_ = (A); M.apd(&M, av_); dec(av_); }) // consumes A From ce98efc525ca46a9030336d3bcd161ac90baa657 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Thu, 4 Jul 2024 09:58:14 -0400 Subject: [PATCH 11/15] =?UTF-8?q?Transform=20atom=E2=8A=B8=E2=8C=BD?= =?UTF-8?q?=E2=8E=89k=20into=20a=20single=20high-rank=20=E2=8C=BD=20call?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/cells.c | 9 +++++++++ src/builtins/sfns.c | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/builtins/cells.c b/src/builtins/cells.c index 304d819e..963e2663 100644 --- a/src/builtins/cells.c +++ b/src/builtins/cells.c @@ -16,6 +16,7 @@ B insert_cells_identity(B x, B f, usz* xsh, ur xr, ur k, u8 rtid); B scan_rows_bit(u8, B x, usz m); // from scan.c B takedrop_highrank(bool take, B w, B x); // from sfns.c +B rotate_highrank(bool inv, B w, B x); // from sfns.c B try_interleave_cells(B w, B x, ur xr, ur xk, usz* xsh); // from transpose.c // X - variable name; XSH - its shape; K - number of leading axes that get iterated over; SLN - number of slices that will be made; DX - additional refcount count to add to x @@ -687,6 +688,14 @@ NOINLINE B for_cells_SA(B f, B w, B x, ur xcr, ur xr, u32 chr) { ap[xk] = o2fG(w); return takedrop_highrank(take, a, x); } break; + case n_reverse: { + if (xcr==0 || !isF64(w)) break; + f64* ap; + B a = m_f64arrv(&ap, xk+1); + FILL_TO(ap, el_f64, 0, m_f64(0), xk); + ap[xk] = o2fG(w); + return rotate_highrank(0, a, x); + } case n_transp: if (q_usz(w)) { usz a=o2sG(w); if (a= (u64)l_) { v_%= (i64)l_; if(v_<0) v_+= l_; } v_; }) -static NOINLINE B rotate_highrank(bool inv, B w, B x) { +NOINLINE B rotate_highrank(bool inv, B w, B x) { #define INV (inv? "⁼" : "") if (RNK(w)>1) thrF("⌽%U: 𝕨 must have rank at most 1 (%H ≡ ≢𝕨)", INV, w); B r; From 46704defb6922e9cad377ffac18d3d7ec4b31c63 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Thu, 4 Jul 2024 11:40:05 -0400 Subject: [PATCH 12/15] =?UTF-8?q?Convert=20list=E2=8A=B8=E2=86=91=CB=98=20?= =?UTF-8?q?to=20a=20single=20=E2=86=91=20call,=20likewise=20=E2=86=93=20an?= =?UTF-8?q?d=20=E2=8C=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/cells.c | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/src/builtins/cells.c b/src/builtins/cells.c index 963e2663..88866a44 100644 --- a/src/builtins/cells.c +++ b/src/builtins/cells.c @@ -7,6 +7,8 @@ B fne_c1(B, B); B shape_c2(B, B, B); B transp_c2(B, B, B); +B take_c2(B, B, B); +B join_c2(B, B, B); // from fold.c: B fold_rows(Md1D* d, B x); @@ -679,21 +681,38 @@ NOINLINE B for_cells_SA(B f, B w, B x, ur xcr, ur xr, u32 chr) { return shift_cells(w, x, cam, xsh[xk], el_or(TI(x,elType), selfElType(w)), rtid); } break; case n_take: case n_drop: { - if (xcr==0 || !isF64(w)) break; bool take = rtid==n_take; - f64* ap; - B a = m_f64arrv(&ap, xk+1); - if (!take) { FILL_TO(ap, el_f64, 0, m_f64(0), xk); } - else { PLAINLOOP for (usz i=0; i1) break; + usz wia = IA(w); + if (xcr < wia) break; // needs rank extension in the middle of x's shape + if (!take) a = C2(take, m_f64(-(i32)(xk+wia)), w); + else a = C2(join, C2(take, m_f64(xk), C1(fne, incG(x))), w); // (k↑≢𝕩)∾𝕨 + } return takedrop_highrank(take, a, x); } break; case n_reverse: { - if (xcr==0 || !isF64(w)) break; - f64* ap; - B a = m_f64arrv(&ap, xk+1); - FILL_TO(ap, el_f64, 0, m_f64(0), xk); - ap[xk] = o2fG(w); + B a; + if (isF64(w)) { + if (xcr < 1) break; + f64* ap; + a = m_f64arrv(&ap, xk+1); + FILL_TO(ap, el_f64, 0, m_f64(0), xk); + ap[xk] = o2fG(w); + } else { + if (!isArr(w) || RNK(w)>1) break; + usz wia = IA(w); + if (xcr < wia) break; + a = C2(take, m_f64(-(i32)(xk+wia)), w); + } return rotate_highrank(0, a, x); } case n_transp: From 48d77e722f47d10dcac44252353dba24a027dd5d Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Thu, 4 Jul 2024 12:03:26 -0400 Subject: [PATCH 13/15] =?UTF-8?q?Extend=20=CB=9D=20to=20=C2=B4=20conversio?= =?UTF-8?q?n=20(for=20singleton=20cells)=20to=20any=20rank?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/fold.c | 46 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/src/builtins/fold.c b/src/builtins/fold.c index 251b0683..d1049cca 100644 --- a/src/builtins/fold.c +++ b/src/builtins/fold.c @@ -376,6 +376,7 @@ u64 usum(B x) { // doesn't consume; will error on non-integers, or elements <0, B select_c1(B, B); B select_c2(B, B, B); +B shape_c1(B, B); static B m1c1(B t, B f, B x) { // consumes x B fn = m1_d(inc(t), inc(f)); B r = c1(fn, x); @@ -409,7 +410,19 @@ B insert_c1(Md1D* d, B x) { B f = d->f; } if (len==1) return C1(select, x); if (RARE(!isFun(f))) { decG(x); if (isMd(f)) thrM("Calling a modifier"); return inc(f); } - if (xr==1 && isPervasiveDyExt(f)) return m_unit(fold_c1(d, x)); + if (isPervasiveDyExt(f)) { + if (xr==1) return m_unit(fold_c1(d, x)); + if (len==IA(x)) { + B r = m_vec1(fold_c1(d, C1(shape, x))); + ur rr = xr - 1; + if (rr > 1) { + ShArr* rsh = m_shArr(rr); + PLAINLOOP for (ur i=0; ia[i] = 1; + arr_shReplace(a(r), rr, rsh); + } + return r; + } + } if (v(f)->flags) { u8 rtid = v(f)->flags-1; if (rtid==n_ltack) return C1(select, x); @@ -432,17 +445,32 @@ B insert_c1(Md1D* d, B x) { B f = d->f; return insert_base(f, x, 0, m_f64(0)); } B insert_c2(Md1D* d, B w, B x) { B f = d->f; - if (isAtm(x) || RNK(x)==0) thrM("˝: 𝕩 must have rank at least 1"); - if (*SH(x)==0) { decG(x); return w; } + ur xr; + if (isAtm(x) || (xr=RNK(x))==0) thrM("˝: 𝕩 must have rank at least 1"); + usz len = *SH(x); + if (len==0) { decG(x); return w; } if (RARE(!isFun(f))) { dec(w); decG(x); if (isMd(f)) thrM("Calling a modifier"); return inc(f); } - if (RNK(x)==1 && isPervasiveDyExt(f)) { - if (isAtm(w)) { - to_fold: return m_unit(fold_c2(d, w, x)); - } - if (RNK(w)==0) { + if (isPervasiveDyExt(f) && len==IA(x)) { + // 1-element arrays are always conformable + // final rank is higher of w, cell rank of x + ur rr = xr - 1; + if (isArr(w)) { + if (IA(w) != 1) goto skip; + ur wr = RNK(w); if (wr>rr) rr = wr; B w0=w; w = IGet(w,0); decG(w0); - goto to_fold; } + if (xr > 1) x = C1(shape, x); + B r = m_unit(fold_c2(d, w, x)); + if (rr > 0) { + if (rr == 1) arr_shVec(a(r)); + else { + ShArr* rsh = m_shArr(rr); + PLAINLOOP for (ur i=0; ia[i] = 1; + arr_shReplace(a(r), rr, rsh); + } + } + return r; + skip:; } if (v(f)->flags) { u8 rtid = v(f)->flags-1; From 201fe1e57c227859956a80df67e3ffa339fdb457 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Thu, 4 Jul 2024 15:23:41 -0400 Subject: [PATCH 14/15] Extend fold_rows to any rank, as long as stride is 1 --- src/builtins/cells.c | 32 ++++++++++++++++++-------------- src/builtins/fold.c | 15 ++++++++++----- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/builtins/cells.c b/src/builtins/cells.c index 88866a44..f7a0cd35 100644 --- a/src/builtins/cells.c +++ b/src/builtins/cells.c @@ -11,7 +11,7 @@ B take_c2(B, B, B); B join_c2(B, B, B); // from fold.c: -B fold_rows(Md1D* d, B x); +B fold_rows(Md1D* d, B x, usz n, usz m); B fold_rows_bit(Md1D* d, B x, usz n, usz m); B insert_cells_join(B x, usz* xsh, ur cr, ur k); B insert_cells_identity(B x, B f, usz* xsh, ur xr, ur k, u8 rtid); @@ -506,21 +506,25 @@ B for_cells_c1(B f, u32 xr, u32 cr, u32 k, B x, u32 chr) { // F⎉cr x, with arr if (m==1 || frtid==n_ltack) return select_cells(0 , x, cam, k, false); if ( frtid==n_rtack) return select_cells(m-1, x, cam, k, false); if (isPervasiveDyExt(fd->f) && 1==shProd(xsh, k+1, xr)) { + B r; + // special cases always return rank 1 + // incG(x) preserves the shape to restore afterwards if needed if (TI(x,elType)==el_bit) { - incG(x); // keep shape alive - B r = fold_rows_bit(fd, x, cam, m); - if (!q_N(r)) { - if (xr > 2) { - usz* rsh = arr_shAlloc(a(r), xr-1); - shcpy(rsh, xsh, k); - shcpy(rsh+k, xsh+k+1, xr-1-k); - } - decG(x); return r; - } - decG(x); + incG(x); r = fold_rows_bit(fd, x, cam, m); + if (q_N(r)) decG(x); // will try fold_rows + else goto finish_fold; } - // TODO extend to any rank - if (xr==2 && k==1 && m<=64 && m 2) { + usz* rsh = arr_shAlloc(a(r), xr-1); + shcpy(rsh, xsh, k); + shcpy(rsh+k, xsh+k+1, xr-1-k); + } + decG(x); return r; } } break; case n_scan: { diff --git a/src/builtins/fold.c b/src/builtins/fold.c index d1049cca..294215b2 100644 --- a/src/builtins/fold.c +++ b/src/builtins/fold.c @@ -512,19 +512,24 @@ B insert_cells_identity(B x, B f, usz* xsh, ur xr, ur k, u8 rtid) { decG(x); return taga(r); } -// Arithmetic fold/insert on rows of flat rank-2 array x +// Arithmetic fold/insert on -k-cells of flat array x +// Return a vector regardless of argument shape B transp_c1(B, B); -B join_c2(B, B, B); -B fold_rows(Md1D* fd, B x) { - assert(isArr(x) && RNK(x)==2); +B fold_rows(Md1D* fd, B x, usz n, usz m) { + assert(isArr(x) && IA(x)==n*m); // Target block size trying to avoid power-of-two lengths, from: // {𝕩/˜⌊´⊸= +˝˘ +˝¬∨`2|>⌊∘÷⟜2⍟(↕12) ⌊0.5+32÷˜𝕩÷⌜1+↕64} +⟜↕2⋆16 u64 block = (116053*8) >> arrTypeBitsLog(TY(x)); if (TI(x,elType)==el_bit || IA(x)/2 <= block) { + if (RNK(x) > 2) { + Arr* xc = cpyWithShape(x); + ShArr* sh = m_shArr(2); + sh->a[0] = n; sh->a[1] = m; + x = taga(arr_shReplace(xc, 2, sh)); + } x = C1(transp, x); return insert_c1(fd, x); } else { - usz *sh = SH(x); usz n = sh[0]; usz m = sh[1]; usz b = (block + m - 1) / m; // Normal block length usz b_max = b + b/4; // Last block max length MAKE_MUT(r, n); MUT_APPEND_INIT(r); From d625fc0d2183d0e384cc8f4ba2e246cee4595a3f Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Sun, 7 Jul 2024 15:52:33 -0400 Subject: [PATCH 15/15] Some tests for rank, type, etc. errors in cells/rank --- test/cases/cells.bqn | 45 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/test/cases/cells.bqn b/test/cases/cells.bqn index 260e9c42..50819073 100644 --- a/test/cases/cells.bqn +++ b/test/cases/cells.bqn @@ -21,6 +21,51 @@ !"˘: Argument frames don't agree (⟨3⟩ ≡ ≢𝕨, ⟨2⟩ ≡ ≢𝕩, common frame of 1 axes)" % "abc" ⊢˘ "ab" ! ∧´{𝕊: ! (∾≡{𝕨∾𝕩}´) (<•rand.Range∘≠⊸⊑ ⟨"ab",1‿2,⟨⟩,↕0,""⟩) ∾˜ (4•rand.Range≠)⊸⊏ ⟨1, {⇐}, 'a', <'a', <{⇐}, "ab", ↕0, ""⟩}¨↕10000 +# error cases that could be affected by special code +!"∧: Argument cannot have rank 0" % ∧˘↕2 +!"∨: Argument cannot have rank 0" % ∨˘"a" +!"Expected non-negative integer, got ¯3" % 2‿¯3/⎉1 6‿2⥊0 +!"/: Lengths of components of 𝕨 must match 𝕩 (3 ≠ 4)" % 1‿2‿3⊸/˘≍4‿5‿6‿7 +!"/: Simple 𝕨 must have rank 0 or 1 (2≡=𝕨)" % (2‿3‿1⥊↕4) /˘ ↕2 +!"𝕨/𝕩: Length of compound 𝕨 must be at most rank of 𝕩" % (<↕0)/˘○(5⊸⥊)<"ab" +!"⊏: Indexing out-of-bounds (24∊𝕨, 4≡≠𝕩)" % 1‿24⊏⎉1↕4‿4 +!"⊏: Indexing out-of-bounds (4∊𝕨, 4≡≠𝕩)" % ⊏⎉1˜6‿4⥊↕24 +!"𝕨⊏𝕩: 𝕨 must be an array of numbers or list of such arrays" % 0‿@‿¯1⊏⎉1 5‿2⥊0.5 +!"Expected integer, got ¯5.25" % ¯5.25⊏˘∘‿4⥊↕24 +!"⊏: Indexing out-of-bounds (1∊𝕨, 1≡≠𝕩)" % 0‿0‿1 ⊏˘○(≍˘) 10000×↕3 +!"⊏: 𝕩 cannot be a unit" % 0⊏˘5⥊<"a" +!"⊏: 𝕩 cannot be a unit" % (3‿0⥊⟨⟩)⊏˘↕3 +!"Expected integer, got 0.1" % 0.1⊑˘3‿5⥊↕15 +!"⊑: 𝕩 must be a list when 𝕨 is a number (3‿4 ≡ ≢𝕩)" % 5⊑˘↕2‿3‿4 +!">: Result rank too large (80 ≡ =𝕩, 205 ≡ =⊑𝕩)" % >⎉80 (200⥊1)⥊<(205⥊1)⥊1 +!"⎉: Result rank too large (195 ≡ =𝕩, 210 ≡ =𝔽v)" % >⎉5 (200⥊1)⥊<(205⥊1)⥊1 +!"∾: Lengths not matchable (⟨6⟩ ≡ ≢𝕨, 1‿1 ≡ ≢𝕩)" % ("abc"∾"def")∾˘○(3/≍)≍"a" +!"∾: Argument ranks must differ by 1 or less (0≡=𝕨, 2≡=𝕩)" % 1∾˘↕3‿3‿3 +!"∾: Lengths not matchable (4‿2 ≡ ≢𝕨, 3‿3 ≡ ≢𝕩)" % (3‿4‿2⥊4)∾˘3‿3‿3⥊5 +!"≍: 𝕨 and 𝕩 must have equal shapes (3‿4 ≡ ≢𝕨, 3‿3 ≡ ≢𝕩)" % (↕3‿4)≍⎉2 2‿3‿3⥊↕18 +!"≍: Result rank too large (255≡=𝕩)" % ≍⎉∞ 0⥊˜255⥊1 +!"shift: Lengths not matchable (⟨6⟩ ≡ ≢𝕨, 1‿1 ≡ ≢𝕩)" % ("abc"∾"def")«˘○(3/≍)≍"a" +!"shift: =𝕨 must be =𝕩 or ¯1+=𝕩 (0≡=𝕨, 2≡=𝕩)" % 1«˘↕2‿2‿2 +!"»: Argument cannot be a scalar" % »⎉0 2‿3‿1⥊↕6 +!"⌽: Argument cannot be a unit" % ⌽˘↕10 +!"Expected integer, got 1.5" % 1.5↑˘↕2‿3‿2 +!"↑: 𝕨 must have rank at most 1 (1‿2 ≡ ≢𝕨)" % (≍1‿2)⊸↑˘↕2‿3‿2 +!"↓: 𝕨 must have rank at most 1 (4‿2 ≡ ≢𝕨)" % (4‿2⥊↕8)↓˘○≍@ +!"Integer out of range: 1e20" % 1e20⌽˘3‿10⥊10 +!"Expected number" % 3‿4‿@⌽˘↕3‿4 +!"Expected integer, got 0.5" % 0.5⊸⌽˘4‿3⥊↕12 +!"↑: Argument must have rank at least 1" % ↑˘↕2 +!"↓: Argument must have rank at least 1" % ↓⎉0 2‿1⥊0 +!"⊐: 𝕩 cannot have rank 0" % ⊐˘"abcd" +!"⊒: Argument cannot have rank 0" % ⊒˘"abcd" +!"∊: Argument cannot have rank 0" % ∊˘"abcd" +!"⍋: 𝕨 must be sorted" % 0‿2‿1⊸⍋˘ 3‿4⥊↕12 +!"`: Shape of 𝕨 must match the cell of 𝕩 (⟨2⟩ ≡ ≢𝕨, 2‿3 ≡ ≢𝕩)" % (2‿2⥊1)+`˘2‿2‿3⥊0.4 +!"`: Shape of 𝕨 must match the cell of 𝕩 (⟨⟩ ≡ ≢𝕨, 3‿3 ≡ ≢𝕩)" % 2+`˘↕3‿3‿3 +!"´: Argument must be a list (3‿3 ≡ ≢𝕩)" % +´˘2‿3‿3⥊↕18 +!"´: 𝕩 must be a list (3‿3 ≡ ≢𝕩)" % 1+´˘2‿3‿3⥊↕18 +!"˝: 𝕩 must have rank at least 1" % +˝˘˘10‿10⥊↕100 + %USE tcc ⋄ ⟨2, 20, ¯2, ¯20, 0⟩ {𝕨 ↑_tcc 𝕩 ⋄ 𝕨 ↓_tcc 𝕩}⌜ ⟨<4, ↕5, 4‿5⥊↕20, 4‿5‿6⥊↕120⟩ %USE tcc ⋄ ⟨<, ≍, ⊏, ⥊⟩ {𝕎 _tcc 𝕩}⌜ ⟨<4, ↕5, 4‿5⥊↕20, 4‿5‿6⥊↕120, 2‿3‿4‿5⥊↕120⟩ %USE tcc ⋄ ⟨<, ≍, ⥊⟩ {𝕎 _tcc 𝕩}⌜ ⟨<4, ↕5, 4‿5⥊↕20, 4‿5‿6⥊↕120, 2‿3‿4‿5⥊↕120⟩