From b8e6996e7eee935c151a8d10053e056819fa6f7b Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Mon, 1 Aug 2022 17:27:22 -0400 Subject: [PATCH 1/6] Shape logic for Join of any list --- src/builtins/sfns.c | 51 +++++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/src/builtins/sfns.c b/src/builtins/sfns.c index 672cfe3e..24f5ce1d 100644 --- a/src/builtins/sfns.c +++ b/src/builtins/sfns.c @@ -883,36 +883,61 @@ B join_c1(B t, B x) { B x0 = GetU(x,0); B rf; if(SFNS_FILLS) rf = getFillQ(x0); - if (isAtm(x0)) goto base; // thrM("∾: Rank of items must be equal or greater than rank of argument"); - usz ir = rnk(x0); - usz* x0sh = a(x0)->sh; - if (ir==0) goto base; // thrM("∾: Rank of items must be equal or greater than rank of argument"); - - usz csz = arr_csz(x0); - usz cam = x0sh[0]; + ur r0 = isAtm(x0) ? 0 : rnk(x0); // Minimum element rank seen + ur r1 = r0; // Maximum + ur rr = r0; // Result rank, or minimum possible so far + usz* esh = NULL; + usz cam = 1; // Result length + if (r0) { + esh = a(x0)->sh; + cam = esh[0]; + } else { + rr++; + } + for (usz i = 1; i < xia; i++) { B c = GetU(x, i); - if (!isArr(c) || rnk(c)!=ir) goto base; // thrF("∾: All items in argument should have same rank (contained items with ranks %i and %i)", ir, isArr(c)? rnk(c) : 0); - usz* csh = a(c)->sh; - if (ir>1) for (usz j = 1; j < ir; j++) if (csh[j]!=x0sh[j]) thrF("∾: Item trailing shapes must be equal (contained arrays with shapes %H and %H)", x0, c); - cam+= a(c)->sh[0]; + ur cr = isAtm(c) ? 0 : rnk(c); + if (cr == 0) { + if (r1 > 1) thrF("∾: Item ranks in a list can differ by at most one (contained ranks %i and %i)", r0, r1); + r0=0; cam++; + } else { + usz* csh = a(c)->sh; + if (cr != r0) { + if (cr > r1) r1 = cr; else r0 = cr; + if (r1-r0 > 2) thrF("∾: Item ranks in a list can differ by at most one (contained ranks %i and %i)", r0, r1); + } + if (cr < rr) { + csh--; cam++; + } else { + if (cr>rr) { // Previous elements were cells + if (cam != i*esh[0]) thrM("∾: Item trailing shapes must be equal"); + esh--; rr++; cam = i; + } + cam+= csh[0]; + } + for (usz j = 1; j < cr; j++) if (csh[j]!=esh[j]) thrF("∾: Item trailing shapes must be equal (contained arrays with shapes %H and %H)", x0, c); + } if (SFNS_FILLS && !noFill(rf)) rf = fill_or(rf, getFillQ(c)); } + if (r1==0) thrM("∾: Some item rank must be equal or greater than rank of argument"); + usz csz = shProd(esh, 1, rr); MAKE_MUT(r, cam*csz); usz ri = 0; for (usz i = 0; i < xia; i++) { B c = GetU(x, i); + if (isAtm(c)) goto base; usz cia = a(c)->ia; mut_copy(r, ri, c, 0, cia); ri+= cia; } assert(ri==cam*csz); Arr* ra = mut_fp(r); - usz* sh = arr_shAlloc(ra, ir); + usz* sh = arr_shAlloc(ra, rr); if (sh) { sh[0] = cam; - shcpy(sh+1, x0sh+1, ir-1); + shcpy(sh+1, esh+1, rr-1); } decG(x); return SFNS_FILLS? qWithFill(taga(ra), rf) : taga(ra); From d9d421db04227a1c547d96ffc6e36e4a8e2e2138 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Mon, 1 Aug 2022 17:31:07 -0400 Subject: [PATCH 2/6] Handle atoms in Join of list --- src/builtins/sfns.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/builtins/sfns.c b/src/builtins/sfns.c index 24f5ce1d..281359b6 100644 --- a/src/builtins/sfns.c +++ b/src/builtins/sfns.c @@ -927,10 +927,14 @@ B join_c1(B t, B x) { usz ri = 0; for (usz i = 0; i < xia; i++) { B c = GetU(x, i); - if (isAtm(c)) goto base; - usz cia = a(c)->ia; - mut_copy(r, ri, c, 0, cia); - ri+= cia; + if (isArr(c)) { + usz cia = a(c)->ia; + mut_copy(r, ri, c, 0, cia); + ri+= cia; + } else { + mut_set(r, ri, inc(c)); + ri++; + } } assert(ri==cam*csz); Arr* ra = mut_fp(r); @@ -942,7 +946,6 @@ B join_c1(B t, B x) { decG(x); return SFNS_FILLS? qWithFill(taga(ra), rf) : taga(ra); } - base: return c1(rt_join, x); } B join_c2(B t, B w, B x) { From bf6a8c5699d8451571c78df477c437486846938c Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Mon, 1 Aug 2022 21:16:21 -0400 Subject: [PATCH 3/6] Handle any rank empty, and rank 0, in Join --- src/builtins/sfns.c | 55 +++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/src/builtins/sfns.c b/src/builtins/sfns.c index 281359b6..5b49cdb6 100644 --- a/src/builtins/sfns.c +++ b/src/builtins/sfns.c @@ -856,31 +856,35 @@ B drop_c2(B t, B w, B x) { extern B rt_join; B join_c1(B t, B x) { if (isAtm(x)) thrM("∾: Argument must be an array"); - if (rnk(x)==1) { - usz xia = a(x)->ia; - if (xia==0) { - B xf = getFillE(x); - if (isAtm(xf)) { - decA(xf); - decG(x); - if (!PROPER_FILLS) return emptyHVec(); - thrM("∾: Empty vector 𝕩 cannot have an atom fill element"); - } - decG(x); - ur ir = rnk(xf); - if (ir==0) thrM("∾: Empty vector 𝕩 cannot have a unit fill element"); - B xff = getFillQ(xf); - HArr_p r = m_harrUp(0); - usz* sh = arr_shAlloc((Arr*)r.c, ir); - if (sh) { - sh[0] = 0; - shcpy(sh+1, a(xf)->sh+1, ir-1); - } - dec(xf); - return withFill(r.b, xff); + + ur xr = rnk(x); + usz xia = a(x)->ia; + if (xia==0) { + B xf = getFillE(x); + if (isAtm(xf)) { + decA(xf); decG(x); + if (!PROPER_FILLS && xr==1) return emptyHVec(); + thrM("∾: Empty array 𝕩 cannot have an atom fill element"); } + ur ir = rnk(xf); + if (irsh; + if (xr>1) { + usz* xsh = a(x)->sh; + for (usz i = 0; i < xr; i++) sh[i] = xsh[i]*fsh[i]; + } + shcpy(sh+xr, fsh+xr, ir-xr); + } + dec(xf); decG(x); + return withFill(r.b, xff); + + } else if (xr==1) { SGetU(x) - B x0 = GetU(x,0); B rf; if(SFNS_FILLS) rf = getFillQ(x0); ur r0 = isAtm(x0) ? 0 : rnk(x0); // Minimum element rank seen @@ -945,8 +949,11 @@ B join_c1(B t, B x) { } decG(x); return SFNS_FILLS? qWithFill(taga(ra), rf) : taga(ra); + } else if (xr==0) { + return bqn_merge(x); + } else { + return c1(rt_join, x); } - return c1(rt_join, x); } B join_c2(B t, B w, B x) { if (isAtm(w)) w = m_atomUnit(w); From c1d5ca5c29d7757aa60caa8e1105ac781926aa92 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Wed, 3 Aug 2022 14:43:48 -0400 Subject: [PATCH 4/6] Switch from min and max to max and difference in Join shape checking --- src/builtins/sfns.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/builtins/sfns.c b/src/builtins/sfns.c index 5b49cdb6..9bd5256a 100644 --- a/src/builtins/sfns.c +++ b/src/builtins/sfns.c @@ -887,12 +887,12 @@ B join_c1(B t, B x) { SGetU(x) B x0 = GetU(x,0); B rf; if(SFNS_FILLS) rf = getFillQ(x0); - ur r0 = isAtm(x0) ? 0 : rnk(x0); // Minimum element rank seen - ur r1 = r0; // Maximum - ur rr = r0; // Result rank, or minimum possible so far + ur rm = isAtm(x0) ? 0 : rnk(x0); // Maximum element rank seen + ur rr = rm; // Result rank, or minimum possible so far + ur rd = 0; // Difference of max and min lengths (0 or 1) usz* esh = NULL; usz cam = 1; // Result length - if (r0) { + if (rm) { esh = a(x0)->sh; cam = esh[0]; } else { @@ -903,28 +903,26 @@ B join_c1(B t, B x) { B c = GetU(x, i); ur cr = isAtm(c) ? 0 : rnk(c); if (cr == 0) { - if (r1 > 1) thrF("∾: Item ranks in a list can differ by at most one (contained ranks %i and %i)", r0, r1); - r0=0; cam++; + if (rm > 1) thrF("∾: Item ranks in a list can differ by at most one (contained ranks %i and %i)", 0, rm); + rd=1; cam++; } else { usz* csh = a(c)->sh; - if (cr != r0) { - if (cr > r1) r1 = cr; else r0 = cr; - if (r1-r0 > 2) thrF("∾: Item ranks in a list can differ by at most one (contained ranks %i and %i)", r0, r1); - } - if (cr < rr) { - csh--; cam++; - } else { - if (cr>rr) { // Previous elements were cells + ur cd = rm - cr; + if (RARE(cd > rd)) { + if ((ur)(cd+1-rd) > 2-rd) thrF("∾: Item ranks in a list can differ by at most one (contained ranks %i and %i)", rm-rd*(cr==rm), cr); + if (cr > rr) { // Previous elements were cells if (cam != i*esh[0]) thrM("∾: Item trailing shapes must be equal"); - esh--; rr++; cam = i; + esh--; rr=cr; cam=i; } - cam+= csh[0]; + rm = cr>rm ? cr : rm; + rd = 1; } + if (cr < rm) { csh--; cam++; } else { cam+=csh[0]; } for (usz j = 1; j < cr; j++) if (csh[j]!=esh[j]) thrF("∾: Item trailing shapes must be equal (contained arrays with shapes %H and %H)", x0, c); } if (SFNS_FILLS && !noFill(rf)) rf = fill_or(rf, getFillQ(c)); } - if (r1==0) thrM("∾: Some item rank must be equal or greater than rank of argument"); + if (rm==0) thrM("∾: Some item rank must be equal or greater than rank of argument"); usz csz = shProd(esh, 1, rr); MAKE_MUT(r, cam*csz); From 1d891388b596c5ade82d76b616245447a292313f Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Fri, 5 Aug 2022 21:38:57 -0400 Subject: [PATCH 5/6] High-rank join shape checking --- src/builtins/sfns.c | 95 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 87 insertions(+), 8 deletions(-) diff --git a/src/builtins/sfns.c b/src/builtins/sfns.c index 9bd5256a..4572a247 100644 --- a/src/builtins/sfns.c +++ b/src/builtins/sfns.c @@ -894,7 +894,7 @@ B join_c1(B t, B x) { usz cam = 1; // Result length if (rm) { esh = a(x0)->sh; - cam = esh[0]; + cam = *esh++; } else { rr++; } @@ -904,27 +904,28 @@ B join_c1(B t, B x) { ur cr = isAtm(c) ? 0 : rnk(c); if (cr == 0) { if (rm > 1) thrF("∾: Item ranks in a list can differ by at most one (contained ranks %i and %i)", 0, rm); - rd=1; cam++; + rd=rm; cam++; } else { usz* csh = a(c)->sh; ur cd = rm - cr; if (RARE(cd > rd)) { if ((ur)(cd+1-rd) > 2-rd) thrF("∾: Item ranks in a list can differ by at most one (contained ranks %i and %i)", rm-rd*(cr==rm), cr); if (cr > rr) { // Previous elements were cells - if (cam != i*esh[0]) thrM("∾: Item trailing shapes must be equal"); - esh--; rr=cr; cam=i; + esh--; + if (cam != i * *esh) thrM("∾: Item trailing shapes must be equal"); + rr=cr; cam=i; } rm = cr>rm ? cr : rm; rd = 1; } - if (cr < rm) { csh--; cam++; } else { cam+=csh[0]; } - for (usz j = 1; j < cr; j++) if (csh[j]!=esh[j]) thrF("∾: Item trailing shapes must be equal (contained arrays with shapes %H and %H)", x0, c); + cam += cr < rm ? 1 : *csh++; + if (!eqShPart(csh, esh, cr-1)) thrF("∾: Item trailing shapes must be equal (contained arrays with shapes %H and %H)", x0, c); } if (SFNS_FILLS && !noFill(rf)) rf = fill_or(rf, getFillQ(c)); } if (rm==0) thrM("∾: Some item rank must be equal or greater than rank of argument"); - usz csz = shProd(esh, 1, rr); + usz csz = shProd(esh, 0, rr-1); MAKE_MUT(r, cam*csz); usz ri = 0; for (usz i = 0; i < xia; i++) { @@ -943,13 +944,91 @@ B join_c1(B t, B x) { usz* sh = arr_shAlloc(ra, rr); if (sh) { sh[0] = cam; - shcpy(sh+1, esh+1, rr-1); + shcpy(sh+1, esh, rr-1); } decG(x); return SFNS_FILLS? qWithFill(taga(ra), rf) : taga(ra); } else if (xr==0) { return bqn_merge(x); } else { + SGetU(x) + B x0 = GetU(x,0); + B rf; if(SFNS_FILLS) rf = getFillQ(x0); + ur r0 = isAtm(x0) ? 0 : rnk(x0); + + usz ia = a(x)->ia; + usz* xsh = a(x)->sh; + usz tlen = 4*xr+2*r0; for (usz a=0; aa; // Temp buffer + st[xr-1]=1; for (ur a=xr; a-->1; ) st[a-1] = st[a]*xsh[a]; // Stride + usz* tsh0 = st+xr; usz* tsh = tsh0+xr+r0; // Test shapes + // Length buffer i is lp+lp[i] + usz* lp = tsh+xr+r0; lp[0]=xr; for (usz a=1; a r0) thrM("∾: Ranks of argument items too small"); + continue; + } + usz step = st[a]; + usz *ll = lp+lp[a]; + ll[0] = r0; + for (usz i=1; ir1s) r1s=ll[i]; + ur r1 = r1s; + ur add = r1==r0; + if (au+add > r0) thrM("∾: Ranks of argument items too small"); + for (usz i=0; i1) thrF("∾: Item ranks along an axis can differ by at most one (contained ranks %i and %i along axis %i)", ll[i], r1, a); + ll[i] = -1; + } else { + B c = GetU(x, i*step); + ll[i] = a(c)->sh[au]; + } + } + + // Check shapes + for (usz j=0; jsh; + lr = r-(r0-au); + shcpy(tsh,sh,r); shcpy(tsh0,sh,r); + if (!add) shcpy(tsh +lr+1, tsh +lr , r-lr ); + else shcpy(tsh0+lr , tsh0+lr+1, r-lr-1); + } + for (usz i=1; ish; } + if (cr != r1-rd) thrF("∾: Incompatible item ranks", base, c); + if (!eqShPart(rd?tsh0:tsh, sh, cr)) thrF("∾: Incompatible item shapes (contained arrays with shapes %H and %H along axis %i)", base, c, a); + if (SFNS_FILLS && !noFill(rf)) rf = fill_or(rf, getFillQ(c)); + } + } + au += add; + + // Transform to lengths by changing -1 to 1, and get total + usz len = 0; + for (usz i=0; i Date: Sat, 6 Aug 2022 17:30:30 -0400 Subject: [PATCH 6/6] Finish multidimensional join --- src/builtins/sfns.c | 88 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 18 deletions(-) diff --git a/src/builtins/sfns.c b/src/builtins/sfns.c index 4572a247..c59a419e 100644 --- a/src/builtins/sfns.c +++ b/src/builtins/sfns.c @@ -853,7 +853,6 @@ B drop_c2(B t, B w, B x) { return c2(rt_drop, w, x); } -extern B rt_join; B join_c1(B t, B x) { if (isAtm(x)) thrM("∾: Argument must be an array"); @@ -956,7 +955,7 @@ B join_c1(B t, B x) { B rf; if(SFNS_FILLS) rf = getFillQ(x0); ur r0 = isAtm(x0) ? 0 : rnk(x0); - usz ia = a(x)->ia; + usz xia = a(x)->ia; usz* xsh = a(x)->sh; usz tlen = 4*xr+2*r0; for (usz a=0; aa; // Temp buffer @@ -965,16 +964,20 @@ B join_c1(B t, B x) { // Length buffer i is lp+lp[i] usz* lp = tsh+xr+r0; lp[0]=xr; for (usz a=1; a r0) thrM("∾: Ranks of argument items too small"); - continue; + if (!tr) thrM("∾: Ranks of argument items too small"); + st[a] = ll[0] = a(x0)->sh[r0-tr]; + tr--; continue; } usz step = st[a]; - usz *ll = lp+lp[a]; ll[0] = r0; for (usz i=1; ir1s) r1s=ll[i]; ur r1 = r1s; - ur add = r1==r0; - if (au+add > r0) thrM("∾: Ranks of argument items too small"); + ur a0 = r1==r0; // Root has axis a + if (tr < a0) thrM("∾: Ranks of argument items too small"); for (usz i=0; ish[au]; + ll[i] = a(c)->sh[r0-tr]; } } // Check shapes - for (usz j=0; jsh; - lr = r-(r0-au); + lr = r - tr; shcpy(tsh,sh,r); shcpy(tsh0,sh,r); - if (!add) shcpy(tsh +lr+1, tsh +lr , r-lr ); - else shcpy(tsh0+lr , tsh0+lr+1, r-lr-1); + if (!a0) shcpy(tsh +lr+1, tsh +lr , tr ); + else shcpy(tsh0+lr , tsh0+lr+1, tr-1); } for (usz i=1; ish + r0-tr : NULL; // Trailing shape + usz csz = shProd(csh, 0, tr); + MAKE_MUT(r, shProd(st, 0, xr)*csz); + // Element index and effective shape, updated progressively + usz *ei =tsh; for (usz i=0; iia; + if (eia) { + usz rj = ri; + usz *ii=tsh0; for (usz k=0; k