Merge pull request #114 from mlochbaum/simplify
Miscellaneous strength reductions
This commit is contained in:
commit
c466db24bc
@ -7,10 +7,18 @@
|
|||||||
B fne_c1(B, B);
|
B fne_c1(B, B);
|
||||||
B shape_c2(B, B, B);
|
B shape_c2(B, B, B);
|
||||||
B transp_c2(B, B, B);
|
B transp_c2(B, B, B);
|
||||||
B fold_rows(Md1D* d, B x); // from fold.c
|
B take_c2(B, B, B);
|
||||||
B fold_rows_bit(Md1D* d, B x, usz n, usz m); // from fold.c
|
B join_c2(B, B, B);
|
||||||
|
|
||||||
|
// from fold.c:
|
||||||
|
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);
|
||||||
|
|
||||||
B scan_rows_bit(u8, B x, usz m); // from scan.c
|
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 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
|
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
|
// 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
|
||||||
@ -165,7 +173,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;
|
if (mr==wr) w=s; else x=s;
|
||||||
return fc2(m_f64(0), w, x);
|
return fc2(m_f64(0), w, x);
|
||||||
} else {
|
} 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;
|
S_KSLICES(b, bsh, mr, cam, 1) usz bp=0;
|
||||||
if (mr==wr) { SGetU(w); for (usz i=0; i<cam; i++) APDD(r, fc2(m_f64(0), GetU(w,i), SLICEI(b))); }
|
if (mr==wr) { SGetU(w); for (usz i=0; i<cam; i++) APDD(r, fc2(m_f64(0), GetU(w,i), SLICEI(b))); }
|
||||||
else { SGetU(x); for (usz i=0; i<cam; i++) APDD(r, fc2(m_f64(0), SLICEI(b), GetU(x,i))); }
|
else { SGetU(x); for (usz i=0; i<cam; i++) APDD(r, fc2(m_f64(0), SLICEI(b), GetU(x,i))); }
|
||||||
@ -178,45 +186,28 @@ NOINLINE B leading_axis_arith(FC2 fc2, B w, B x, usz* wsh, usz* xsh, ur mr) { //
|
|||||||
|
|
||||||
// fast special-case implementations
|
// 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)
|
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);
|
ur xr = RNK(x);
|
||||||
assert(xr>1 && k<xr);
|
assert(xr>1 && k<xr);
|
||||||
usz* xsh = SH(x);
|
usz* xsh = SH(x);
|
||||||
usz csz = shProd(xsh, k+1, xr);
|
usz csz = shProd(xsh, k+1, xr);
|
||||||
usz take = leaf? 1 : csz;
|
usz l = xsh[k];
|
||||||
usz jump = xsh[k] * csz;
|
assert(0<=ind && ind<l);
|
||||||
assert(cam*jump == IA(x));
|
assert(cam*l*csz == IA(x));
|
||||||
Arr* ra;
|
Arr* ra;
|
||||||
if (take==jump) {
|
usz take = leaf? 1 : csz;
|
||||||
|
if (l==1 && take==csz) {
|
||||||
ra = cpyWithShape(incG(x));
|
ra = cpyWithShape(incG(x));
|
||||||
arr_shErase(ra, 1);
|
arr_shErase(ra, 1);
|
||||||
} else if (take==1) {
|
} else {
|
||||||
u8 xe = TI(x,elType);
|
u8 xe = TI(x,elType);
|
||||||
if (xe==el_B) {
|
u8 ewl= elwBitLog(xe);
|
||||||
SGet(x)
|
u8 xl = leaf? ewl : multWidthLog(csz, ewl);
|
||||||
HArr_p rp = m_harrUv(cam);
|
usz ria = cam*take;
|
||||||
for (usz i = 0; i < cam; i++) rp.a[i] = Get(x, i*jump+n);
|
if (xl>=7 || (xl<3 && xl>0)) { // generic case
|
||||||
NOGC_E; ra = (Arr*)rp.c;
|
MAKE_MUT_INIT(rm, ria, TI(x,elType)); MUTG_INIT(rm);
|
||||||
} else {
|
usz jump = l * csz;
|
||||||
void* rp = m_tyarrlbp(&ra, elwBitLog(xe), cam, el2t(xe));
|
usz xi = take*ind;
|
||||||
void* xp = tyany_ptr(x);
|
|
||||||
switch(xe) {
|
|
||||||
case el_bit:
|
|
||||||
#if SINGELI
|
|
||||||
if (jump < 64) si_select_cells_bit_lt64(xp, rp, cam, jump, n);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
for (usz i=0; i<cam; i++) bitp_set(rp, i, bitp_get(xp, i*jump+n));
|
|
||||||
break;
|
|
||||||
case el_i8: case el_c8: PLAINLOOP for (usz i=0; i<cam; i++) ((u8* )rp)[i] = ((u8* )xp)[i*jump+n]; break;
|
|
||||||
case el_i16: case el_c16: PLAINLOOP for (usz i=0; i<cam; i++) ((u16*)rp)[i] = ((u16*)xp)[i*jump+n]; break;
|
|
||||||
case el_i32: case el_c32: PLAINLOOP for (usz i=0; i<cam; i++) ((u32*)rp)[i] = ((u32*)xp)[i*jump+n]; break;
|
|
||||||
case el_f64: PLAINLOOP for (usz i=0; i<cam; i++) ((f64*)rp)[i] = ((f64*)xp)[i*jump+n]; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
MAKE_MUT_INIT(rm, cam*take, TI(x,elType)); MUTG_INIT(rm);
|
|
||||||
usz xi = take*n;
|
|
||||||
usz ri = 0;
|
usz ri = 0;
|
||||||
for (usz i = 0; i < cam; i++) {
|
for (usz i = 0; i < cam; i++) {
|
||||||
mut_copyG(rm, ri, x, xi, take);
|
mut_copyG(rm, ri, x, xi, take);
|
||||||
@ -224,6 +215,29 @@ static NOINLINE B select_cells(usz n, B x, usz cam, usz k, bool leaf) { // n {le
|
|||||||
ri+= take;
|
ri+= take;
|
||||||
}
|
}
|
||||||
ra = mut_fp(rm);
|
ra = mut_fp(rm);
|
||||||
|
} else if (xe==el_B) {
|
||||||
|
assert(take == 1);
|
||||||
|
SGet(x)
|
||||||
|
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, ewl, ria, el2t(xe));
|
||||||
|
void* xp = tyany_ptr(x);
|
||||||
|
switch(xl) {
|
||||||
|
case 0:
|
||||||
|
#if SINGELI
|
||||||
|
if (l < 64) si_select_cells_bit_lt64(xp, rp, cam, l, ind);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
for (usz i=0; i<cam; i++) bitp_set(rp, i, bitp_get(xp, i*l+ind));
|
||||||
|
break;
|
||||||
|
case 3: PLAINLOOP for (usz i=0; i<cam; i++) ((u8* )rp)[i] = ((u8* )xp)[i*l+ind]; break;
|
||||||
|
case 4: PLAINLOOP for (usz i=0; i<cam; i++) ((u16*)rp)[i] = ((u16*)xp)[i*l+ind]; break;
|
||||||
|
case 5: PLAINLOOP for (usz i=0; i<cam; i++) ((u32*)rp)[i] = ((u32*)xp)[i*l+ind]; break;
|
||||||
|
case 6: PLAINLOOP for (usz i=0; i<cam; i++) ((f64*)rp)[i] = ((f64*)xp)[i*l+ind]; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
usz* rsh = arr_shAlloc(ra, leaf? k : xr-1);
|
usz* rsh = arr_shAlloc(ra, leaf? k : xr-1);
|
||||||
if (rsh) {
|
if (rsh) {
|
||||||
@ -444,8 +458,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));
|
return taga(arr_shReplace(r, k+1, rsh));
|
||||||
}
|
}
|
||||||
case n_shifta: case n_shiftb: {
|
case n_shifta: case n_shiftb: {
|
||||||
if (IA(x)==0) goto noSpecial;
|
if (IA(x)==0) return x;
|
||||||
if (cr!=1) goto base;
|
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);
|
B xf = getFillR(x);
|
||||||
if (noFill(xf)) goto base;
|
if (noFill(xf)) goto base;
|
||||||
return shift_cells(xf, x, cam, xsh[k], TI(x,elType), rtid);
|
return shift_cells(xf, x, cam, xsh[k], TI(x,elType), rtid);
|
||||||
@ -453,48 +471,75 @@ B for_cells_c1(B f, u32 xr, u32 cr, u32 k, B x, u32 chr) { // F⎉cr x, with arr
|
|||||||
case n_transp: {
|
case n_transp: {
|
||||||
return cr<=1? x : transp_cells(xr-1, k, x);
|
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) {
|
if (TY(f) == t_md1D) {
|
||||||
Md1D* fd = c(Md1D,f);
|
Md1D* fd = c(Md1D,f);
|
||||||
u8 rtid = fd->m1->flags-1;
|
u8 rtid = fd->m1->flags-1;
|
||||||
if (rtid==n_const) { f=fd->f; goto const_f; }
|
switch(rtid) {
|
||||||
usz *sh = SH(x);
|
case n_const: f=fd->f; goto const_f;
|
||||||
if (((rtid==n_fold && cr==1) || rtid==n_insert) && TI(x,elType)!=el_B
|
case n_cell: cr-= cr>0; return for_cells_c1(fd->f, xr, cr, xr-cr, x, U'˘');
|
||||||
&& isFun(fd->f) && 1==shProd(sh, k+1, xr) && sh[k] > 0) {
|
case n_fold: if (cr != 1) break; // else fall through
|
||||||
usz m = sh[k];
|
case n_insert: if (cr>0 && isFun(fd->f)) {
|
||||||
u8 frtid = v(fd->f)->flags-1;
|
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 (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 ( frtid==n_rtack) return select_cells(m-1, x, cam, k, false);
|
||||||
if (isPervasiveDyExt(fd->f)) {
|
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) {
|
if (TI(x,elType)==el_bit) {
|
||||||
incG(x); // keep shape alive
|
incG(x); r = fold_rows_bit(fd, x, cam, m);
|
||||||
B r = fold_rows_bit(fd, x, shProd(sh, 0, k), m);
|
if (q_N(r)) decG(x); // will try fold_rows
|
||||||
if (!q_N(r)) {
|
else goto finish_fold;
|
||||||
|
}
|
||||||
|
if (m<=64 && m<cam) {
|
||||||
|
incG(x); r = fold_rows (fd, x, cam, m);
|
||||||
|
}
|
||||||
|
else break;
|
||||||
|
finish_fold:
|
||||||
if (xr > 2) {
|
if (xr > 2) {
|
||||||
usz* rsh = arr_shAlloc(a(r), xr-1);
|
usz* rsh = arr_shAlloc(a(r), xr-1);
|
||||||
shcpy(rsh, sh, k);
|
shcpy(rsh, xsh, k);
|
||||||
shcpy(rsh+k, sh+k+1, xr-1-k);
|
shcpy(rsh+k, xsh+k+1, xr-1-k);
|
||||||
}
|
}
|
||||||
decG(x); return r;
|
decG(x); return r;
|
||||||
}
|
}
|
||||||
decG(x);
|
} break;
|
||||||
}
|
case n_scan: {
|
||||||
// TODO extend to any rank
|
if (cr==0) break;
|
||||||
if (xr==2 && k==1 && m<=64 && m<sh[0]) return fold_rows(fd, x);
|
usz m = xsh[k];
|
||||||
}
|
|
||||||
}
|
|
||||||
if (rtid==n_scan) {
|
|
||||||
if (cr==0) goto noSpecial;
|
|
||||||
usz *sh = SH(x); usz m = sh[k];
|
|
||||||
if (m<=1 || IA(x)==0) return x;
|
if (m<=1 || IA(x)==0) return x;
|
||||||
if (!isFun(fd->f)) goto base;
|
if (!isFun(fd->f)) break;
|
||||||
u8 frtid = v(fd->f)->flags-1;
|
u8 frtid = v(fd->f)->flags-1;
|
||||||
if (frtid==n_rtack) return x;
|
if (frtid==n_rtack) return x;
|
||||||
if (TI(x,elType)==el_bit && (isPervasiveDyExt(fd->f)||frtid==n_ltack)
|
if (TI(x,elType)==el_bit && (isPervasiveDyExt(fd->f)||frtid==n_ltack)
|
||||||
&& 1==shProd(sh, k+1, xr)) {
|
&& 1==shProd(xsh, k+1, xr)) {
|
||||||
B r = scan_rows_bit(frtid, x, m); if (!q_N(r)) return r;
|
B r = scan_rows_bit(frtid, x, m); if (!q_N(r)) return r;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (TY(f) == t_md2D) {
|
} else if (TY(f) == t_md2D) {
|
||||||
Md2D* fd = c(Md2D,f);
|
Md2D* fd = c(Md2D,f);
|
||||||
@ -531,7 +576,7 @@ B for_cells_c1(B f, u32 xr, u32 cr, u32 k, B x, u32 chr) { // F⎉cr x, with arr
|
|||||||
|
|
||||||
base:;
|
base:;
|
||||||
|
|
||||||
M_APD_SH(r, k, xsh);
|
M_APD_SH_N(r, k, xsh, cam);
|
||||||
S_KSLICES(x, xsh, k, cam, 1); FC1 fc1 = c1fn(f);
|
S_KSLICES(x, xsh, k, cam, 1); FC1 fc1 = c1fn(f);
|
||||||
for (usz i=0,xp=0; i<cam; i++) APDD(r, fc1(f, SLICEI(x)));
|
for (usz i=0,xp=0; i<cam; i++) APDD(r, fc1(f, SLICEI(x)));
|
||||||
decG(x);
|
decG(x);
|
||||||
@ -608,7 +653,7 @@ NOINLINE B for_cells_AS(B f, B w, B x, ur wcr, ur wr, u32 chr) {
|
|||||||
}
|
}
|
||||||
generic:;
|
generic:;
|
||||||
S_KSLICES(w, wsh, wk, cam, 1) incBy(x, cam-1);
|
S_KSLICES(w, wsh, wk, cam, 1) incBy(x, cam-1);
|
||||||
M_APD_SH(r, wk, wsh); FC2 fc2 = c2fn(f);
|
M_APD_SH_N(r, wk, wsh, cam); FC2 fc2 = c2fn(f);
|
||||||
for (usz i=0,wp=0; i<cam; i++) APDD(r, fc2(f, SLICEI(w), x));
|
for (usz i=0,wp=0; i<cam; i++) APDD(r, fc2(f, SLICEI(w), x));
|
||||||
decG(w); return taga(APD_SH_GET(r, chr));
|
decG(w); return taga(APD_SH_GET(r, chr));
|
||||||
}
|
}
|
||||||
@ -618,40 +663,79 @@ 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);
|
usz* xsh=SH(x); usz cam=shProd(xsh,0,xk);
|
||||||
if (cam==0) return rank2_empty(f, w, 0, x, xk, chr);
|
if (cam==0) return rank2_empty(f, w, 0, x, xk, chr);
|
||||||
if (isFun(f)) {
|
if (isFun(f)) {
|
||||||
if (IA(x)==0) goto generic;
|
|
||||||
u8 rtid = v(f)->flags-1;
|
u8 rtid = v(f)->flags-1;
|
||||||
if (rtid==n_rtack) { dec(w); return x; }
|
switch(rtid) {
|
||||||
if (rtid==n_ltack) return const_cells(x, xk, xsh, w, chr);
|
case n_rtack: dec(w); return x;
|
||||||
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);
|
case n_ltack: return const_cells(x, xk, xsh, w, chr);
|
||||||
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);
|
case n_select: if (isF64(w) && xcr>=1) {
|
||||||
if ((rtid==n_shifta || rtid==n_shiftb) && xk==1 && xr==2 && isAtm(w)) {
|
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); }
|
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);
|
return shift_cells(w, x, cam, xsh[xk], el_or(TI(x,elType), selfElType(w)), rtid);
|
||||||
}
|
} break;
|
||||||
if (rtid==n_take || rtid==n_drop) {
|
case n_take: case n_drop: {
|
||||||
if (xcr==0 || !isF64(w)) goto generic;
|
|
||||||
bool take = rtid==n_take;
|
bool take = rtid==n_take;
|
||||||
|
B a;
|
||||||
|
if (isF64(w)) {
|
||||||
|
if (xcr < 1) break;
|
||||||
f64* ap;
|
f64* ap;
|
||||||
B a = m_f64arrv(&ap, xk+1);
|
a = m_f64arrv(&ap, xk+1);
|
||||||
if (!take) { FILL_TO(ap, el_f64, 0, m_f64(0), xk); }
|
if (!take) { FILL_TO(ap, el_f64, 0, m_f64(0), xk); }
|
||||||
else { usz* xsh=SH(x); PLAINLOOP for (usz i=0; i<xk; i++) ap[i] = xsh[i]; }
|
else { PLAINLOOP for (usz i=0; i<xk; i++) ap[i] = xsh[i]; }
|
||||||
ap[xk] = o2fG(w);
|
ap[xk] = o2fG(w);
|
||||||
return takedrop_highrank(take, a, x);
|
} else {
|
||||||
|
if (!isArr(w) || RNK(w)>1) 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↑≢𝕩)∾𝕨
|
||||||
}
|
}
|
||||||
if (rtid==n_transp && q_usz(w)) { usz a=o2sG(w); if (a<xcr) return transp_cells(a+xk, xk, x); }
|
return takedrop_highrank(take, a, x);
|
||||||
if (isPervasiveDy(f)) {
|
} break;
|
||||||
|
case n_reverse: {
|
||||||
|
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:
|
||||||
|
if (q_usz(w)) { usz a=o2sG(w); if (a<xcr) return transp_cells(a+xk, xk, x); }
|
||||||
|
break;
|
||||||
|
default: if (isPervasiveDy(f)) {
|
||||||
if (isAtm(w)) return c2(f, w, x);
|
if (isAtm(w)) return c2(f, w, x);
|
||||||
if (RNK(w)!=xcr || !eqShPart(SH(w), xsh+xk, xcr)) goto generic;
|
if (IA(x)==0) break;
|
||||||
if (TI(w,elType)==el_B || TI(x,elType)==el_B || (IA(w)>(2048*8)>>arrTypeBitsLog(TY(w)) && IA(w)!=IA(x))) goto generic;
|
if (RNK(w)!=xcr || !eqShPart(SH(w), xsh+xk, xcr)) break;
|
||||||
|
if (TI(w,elType)==el_B || TI(x,elType)==el_B || (IA(w)>(2048*8)>>arrTypeBitsLog(TY(w)) && IA(w)!=IA(x))) break;
|
||||||
return c2(f, C2(shape, C1(fne, incG(x)), w), x);
|
return c2(f, C2(shape, C1(fne, incG(x)), w), x);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else if (!isMd(f)) {
|
} else if (!isMd(f)) {
|
||||||
dec(w);
|
dec(w);
|
||||||
return const_cells(x, xk, xsh, inc(f), chr);
|
return const_cells(x, xk, xsh, inc(f), chr);
|
||||||
}
|
}
|
||||||
generic:;
|
|
||||||
S_KSLICES(x, xsh, xk, cam, 1) incBy(w, cam-1);
|
S_KSLICES(x, xsh, xk, cam, 1) incBy(w, cam-1);
|
||||||
M_APD_SH(r, xk, xsh); FC2 fc2 = c2fn(f);
|
M_APD_SH_N(r, xk, xsh, cam); FC2 fc2 = c2fn(f);
|
||||||
for (usz i=0,xp=0; i<cam; i++) APDD(r, fc2(f, w, SLICEI(x)));
|
for (usz i=0,xp=0; i<cam; i++) APDD(r, fc2(f, w, SLICEI(x)));
|
||||||
decG(x); return taga(APD_SH_GET(r, chr));
|
decG(x); return taga(APD_SH_GET(r, chr));
|
||||||
}
|
}
|
||||||
@ -705,7 +789,7 @@ NOINLINE B for_cells_AA(B f, B w, B x, ur wcr, ur xcr, u32 chr) {
|
|||||||
}
|
}
|
||||||
generic:;
|
generic:;
|
||||||
|
|
||||||
M_APD_SH(r, zk, zsh);
|
M_APD_SH_N(r, zk, zsh, cam);
|
||||||
S_KSLICES(w, wsh, wk, xkM? cam0 : cam, 1) usz wp=0;
|
S_KSLICES(w, wsh, wk, xkM? cam0 : cam, 1) usz wp=0;
|
||||||
S_KSLICES(x, xsh, xk, xkM? cam : cam0, 1) usz xp=0;
|
S_KSLICES(x, xsh, xk, xkM? cam : cam0, 1) usz xp=0;
|
||||||
FC2 fc2 = c2fn(f);
|
FC2 fc2 = c2fn(f);
|
||||||
|
|||||||
@ -14,7 +14,8 @@
|
|||||||
// Insert with rank (˝˘ or ˝⎉k), or fold on flat array
|
// Insert with rank (˝˘ or ˝⎉k), or fold on flat array
|
||||||
// SHOULD optimize dyadic insert with rank
|
// SHOULD optimize dyadic insert with rank
|
||||||
// Length 1, ⊣⊢: implemented as ⊏˘
|
// 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:
|
// Boolean operand, cell size 1:
|
||||||
// +: popcount
|
// +: popcount
|
||||||
// Rows length ≤64: extract rows, popcount each
|
// Rows length ≤64: extract rows, popcount each
|
||||||
@ -375,28 +376,58 @@ u64 usum(B x) { // doesn't consume; will error on non-integers, or elements <0,
|
|||||||
|
|
||||||
B select_c1(B, B);
|
B select_c1(B, B);
|
||||||
B select_c2(B, B, B);
|
B select_c2(B, B, B);
|
||||||
|
B shape_c1(B, B);
|
||||||
static B m1c1(B t, B f, B x) { // consumes x
|
static B m1c1(B t, B f, B x) { // consumes x
|
||||||
B fn = m1_d(inc(t), inc(f));
|
B fn = m1_d(inc(t), inc(f));
|
||||||
B r = c1(fn, x);
|
B r = c1(fn, x);
|
||||||
decG(fn);
|
decG(fn);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
extern GLOBAL B rt_insert;
|
|
||||||
extern B insert_base(B f, B x, bool has_w, B w); // from cells.c
|
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;
|
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);
|
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 (len==1) return C1(select, x);
|
||||||
if (RARE(!isFun(f))) { decG(x); if (isMd(f)) thrM("Calling a modifier"); return inc(f); }
|
if (RARE(!isFun(f))) { decG(x); if (isMd(f)) thrM("Calling a modifier"); return inc(f); }
|
||||||
ur xr = RNK(x);
|
if (isPervasiveDyExt(f)) {
|
||||||
if (xr==1 && isPervasiveDyExt(f)) return m_unit(fold_c1(d, x));
|
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; i<rr; i++) rsh->a[i] = 1;
|
||||||
|
arr_shReplace(a(r), rr, rsh);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (v(f)->flags) {
|
if (v(f)->flags) {
|
||||||
u8 rtid = v(f)->flags-1;
|
u8 rtid = v(f)->flags-1;
|
||||||
if (rtid==n_ltack) return C1(select, x);
|
if (rtid==n_ltack) return C1(select, x);
|
||||||
if (rtid==n_rtack) return C2(select, m_f64(-1), 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;
|
if (xr==1) return x;
|
||||||
ShArr* rsh;
|
ShArr* rsh;
|
||||||
if (xr>2) {
|
if (xr>2) {
|
||||||
@ -414,17 +445,32 @@ B insert_c1(Md1D* d, B x) { B f = d->f;
|
|||||||
return insert_base(f, x, 0, m_f64(0));
|
return insert_base(f, x, 0, m_f64(0));
|
||||||
}
|
}
|
||||||
B insert_c2(Md1D* d, B w, B x) { B f = d->f;
|
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");
|
ur xr;
|
||||||
if (*SH(x)==0) { decG(x); return w; }
|
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 (RARE(!isFun(f))) { dec(w); decG(x); if (isMd(f)) thrM("Calling a modifier"); return inc(f); }
|
||||||
if (RNK(x)==1 && isPervasiveDyExt(f)) {
|
if (isPervasiveDyExt(f) && len==IA(x)) {
|
||||||
if (isAtm(w)) {
|
// 1-element arrays are always conformable
|
||||||
to_fold: return m_unit(fold_c2(d, w, x));
|
// final rank is higher of w, cell rank of x
|
||||||
}
|
ur rr = xr - 1;
|
||||||
if (RNK(w)==0) {
|
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);
|
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; i<rr; i++) rsh->a[i] = 1;
|
||||||
|
arr_shReplace(a(r), rr, rsh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
skip:;
|
||||||
}
|
}
|
||||||
if (v(f)->flags) {
|
if (v(f)->flags) {
|
||||||
u8 rtid = v(f)->flags-1;
|
u8 rtid = v(f)->flags-1;
|
||||||
@ -434,19 +480,56 @@ B insert_c2(Md1D* d, B w, B x) { B f = d->f;
|
|||||||
return insert_base(f, x, 1, w);
|
return insert_base(f, x, 1, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Arithmetic fold/insert on rows of flat rank-2 array x
|
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 -k-cells of flat array x
|
||||||
|
// Return a vector regardless of argument shape
|
||||||
B transp_c1(B, B);
|
B transp_c1(B, B);
|
||||||
B join_c2(B, B, B);
|
B fold_rows(Md1D* fd, B x, usz n, usz m) {
|
||||||
B fold_rows(Md1D* fd, B x) {
|
assert(isArr(x) && IA(x)==n*m);
|
||||||
assert(isArr(x) && RNK(x)==2);
|
|
||||||
// Target block size trying to avoid power-of-two lengths, from:
|
// Target block size trying to avoid power-of-two lengths, from:
|
||||||
// {𝕩/˜⌊´⊸= +˝˘ +˝¬∨`2|>⌊∘÷⟜2⍟(↕12) ⌊0.5+32÷˜𝕩÷⌜1+↕64} +⟜↕2⋆16
|
// {𝕩/˜⌊´⊸= +˝˘ +˝¬∨`2|>⌊∘÷⟜2⍟(↕12) ⌊0.5+32÷˜𝕩÷⌜1+↕64} +⟜↕2⋆16
|
||||||
u64 block = (116053*8) >> arrTypeBitsLog(TY(x));
|
u64 block = (116053*8) >> arrTypeBitsLog(TY(x));
|
||||||
if (TI(x,elType)==el_bit || IA(x)/2 <= block) {
|
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);
|
x = C1(transp, x);
|
||||||
return insert_c1(fd, x);
|
return insert_c1(fd, x);
|
||||||
} else {
|
} else {
|
||||||
usz *sh = SH(x); usz n = sh[0]; usz m = sh[1];
|
|
||||||
usz b = (block + m - 1) / m; // Normal block length
|
usz b = (block + m - 1) / m; // Normal block length
|
||||||
usz b_max = b + b/4; // Last block max length
|
usz b_max = b + b/4; // Last block max length
|
||||||
MAKE_MUT(r, n); MUT_APPEND_INIT(r);
|
MAKE_MUT(r, n); MUT_APPEND_INIT(r);
|
||||||
|
|||||||
@ -998,7 +998,10 @@ B shiftb_c1(B t, B x) {
|
|||||||
if (ia==0) return x;
|
if (ia==0) return x;
|
||||||
B xf = getFillE(x);
|
B xf = getFillE(x);
|
||||||
usz csz = arr_csz(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);
|
MAKE_MUT_INIT(r, ia, el_or(TI(x,elType), selfElType(xf))); MUTG_INIT(r);
|
||||||
mut_copyG(r, csz, x, 0, ia-csz);
|
mut_copyG(r, csz, x, 0, ia-csz);
|
||||||
mut_fillG(r, 0, xf, csz);
|
mut_fillG(r, 0, xf, csz);
|
||||||
@ -1025,6 +1028,10 @@ B shifta_c1(B t, B x) {
|
|||||||
if (ia==0) return x;
|
if (ia==0) return x;
|
||||||
B xf = getFillE(x);
|
B xf = getFillE(x);
|
||||||
usz csz = arr_csz(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);
|
MAKE_MUT_INIT(r, ia, el_or(TI(x,elType), selfElType(xf))); MUTG_INIT(r);
|
||||||
mut_copyG(r, 0, x, csz, ia-csz);
|
mut_copyG(r, 0, x, csz, ia-csz);
|
||||||
mut_fillG(r, ia-csz, xf, csz);
|
mut_fillG(r, ia-csz, xf, csz);
|
||||||
@ -1059,7 +1066,7 @@ static u64 bit_reverse(u64 x) {
|
|||||||
B reverse_c1(B t, B x) {
|
B reverse_c1(B t, B x) {
|
||||||
if (isAtm(x) || RNK(x)==0) thrM("⌽: Argument cannot be a unit");
|
if (isAtm(x) || RNK(x)==0) thrM("⌽: Argument cannot be a unit");
|
||||||
usz n = *SH(x);
|
usz n = *SH(x);
|
||||||
if (n==0) return x;
|
if (n<=1) return x;
|
||||||
u8 xl = cellWidthLog(x);
|
u8 xl = cellWidthLog(x);
|
||||||
u8 xt = arrNewType(TY(x));
|
u8 xt = arrNewType(TY(x));
|
||||||
if (xl<=6 && (xl>=3 || xl==0)) {
|
if (xl<=6 && (xl>=3 || xl==0)) {
|
||||||
@ -1115,7 +1122,7 @@ B reverse_c1(B t, B x) {
|
|||||||
B reverse_c2(B t, B w, B x);
|
B reverse_c2(B t, B w, B x);
|
||||||
|
|
||||||
#define WRAP_ROT(V, L) ({ i64 v_ = (V); usz l_ = (L); if ((u64)v_ >= (u64)l_) { v_%= (i64)l_; if(v_<0) v_+= l_; } v_; })
|
#define WRAP_ROT(V, L) ({ i64 v_ = (V); usz l_ = (L); if ((u64)v_ >= (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? "⁼" : "")
|
#define INV (inv? "⁼" : "")
|
||||||
if (RNK(w)>1) thrF("⌽%U: 𝕨 must have rank at most 1 (%H ≡ ≢𝕨)", INV, w);
|
if (RNK(w)>1) thrF("⌽%U: 𝕨 must have rank at most 1 (%H ≡ ≢𝕨)", INV, w);
|
||||||
B r;
|
B r;
|
||||||
|
|||||||
@ -73,11 +73,15 @@ SHOULD_INLINE void arr_check_size(u64 sz, u8 type, usz ia) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
// Log of width in bits: max of 7, and also return 7 if not power of 2
|
// 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 bit
|
||||||
|
if (n & (n-1)) return 7; // Not power of 2
|
||||||
|
return lw + CTZ(n | 128>>lw); // Max of 7; also handle n==0
|
||||||
|
}
|
||||||
|
SHOULD_INLINE u8 kCellWidthLog(B x, ur k) {
|
||||||
assert(isArr(x) && RNK(x)>=1);
|
assert(isArr(x) && RNK(x)>=1);
|
||||||
u8 lw = arrTypeBitsLog(TY(x));
|
u8 lw = arrTypeBitsLog(TY(x));
|
||||||
if (LIKELY(RNK(x)==1)) return lw;
|
ur xr = RNK(x);
|
||||||
usz csz = arr_csz(x);
|
if (LIKELY(xr <= k)) return lw;
|
||||||
if (csz & (csz-1)) return 7; // Not power of 2
|
return multWidthLog(shProd(SH(x), k, xr), lw);
|
||||||
return lw + CTZ(csz | 128>>lw); // Max of 7; also handle csz==0
|
|
||||||
}
|
}
|
||||||
|
SHOULD_INLINE u8 cellWidthLog(B x) { return kCellWidthLog(x, 1); }
|
||||||
|
|||||||
@ -460,7 +460,7 @@ B bqn_merge(B x, u32 type) {
|
|||||||
return taga(r);
|
return taga(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
M_APD_SH(r, xr, SH(x));
|
M_APD_SH_N(r, xr, SH(x), xia);
|
||||||
SGetU(x)
|
SGetU(x)
|
||||||
for (usz i = 0; i < xia; i++) APD(r, GetU(x, i));
|
for (usz i = 0; i < xia; i++) APD(r, GetU(x, i));
|
||||||
decG(x);
|
decG(x);
|
||||||
|
|||||||
@ -129,7 +129,7 @@ NOINLINE B load_fullpath(B path, B name) {
|
|||||||
|
|
||||||
GLOBAL HArr* comps_curr;
|
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;
|
rt_group, rt_under, rt_find;
|
||||||
Block* load_buildBlock(B x, B src, B path, B name, Scope* sc, i32 nsResult) { // consumes x,src
|
Block* load_buildBlock(B x, B src, B path, B name, Scope* sc, i32 nsResult) { // consumes x,src
|
||||||
B fullpath = load_fullpath(path, name);
|
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_under = Get(rtObjRaw, n_under ));
|
||||||
gc_add(rt_find = Get(rtObjRaw, n_find ));
|
gc_add(rt_find = Get(rtObjRaw, n_find ));
|
||||||
gc_add(rt_depth = Get(rtObjRaw, n_depth ));
|
gc_add(rt_depth = Get(rtObjRaw, n_depth ));
|
||||||
gc_add(rt_insert = Get(rtObjRaw, n_insert));
|
|
||||||
|
|
||||||
for (usz i = 0; i < RT_LEN; i++) {
|
for (usz i = 0; i < RT_LEN; i++) {
|
||||||
#ifdef RT_WRAP
|
#ifdef RT_WRAP
|
||||||
@ -542,7 +541,7 @@ void load_init() { // very last init function
|
|||||||
load_rt = frtObj;
|
load_rt = frtObj;
|
||||||
|
|
||||||
rt_select = rt_slash = rt_group = rt_find = bi_invalidFn;
|
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_under = rt_depth = bi_invalidMd2;
|
||||||
|
|
||||||
rt_invFnRegFn = rt_invFnSwapFn = invalidFn_c1;
|
rt_invFnRegFn = rt_invFnSwapFn = invalidFn_c1;
|
||||||
|
|||||||
@ -665,6 +665,37 @@ NOINLINE void apd_sh_init(ApdMut* m, B x) {
|
|||||||
else m->apd(m, x);
|
else m->apd(m, x);
|
||||||
if (xe==el_B) NOGC_E;
|
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; i<rr0; i++) assert(m->rsh0[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; i<rr0; i++) rsh->a[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) {
|
NOINLINE void apd_widen(ApdMut* m, B x, ApdFn* const* fns) {
|
||||||
u8 xe = isArr(x)? TI(x,elType) : selfElType(x);
|
u8 xe = isArr(x)? TI(x,elType) : selfElType(x);
|
||||||
|
|||||||
@ -265,7 +265,7 @@ struct ApdMut {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
ApdFn apd_tot_init, apd_sh_init;
|
ApdFn apd_tot_init, apd_sh_init, apd_reshape;
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
ApdFn apd_dbg_apd;
|
ApdFn apd_dbg_apd;
|
||||||
ApdEnd apd_dbg_end;
|
ApdEnd apd_dbg_end;
|
||||||
@ -275,6 +275,7 @@ ApdFn apd_tot_init, apd_sh_init;
|
|||||||
#endif
|
#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_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(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 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 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
|
#define APDD(M, A) ({ B av_ = (A); M.apd(&M, av_); dec(av_); }) // consumes A
|
||||||
|
|||||||
@ -21,6 +21,51 @@
|
|||||||
!"˘: Argument frames don't agree (⟨3⟩ ≡ ≢𝕨, ⟨2⟩ ≡ ≢𝕩, common frame of 1 axes)" % "abc" ⊢˘ "ab"
|
!"˘: 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
|
! ∧´{𝕊: ! (∾≡{𝕨∾𝕩}´) (<•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 ⋄ ⟨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⟩
|
||||||
%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⟩
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user