Specialize ApdMut to reshape if there's only one append

This commit is contained in:
Marshall Lochbaum 2024-07-03 22:17:06 -04:00
parent 76a40491e9
commit 3b49294145
4 changed files with 39 additions and 7 deletions

View File

@ -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; 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))); }
@ -569,7 +569,7 @@ B for_cells_c1(B f, u32 xr, u32 cr, u32 k, B x, u32 chr) { // F⎉cr x, with arr
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);
for (usz i=0,xp=0; i<cam; i++) APDD(r, fc1(f, SLICEI(x)));
decG(x);
@ -646,7 +646,7 @@ NOINLINE B for_cells_AS(B f, B w, B x, ur wcr, ur wr, u32 chr) {
}
generic:;
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));
decG(w); return taga(APD_SH_GET(r, chr));
}
@ -703,7 +703,7 @@ NOINLINE B for_cells_SA(B f, B w, B x, ur xcr, ur xr, u32 chr) {
return const_cells(x, xk, xsh, inc(f), chr);
}
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)));
decG(x); return taga(APD_SH_GET(r, chr));
}
@ -757,7 +757,7 @@ NOINLINE B for_cells_AA(B f, B w, B x, ur wcr, ur xcr, u32 chr) {
}
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(x, xsh, xk, xkM? cam : cam0, 1) usz xp=0;
FC2 fc2 = c2fn(f);

View File

@ -460,7 +460,7 @@ B bqn_merge(B x, u32 type) {
return taga(r);
}
M_APD_SH(r, xr, SH(x));
M_APD_SH_N(r, xr, SH(x), xia);
SGetU(x)
for (usz i = 0; i < xia; i++) APD(r, GetU(x, i));
decG(x);

View File

@ -665,6 +665,37 @@ NOINLINE void apd_sh_init(ApdMut* m, B x) {
else m->apd(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; 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) {
u8 xe = isArr(x)? TI(x,elType) : selfElType(x);

View File

@ -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