Merge pull request #83 from mlochbaum/trivial

Identity and constant operand special code
This commit is contained in:
dzaima 2023-05-19 13:15:34 +03:00 committed by GitHub
commit ad82b63ce3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 162 additions and 77 deletions

View File

@ -32,24 +32,25 @@ B takedrop_highrank(bool take, B w, B x); // from sfns.c
BSS2A X##_slc = TI(X,slice); \
incByG(X, (i64)X##_sn + ((i64)DX-1));
#define S_SLICES(X, SLN) usz* X##_sh = SH(X); S_KSLICES(X, X##_sh, 1, SLN, 0)
#define SLICE(X, S) taga(arr_shSetUO(X##_slc(X, S, X##_csz), X##_cr, X##_csh))
#define SLICEI(X) ({ B r = SLICE(X, X##p); X##p+= X##_csz; r; })
// Used by Insert in fold.c
B insert_base(B f, B x, usz xia, bool has_w, B w) {
B insert_base(B f, B x, bool has_w, B w) {
assert(isArr(x) && RNK(x)>0);
S_SLICES(x, *x_sh)
usz p = xia;
usz* xsh = SH(x);
usz xn = xsh[0];
S_KSLICES(x, xsh, 1, xn, 0)
usz p = xn*x_csz;
B r = w;
if (!has_w) {
p -= x_csz;
p -= x_csz; xn--;
r = SLICE(x, p);
}
FC2 fc2 = c2fn(f);
while(p!=0) {
while (xn--) {
p-= x_csz;
r = fc2(f, SLICE(x, p), r);
}
@ -303,6 +304,29 @@ static ur cell_rank(f64 r, f64 k) { // ⎉k over arg rank r
return k<0? (k+r<0? 0 : k+r) : (k>r? r : k);
}
// v˙⎉(-k) x
static B const_cells(B x, ur k, usz* xsh, B v, u32 chr) { // consumes v, x
u32 vr;
if (isAtm(v) || RNK(v)==0) {
if (k!=1) { vr = 0; goto rank0; }
usz cam = xsh[0];
decG(x);
return C2(shape, m_usz(cam), v);
} else {
vr = RNK(v);
if (vr+k > UR_MAX) thrF("%c: Result rank too large", chr);
rank0:;
f64* shp; B sh = m_f64arrv(&shp, k+vr);
PLAINLOOP for (usz i=0; i<k; i++) shp[i] = xsh[i];
if (vr) {
usz* vsh = SH(v);
PLAINLOOP for (usz i=0; i<vr; i++) shp[k+i] = vsh[i];
}
decG(x);
return C2(shape, sh, v);
}
}
NOINLINE B for_cells_AS(B f, B w, B x, ur wcr, ur wr, u32 chr);
NOINLINE B for_cells_SA(B f, B w, B x, ur xcr, ur xr, u32 chr);
@ -318,6 +342,8 @@ B for_cells_c1(B f, u32 xr, u32 cr, u32 k, B x, u32 chr) { // F⎉cr x, with arr
if (isFun(f)) {
u8 rtid = v(f)->flags-1;
switch(rtid) {
case n_ltack: case n_rtack:
return x;
case n_lt:
if (cam==0) goto noCells; // toCells/toKCells don't set outer array fill
return k==1 && RNK(x)>1? toCells(x) : k==0? m_unit(x) : toKCells(x, k);
@ -375,26 +401,8 @@ B for_cells_c1(B f, u32 xr, u32 cr, u32 k, B x, u32 chr) { // F⎉cr x, with arr
if (rtid==n_after && !isCallable(fd->g)) return for_cells_AS(fd->f, x, inc(fd->g), cr, xr, chr);
}
} else if (!isMd(f)) {
const_f:; inc(f);
u32 fr;
if (isAtm(f) || RNK(f)==0) {
if (k!=1) { fr = 0; goto const_f_cont; }
usz cam = xsh[0];
decG(x);
return C2(shape, m_usz(cam), f);
} else {
fr = RNK(f);
if (fr+k > UR_MAX) thrF("%c: Result rank too large", chr);
const_f_cont:;
f64* shp; B sh = m_f64arrv(&shp, fr+k);
PLAINLOOP for (usz i=0; i<k; i++) shp[i] = xsh[i];
if (isArr(f)) {
usz* fsh = SH(f);
PLAINLOOP for (usz i=0; i<fr; i++) shp[i+k] = fsh[i];
}
decG(x);
return C2(shape, sh, f);
}
const_f:;
return const_cells(x, k, xsh, inc(f), chr);
}
noSpecial:;
@ -482,13 +490,19 @@ NOINLINE B for_cells_AS(B f, B w, B x, ur wcr, ur wr, u32 chr) {
ur wk = wr-wcr; assert(wk>0 && wcr<wr);
usz* wsh=SH(w); usz cam=shProd(wsh,0,wk);
if (cam==0) return rank2_empty(f, w, wk, x, 0, chr);
if (isFun(f) && IA(w)!=0) {
if (isPervasiveDy(f)) {
if (isFun(f)) {
u8 rtid = v(f)->flags-1;
if (rtid==n_ltack) { dec(x); return w; }
if (rtid==n_rtack) return const_cells(w, wk, wsh, x, chr);
if (IA(w)!=0 && isPervasiveDy(f)) {
if (isAtm(x)) return c2(f, w, x);
if (RNK(x)!=wcr || !eqShPart(SH(x), wsh+wk, wcr)) goto generic;
if (TI(w,elType)==el_B || TI(x,elType)==el_B || (IA(x)>(2048*8)>>arrTypeBitsLog(TY(x)) && IA(w)!=IA(x))) goto generic;
return c2(f, w, C2(shape, C1(fne, incG(w)), x));
}
} else if (!isMd(f)) {
dec(x);
return const_cells(w, wk, wsh, inc(f), chr);
}
generic:;
S_KSLICES(w, wsh, wk, cam, 1) incBy(x, cam-1);
@ -501,8 +515,11 @@ NOINLINE B for_cells_SA(B f, B w, B x, ur xcr, ur xr, u32 chr) {
ur xk = xr-xcr; assert(xk>0 && xcr<xr);
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) && IA(x)!=0) {
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)) {
@ -526,6 +543,9 @@ NOINLINE B for_cells_SA(B f, B w, B x, ur xcr, ur xr, u32 chr) {
if (TI(w,elType)==el_B || TI(x,elType)==el_B || (IA(w)>(2048*8)>>arrTypeBitsLog(TY(w)) && IA(w)!=IA(x))) goto generic;
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);
@ -557,6 +577,8 @@ NOINLINE B for_cells_AA(B f, B w, B x, ur wcr, ur xcr, u32 chr) {
if (isFun(f)) {
if (wk==xk) {
u8 rtid = v(f)->flags-1;
if (rtid==n_rtack) { decG(w); return x; }
if (rtid==n_ltack) { decG(x); return w; }
if (rtid==n_feq || rtid==n_fne) {
Arr* r = match_cells(rtid!=n_feq, w, x, wr, xr, wk, cam);
if (r==NULL) goto generic;
@ -571,6 +593,9 @@ NOINLINE B for_cells_AA(B f, B w, B x, ur wcr, ur xcr, u32 chr) {
if ((wk>mr?mr:wk) != (xk>mr?mr:xk) || !eqShPart(wsh, xsh, mr)) goto generic;
return c2(f, w, x);
}
} else if (!isMd(f)) {
dec(xkM? w : x);
return const_cells(xkM? x : w, zk, zsh, inc(f), chr);
}
generic:;

View File

@ -168,8 +168,9 @@ B fold_c1(Md1D* d, B x) { B f = d->f;
thrM("´: No identity found");
}
}
if (RARE(!isFun(f))) { decG(x); if (isMd(f)) thrM("Calling a modifier"); return inc(f); }
u8 xe = TI(x,elType);
if (isFun(f) && v(f)->flags) {
if (v(f)->flags) {
u8 rtid = v(f)->flags-1;
if (rtid==n_ltack) { B r = IGet(x, 0 ); decG(x); return r; }
if (rtid==n_rtack) { B r = IGet(x, ia-1); decG(x); return r; }
@ -235,13 +236,15 @@ B fold_c1(Md1D* d, B x) { B f = d->f;
B fold_c2(Md1D* d, B w, B x) { B f = d->f;
if (isAtm(x) || RNK(x)!=1) thrF("´: 𝕩 must be a list (%H ≡ ≢𝕩)", x);
usz ia = IA(x);
if (RARE(ia==0)) { decG(x); return w; }
if (RARE(!isFun(f))) { dec(w); decG(x); if (isMd(f)) thrM("Calling a modifier"); return inc(f); }
u8 xe = TI(x,elType);
if (isFun(f) && v(f)->flags) {
if (v(f)->flags) {
u8 rtid = v(f)->flags-1;
if (rtid==n_ltack) {
B r = w;
if (ia) { dec(w); r=IGet(x, 0); }
decG(x); return r;
B r = IGet(x, 0);
dec(w); decG(x); return r;
}
if (rtid==n_rtack) { decG(x); return w; }
if (!isF64(w) || xe>el_f64) goto base;
@ -263,8 +266,8 @@ B fold_c2(Md1D* d, B w, B x) { B f = d->f;
f64 r = sum_fns[sel](tyany_ptr(x), ia, wf);
decG(x); return m_f64(r);
}
if (rtid==n_floor) { f64 r=wf; if (ia>0) { f64 m=min_fns[xe-el_i8](tyany_ptr(x), ia); if (m<r) r=m; } decG(x); return m_f64(r); } // ⌊
if (rtid==n_ceil ) { f64 r=wf; if (ia>0) { f64 m=max_fns[xe-el_i8](tyany_ptr(x), ia); if (m>r) r=m; } decG(x); return m_f64(r); } // ⌈
if (rtid==n_floor) { f64 r=wf; f64 m=min_fns[xe-el_i8](tyany_ptr(x), ia); if (m<r) r=m; decG(x); return m_f64(r); } // ⌊
if (rtid==n_ceil ) { f64 r=wf; f64 m=max_fns[xe-el_i8](tyany_ptr(x), ia); if (m>r) r=m; decG(x); return m_f64(r); } // ⌈
i32 wi = wf;
if (rtid==n_mul | rtid==n_and) { // ×/∧
void *xv = tyany_ptr(x);
@ -322,6 +325,8 @@ u64 usum(B x) { // doesn't consume; will error on non-integers, or elements <0,
neg: thrM("Didn't expect negative integer");
}
B select_c1(B, B);
B select_c2(B, 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);
@ -329,17 +334,21 @@ static B m1c1(B t, B f, B x) { // consumes x
return r;
}
extern B rt_insert;
extern B insert_base(B f, B x, usz xia, 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;
if (isAtm(x) || RNK(x)==0) thrM("˝: 𝕩 must have rank at least 1");
usz xia = IA(x);
if (xia==0) { SLOW2("!𝕎˝𝕩", f, x); return m1c1(rt_insert, f, x); }
if (isFun(f)) {
usz len = *SH(x);
if (len==0) { SLOW2("!𝕎˝𝕩", f, x); return m1c1(rt_insert, f, x); }
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;
ur xr = RNK(x);
if (xr==1 && isPervasiveDyExt(f)) return m_unit(fold_c1(d, x));
if (rtid == n_join) {
if (rtid==n_ltack) return C1(select, x);
if (rtid==n_rtack) return C2(select, m_f64(-1), x);
if (rtid==n_join) {
if (xr==1) return x;
ShArr* rsh;
if (xr>2) {
@ -354,26 +363,27 @@ B insert_c1(Md1D* d, B x) { B f = d->f;
return taga(r);
}
}
return insert_base(f, x, xia, 0, bi_N);
return insert_base(f, x, 0, bi_N);
}
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");
usz xia = IA(x);
B r = w;
if (xia==0) { decG(x); return r; }
if (isFun(f)) {
if (RNK(x)==1 && isPervasiveDyExt(f)) {
if (isAtm(w)) {
to_fold: return m_unit(fold_c2(d, w, x));
}
if (RNK(w)==0) {
B w0=w; w = IGet(w,0); decG(w0);
goto to_fold;
}
if (*SH(x)==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) {
B w0=w; w = IGet(w,0); decG(w0);
goto to_fold;
}
}
return insert_base(f, x, xia, 1, w);
if (v(f)->flags) {
u8 rtid = v(f)->flags-1;
if (rtid==n_ltack) { dec(w); return C1(select, x); }
if (rtid==n_rtack) { decG(x); return w; }
}
return insert_base(f, x, 1, w);
}
// Arithmetic fold/insert on rows of flat rank-2 array x

View File

@ -42,10 +42,13 @@ B each_c1(Md1D* d, B x) { B f = d->f;
if (EACH_FILLS) xf = getFillR(x);
if (isAtm(x)) r = m_hunit(c1(f, x));
else if (isFun(f)) r = eachm_fn(f, x, c(Fun,f)->c1);
else {
if (isMd(f)) if (isAtm(x) || IA(x)) { decR(x); thrM("Calling a modifier"); }
else if (isFun(f)) {
u8 rtid = v(f)->flags-1;
if (rtid==n_ltack || rtid==n_rtack) return x;
r = eachm_fn(f, x, c(Fun,f)->c1);
} else {
usz ia = IA(x);
if (isMd(f) && ia>0) { decR(x); thrM("Calling a modifier"); }
MAKE_MUT(rm, ia);
mut_fill(rm, 0, f, ia);
r = mut_fcd(rm, x);
@ -72,10 +75,25 @@ B tbl_c2(Md1D* d, B w, B x) { B f = d->f;
usz* rsh;
FC2 fc2 = c2fn(f);
if (isFun(f) && TI(w,arrD1) && isPervasiveDyExt(f)) {
if (RARE(!isFun(f))) {
if (isMd(f) && ria>0) thrM("Calling a modifier");
MAKE_MUT(rm, ria);
mut_fill(rm, 0, f, ria);
Arr* ra = mut_fp(rm);
rsh = arr_shAlloc(ra, rr);
r = taga(ra);
} else if (v(f)->flags-1 == n_ltack) {
Arr* wd = arr_shVec(TI(w,slice)(incG(w), 0, wia));
r = C2(slash, m_i32(xia), taga(wd));
goto arith_finish;
} else if (v(f)->flags-1 == n_rtack) {
r = C2(shape, m_f64(ria), incG(x));
goto arith_finish;
} else if (TI(w,arrD1) && isPervasiveDyExt(f)) {
if (TI(x,arrD1) && wia>=4 && xia<2560>>arrTypeBitsLog(TY(x))) {
Arr* wd = arr_shVec(TI(w,slice)(incG(w), 0, wia));
r = fc2(f, C2(slash, m_i32(xia), taga(wd)), C2(shape, m_f64(ria), incG(x)));
arith_finish:;
if(RARE(!reusable(r))) r = taga(cpyWithShape(r));
arr_shErase(a(r), 1);
} else if (xia>7 && wia>0) {
@ -136,7 +154,7 @@ B swap_c2(Md1D* d, B w, B x) { return c2(d->f, x , w); }
B timed_c2(Md1D* d, B w, B x) { B f = d->f;
i64 am = o2i64(w);
if (am<=0) thrM("•_timed: 𝕨 must be an integer greater than 1");
incBy(x, am);
incBy(x, am-1);
FC1 fc1 = c1fn(f);
u64 sns = nsTime();
for (i64 i = 0; i < am; i++) dec(fc1(f, x));

View File

@ -178,14 +178,35 @@ static B scan_plus(f64 r0, B x, u8 xe, usz ia) {
#endif
}
B fne_c1(B, B);
B shape_c2(B, B, B);
B scan_c1(Md1D* d, B x) { B f = d->f;
if (isAtm(x) || RNK(x)==0) thrM("`: Argument cannot have rank 0");
ur xr = RNK(x);
usz ia = IA(x);
if (ia==0) return x;
if (*SH(x)<=1 || ia==0) return x;
if (RARE(!isFun(f))) {
if (isMd(f)) thrM("Calling a modifier");
B xf = getFillR(x);
MAKE_MUT(rm, ia);
usz csz = arr_csz(x);
mut_copy(rm, 0, x, 0, csz);
mut_fill(rm, csz, f, ia-csz);
return withFill(mut_fcd(rm, x), xf);
}
u8 xe = TI(x,elType);
if (xr==1 && xe<=el_f64 && isFun(f) && v(f)->flags) {
if (v(f)->flags) {
u8 rtid = v(f)->flags-1;
if (rtid==n_rtack) return x;
if (rtid==n_ltack) {
usz csz = arr_csz(x);
B s = C1(fne, incG(x));
Arr* r = TI(x,slice)(x, 0, csz);
return C2(shape, s, taga(r));
}
if (!(xr==1 && xe<=el_f64)) goto base;
if (xe==el_bit) {
if (rtid==n_add ) return scan_add_bool(x, ia); // +
if (rtid==n_or | rtid==n_ceil ) return scan_or(x, ia); // ∨⌈
@ -237,9 +258,21 @@ B add_c2(B, B, B);
B scan_c2(Md1D* d, B w, B x) { B f = d->f;
if (isAtm(x) || RNK(x)==0) thrM("`: 𝕩 cannot have rank 0");
ur xr = RNK(x); usz* xsh = SH(x); usz ia = IA(x);
if (isArr(w)? !ptr_eqShape(SH(w), RNK(w), xsh+1, xr-1) : xr!=1) thrF("`: Shape of 𝕨 must match the cell of 𝕩 (%H ≡ ≢𝕨, %H ≡ ≢𝕩)", w, x);
if (ia==0) { dec(w); return x; }
if (RARE(!isFun(f))) {
if (isMd(f)) thrM("Calling a modifier");
B xf = getFillR(x);
MAKE_MUT(rm, ia);
mut_fill(rm, 0, f, ia);
return withFill(mut_fcd(rm, x), xf);
}
u8 xe = TI(x,elType);
if (xr==1 && elNum(xe) && isFun(f) && v(f)->flags && isF64(w)) {
if (v(f)->flags) {
u8 rtid = v(f)->flags-1;
if (rtid==n_rtack) { dec(w); return x; }
if (rtid==n_ltack) return C2(shape, C1(fne, x), w);
if (!(xr==1 && elNum(xe) && xe<=el_f64)) goto base;
if (rtid==n_floor) return scan2_min_num(w, x, xe, ia); // ⌊
if (rtid==n_ceil ) return scan2_max_num(w, x, xe, ia); // ⌈
@ -286,17 +319,12 @@ B scan_c2(Md1D* d, B w, B x) { B f = d->f;
FC2 fc2 = c2fn(f);
if (isArr(w)) {
if (!ptr_eqShape(SH(w), RNK(w), xsh+1, xr-1)) thrF("`: Shape of 𝕨 must match the cell of 𝕩 (%H ≡ ≢𝕨, %H ≡ ≢𝕩)", w, x);
if (ia!=0) {
usz csz = arr_csz(x);
SGet(w)
for (; i < csz; i++) r.a[i] = fc2(f, Get(w,i), xget(xa,i));
for (; i < ia; i++) r.a[i] = fc2(f, inc(r.a[i-csz]), xget(xa,i));
}
usz csz = arr_csz(x);
SGet(w)
for (; i < csz; i++) r.a[i] = fc2(f, Get(w,i), xget(xa,i));
for (; i < ia; i++) r.a[i] = fc2(f, inc(r.a[i-csz]), xget(xa,i));
decG(w);
} else {
if (xr!=1) thrF("`: Shape of 𝕨 must match the cell of 𝕩 (%H ≡ ≢𝕨, %H ≡ ≢𝕩)", w, x);
if (ia==0) return x;
B pr = r.a[0] = fc2(f, w, xget(xa,0)); i++;
for (; i < ia; i++) r.a[i] = pr = fc2(f, inc(pr), xget(xa,i));
}

View File

@ -38,6 +38,10 @@ B eachd_fn(B fo, B w, B x, FC2 f) {
B rb;
if (ria==0) {
rb = rM==1? emptyHVec() : m_harrUc(bo).b;
} else if (f == arr_c2) {
MAKE_MUT(rm, ria);
mut_fill(rm, 0, fo, ria);
rb = mut_fc(rm, bo);
} else {
M_HARR(r, ria)
if (wr==xr) { SGet(x) SGet(w) for(usz ri=0; ri<ria; ri++) HARR_ADD(r, ri, f(fo, Get(w,ri), Get(x,ri))); }
@ -128,4 +132,4 @@ B arith_recd(FC2 f, B w, B x) {
popCatch();
return withFill(r, asFill(fr));
}
#endif
#endif

View File

@ -8,7 +8,7 @@ hCBQNFile ← •file.At "generated/cells_hCBQNOut.bqn"
validFile •file.At "generated/cells_valid.bqn"
cbqni {"internal"<•listsys? •BQN"•internal"; @}
bqntype {cbqni@? 2; "harr"cbqni.Type 0 ""} # 0: full CBQN; 1: heapverify CBQN; 2: bqn.js
bqntype {cbqni@? 2; ¬cbqni.HasFill +˜0<0} # 0: full CBQN; 1: heapverify CBQN; 2: bqn.js
SHRun {
f•BQN"•SH"