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