native ⌾(a⊸⊏)

This commit is contained in:
dzaima 2021-05-19 17:02:03 +03:00
parent c9a54b9363
commit 422c3ff823
4 changed files with 81 additions and 8 deletions

View File

@ -89,6 +89,7 @@ void gc_forceGC() {
u64 start = nsTime(); u64 start = nsTime();
gc_visitBytes = 0; gc_freedBytes = 0; gc_visitBytes = 0; gc_freedBytes = 0;
gc_visitCount = 0; gc_freedCount = 0; gc_visitCount = 0; gc_freedCount = 0;
u64 startAllocB = allocB;
#endif #endif
#ifdef ENABLE_GC #ifdef ENABLE_GC
gc_visitRoots(); gc_visitRoots();
@ -96,7 +97,7 @@ void gc_forceGC() {
gc_tagNew = gc_tagCurr; gc_tagNew = gc_tagCurr;
gc_tagCurr^= 0x80; gc_tagCurr^= 0x80;
#ifdef LOG_GC #ifdef LOG_GC
fprintf(stderr, "GC kept %ldB from %ld objects, freed %ldB from %ld objects; took %.3fms\n", gc_visitBytes, gc_visitCount, gc_freedBytes, gc_freedCount, (nsTime()-start)/1e6); fprintf(stderr, "GC kept %ldB from %ld objects, freed %ldB, including directly %ldB from %ld objects; took %.3fms\n", gc_visitBytes, gc_visitCount, startAllocB-allocB, gc_freedBytes, gc_freedCount, (nsTime()-start)/1e6);
#endif #endif
gc_lastAlloc = allocB; gc_lastAlloc = allocB;
#endif #endif

View File

@ -400,6 +400,7 @@ f64 o2fu (B x) { return x.f; }
i64 o2i64u(B x) { return (i64)x.f; } i64 o2i64u(B x) { return (i64)x.f; }
bool o2b (B x) { usz t=o2s(x); if(t!=0&t!=1)thrM("Expected boolean"); return t; } bool o2b (B x) { usz t=o2s(x); if(t!=0&t!=1)thrM("Expected boolean"); return t; }
bool q_i32(B x) { return isI32(x) | (isF64(x) && x.f==(f64)(i32)x.f); } bool q_i32(B x) { return isI32(x) | (isF64(x) && x.f==(f64)(i32)x.f); }
bool q_i64(B x) { return isI32(x) | (isF64(x) && x.f==(f64)(i64)x.f); }
bool q_f64(B x) { return isF64(x) || isI32(x); } bool q_f64(B x) { return isF64(x) || isI32(x); }

View File

@ -67,13 +67,12 @@ B mut_fcd(Mut* m, B x) { assert(m->type!=el_MAX);
u8 el_or(u8 a, u8 b) { u8 el_or(u8 a, u8 b) {
#define M(X) if(b==X) return a>X?a:X; #define M(X) if(b==X) return a>X?a:X;
switch (a) { switch (a) { default: UD;
case el_c32: M(el_c32); return el_B; case el_c32: M(el_c32); return el_B;
case el_i32: M(el_i32); M(el_f64); return el_B; case el_i32: M(el_i32); M(el_f64); return el_B;
case el_f64: M(el_i32); M(el_f64); return el_B; case el_f64: M(el_i32); M(el_f64); return el_B;
case el_B: return el_B; case el_B: return el_B;
case el_MAX: return b; case el_MAX: return b;
default: UD;
} }
#undef M #undef M
} }
@ -86,7 +85,7 @@ void mut_pfree(Mut* m, usz n) { // free the first n-1 elements
void mut_set(Mut* m, usz ms, B x) { // consumes; sets m[ms] to x void mut_set(Mut* m, usz ms, B x) { // consumes; sets m[ms] to x
again: again:
#define AGAIN(T) { mut_to(m, T); goto again; } #define AGAIN(T) { mut_to(m, T); goto again; }
switch(m->type) { switch(m->type) { default: UD;
case el_MAX: AGAIN(isF64(x)? (q_i32(x)? el_i32 : el_f64) : (isC32(x)? el_c32 : el_B)); case el_MAX: AGAIN(isF64(x)? (q_i32(x)? el_i32 : el_f64) : (isC32(x)? el_c32 : el_B));
case el_i32: { case el_i32: {
@ -111,12 +110,23 @@ void mut_set(Mut* m, usz ms, B x) { // consumes; sets m[ms] to x
} }
#undef AGAIN #undef AGAIN
} }
void mut_rm(Mut* m, usz ms) { // clears the object at position ms
if (m->type == el_B) dec(m->aB[ms]);
}
B mut_getU(Mut* m, usz ms) {
switch(m->type) { default: UD;
case el_i32: return m_i32(m->ai32[ms]);
case el_c32: return m_c32(m->ac32[ms]);
case el_f64: return m_c32(m->af64[ms]);
case el_B: return m->aB[ms];
}
}
// doesn't consume; fills m[ms…ms+l] with x // doesn't consume; fills m[ms…ms+l] with x
void mut_fill(Mut* m, usz ms, B x, usz l) { void mut_fill(Mut* m, usz ms, B x, usz l) {
again: again:
#define AGAIN(T) { mut_to(m, T); goto again; } #define AGAIN(T) { mut_to(m, T); goto again; }
switch(m->type) { switch(m->type) { default: UD;
case el_MAX: AGAIN(isF64(x)? (q_i32(x)? el_i32 : el_f64) : (isC32(x)? el_c32 : el_B)); case el_MAX: AGAIN(isF64(x)? (q_i32(x)? el_i32 : el_f64) : (isC32(x)? el_c32 : el_B));
case el_i32: { case el_i32: {
@ -160,7 +170,7 @@ void mut_copy(Mut* m, usz ms, B x, usz xs, usz l) {
again: again:
#define AGAIN { mut_to(m, el_or(m->type, xe)); goto again; } #define AGAIN { mut_to(m, el_or(m->type, xe)); goto again; }
// TODO try harder to not bump type // TODO try harder to not bump type
switch(m->type) { switch(m->type) { default: UD;
case el_MAX: AGAIN; case el_MAX: AGAIN;
case el_i32: { case el_i32: {

View File

@ -788,10 +788,10 @@ B pick_ucw(B t, B o, B w, B x) {
} }
B slash_ucw(B t, B o, B w, B x) { B slash_ucw(B t, B o, B w, B x) {
if (isAtm(w) || rnk(w)!=1 || rnk(x)!=1 || a(w)->ia!=a(x)->ia) return def_fn_ucw(t, o, w, x); if (isAtm(w) || isAtm(x) || rnk(w)!=1 || rnk(x)!=1 || a(w)->ia!=a(x)->ia) return def_fn_ucw(t, o, w, x);
usz ia = a(x)->ia; usz ia = a(x)->ia;
BS2B wgetU = TI(w).getU; BS2B wgetU = TI(w).getU;
for (usz i = 0; i < ia; i++) { B cw=wgetU(w,i); if (!q_i32(cw)) return def_fn_ucw(t, o, w, x); } if (TI(w).elType!=el_i32) for (usz i = 0; i < ia; i++) if (!q_i32(wgetU(w,i))) return def_fn_ucw(t, o, w, x);
B arg = slash_c2(t, inc(w), inc(x)); B arg = slash_c2(t, inc(w), inc(x));
usz argIA = a(arg)->ia; usz argIA = a(arg)->ia;
B rep = c1(o, arg); B rep = c1(o, arg);
@ -814,6 +814,66 @@ B slash_ucw(B t, B o, B w, B x) {
return mut_fcd(r, x); return mut_fcd(r, x);
} }
B select_ucw(B t, B o, B w, B x) {
if (isAtm(x) || rnk(x)!=1 || isAtm(w) || rnk(w)!=1) return def_fn_ucw(t, o, w, x);
usz xia = a(x)->ia;
usz wia = a(w)->ia;
BS2B wgetU = TI(w).getU;
if (TI(w).elType!=el_i32) for (usz i = 0; i < wia; i++) if (!q_i64(wgetU(w,i))) return def_fn_ucw(t, o, w, x);
B arg = select_c2(t, inc(w), inc(x));
B rep = c1(o, arg);
if (isAtm(rep) || rnk(rep)!=1 || a(rep)->ia != wia) thrF("𝔽⌾(a⊸⊏)𝕩: Result of 𝔽 must have the same shape as a⊏𝕩 (expected ⟨%s⟩, got %H)", wia, rep);
#if CHECK_VALID
bool set[xia];
for (i64 i = 0; i < xia; i++) set[i] = false;
#define EQ(F) if (set[cw] && (F)) thrM("𝔽⌾(a⊸⊏): Incompatible result elements"); set[cw] = true;
#else
#define EQ(F)
#endif
if (TI(w).elType==el_i32) {
i32* wp = i32any_ptr(w);
if (reusable(x) && TI(x).elType==TI(rep).elType) {
if (v(x)->type==t_i32arr) {
i32* xp = i32arr_ptr(x);
i32* rp = i32any_ptr(rep);
for (usz i = 0; i < wia; i++) {
i64 cw = wp[i]; if (cw<0) cw+= (i64)xia;
i32 cr = rp[i];
EQ(cr!=xp[cw]);
xp[cw] = cr;
}
dec(w); dec(rep);
return x;
} else if (v(x)->type==t_harr) {
B* xp = harr_ptr(x);
BS2B rget = TI(rep).get;
for (usz i = 0; i < wia; i++) {
i64 cw = wp[i]; if (cw<0) cw+= (i64)xia;
B cr = rget(rep, i);
EQ(!equal(cr,xp[cw]));
dec(xp[cw]);
xp[cw] = cr;
}
dec(w); dec(rep);
return x;
}
}
}
MAKE_MUT(r, xia); mut_to(r, el_or(TI(x).elType, TI(rep).elType));
mut_copy(r, 0, x, 0, xia);
BS2B rget = TI(rep).get;
for (usz i = 0; i < wia; i++) {
i64 cw = o2i64u(wgetU(w, i)); if (cw<0) cw+= (i64)xia; // oob already checked by original select_c2 call
B cr = rget(rep, i);
EQ(!equal(mut_getU(r, cw), cr));
mut_rm(r, cw);
mut_set(r, cw, cr);
}
dec(w); dec(rep);
return mut_fcd(r, x);
#undef EQ
}
#define F(A,M,D) A(shape) A(pick) A(pair) A(select) A(slash) A(join) A(couple) A(shiftb) A(shifta) A(take) A(drop) A(group) #define F(A,M,D) A(shape) A(pick) A(pair) A(select) A(slash) A(join) A(couple) A(shiftb) A(shifta) A(take) A(drop) A(group)
BI_FNS0(F); BI_FNS0(F);
@ -821,5 +881,6 @@ static inline void sfns_init() { BI_FNS1(F)
c(BFn,bi_pick)->uc1 = pick_uc1; c(BFn,bi_pick)->uc1 = pick_uc1;
c(BFn,bi_pick)->ucw = pick_ucw; c(BFn,bi_pick)->ucw = pick_ucw;
c(BFn,bi_slash)->ucw = slash_ucw; c(BFn,bi_slash)->ucw = slash_ucw;
c(BFn,bi_select)->ucw = select_ucw;
} }
#undef F #undef F