From 422c3ff823f44a97374cac31b2a97966df0d2280 Mon Sep 17 00:00:00 2001 From: dzaima Date: Wed, 19 May 2021 17:02:03 +0300 Subject: [PATCH] =?UTF-8?q?native=20=E2=8C=BE(a=E2=8A=B8=E2=8A=8F)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/gc.c | 3 ++- src/h.h | 1 + src/mut.c | 20 ++++++++++++----- src/sfns.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 81 insertions(+), 8 deletions(-) diff --git a/src/gc.c b/src/gc.c index a426821b..e7988aea 100644 --- a/src/gc.c +++ b/src/gc.c @@ -89,6 +89,7 @@ void gc_forceGC() { u64 start = nsTime(); gc_visitBytes = 0; gc_freedBytes = 0; gc_visitCount = 0; gc_freedCount = 0; + u64 startAllocB = allocB; #endif #ifdef ENABLE_GC gc_visitRoots(); @@ -96,7 +97,7 @@ void gc_forceGC() { gc_tagNew = gc_tagCurr; gc_tagCurr^= 0x80; #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 gc_lastAlloc = allocB; #endif diff --git a/src/h.h b/src/h.h index 25bfa3ef..5a0f541d 100644 --- a/src/h.h +++ b/src/h.h @@ -400,6 +400,7 @@ f64 o2fu (B x) { return 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 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); } diff --git a/src/mut.c b/src/mut.c index b12c4f80..a40c0697 100644 --- a/src/mut.c +++ b/src/mut.c @@ -67,13 +67,12 @@ B mut_fcd(Mut* m, B x) { assert(m->type!=el_MAX); u8 el_or(u8 a, u8 b) { #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_i32: 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_MAX: return b; - default: UD; } #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 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_i32: { @@ -111,12 +110,23 @@ void mut_set(Mut* m, usz ms, B x) { // consumes; sets m[ms] to x } #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 void mut_fill(Mut* m, usz ms, B x, usz l) { 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_i32: { @@ -160,7 +170,7 @@ void mut_copy(Mut* m, usz ms, B x, usz xs, usz l) { again: #define AGAIN { mut_to(m, el_or(m->type, xe)); goto again; } // TODO try harder to not bump type - switch(m->type) { + switch(m->type) { default: UD; case el_MAX: AGAIN; case el_i32: { diff --git a/src/sfns.c b/src/sfns.c index 37eddfdf..d29ab0b6 100644 --- a/src/sfns.c +++ b/src/sfns.c @@ -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) { - 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; 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)); usz argIA = a(arg)->ia; 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); } +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) 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)->ucw = pick_ucw; c(BFn,bi_slash)->ucw = slash_ucw; + c(BFn,bi_select)->ucw = select_ucw; } #undef F