From 62a96f1196307a9e2ad7421eecc5666951d93b35 Mon Sep 17 00:00:00 2001 From: dzaima Date: Thu, 16 Sep 2021 23:20:58 +0300 Subject: [PATCH] squoze --- src/builtins/md1.c | 4 ++-- src/builtins/sfns.c | 16 ++++++++-------- src/core/fillarr.c | 6 +++--- src/core/stuff.c | 37 +++++++++++++++++++------------------ src/core/stuff.h | 6 ++++-- src/h.h | 13 ++++++++++++- src/utils/each.h | 10 +++++----- 7 files changed, 53 insertions(+), 39 deletions(-) diff --git a/src/builtins/md1.c b/src/builtins/md1.c index 36cf089b..d78b8e3a 100644 --- a/src/builtins/md1.c +++ b/src/builtins/md1.c @@ -121,7 +121,7 @@ B scan_c1(Md1D* d, B x) { B f = d->f; bool reuse = v(x)->type==t_harr && reusable(x); usz i = 0; - HArr_p r = reuse? harr_parts(x) : m_harrs(a(x)->ia, &i); + HArr_p r = reuse? harr_parts(REUSE(x)) : m_harrs(a(x)->ia, &i); AS2B xget = reuse? TI(x,getU) : TI(x,get); Arr* xa = a(x); BBB2B fc2 = c2fn(f); @@ -163,7 +163,7 @@ B scan_c2(Md1D* d, B w, B x) { B f = d->f; base:; bool reuse = (v(x)->type==t_harr && reusable(x)) | !ia; usz i = 0; - HArr_p r = reuse? harr_parts(x) : m_harrs(a(x)->ia, &i); + HArr_p r = reuse? harr_parts(REUSE(x)) : m_harrs(a(x)->ia, &i); AS2B xget = reuse? TI(x,getU) : TI(x,get); Arr* xa = a(x); BBB2B fc2 = c2fn(f); diff --git a/src/builtins/sfns.c b/src/builtins/sfns.c index 304d71a9..d6cb3373 100644 --- a/src/builtins/sfns.c +++ b/src/builtins/sfns.c @@ -46,7 +46,7 @@ B shape_c1(B t, B x) { dec(x); return unitV1(n); } - if (reusable(x)) { + if (reusable(x)) { FL_KEEP(x, fl_squoze); decSh(v(x)); arr_shVec(a(x)); return x; } @@ -138,7 +138,7 @@ B shape_c2(B t, B w, B x) { } else { if (nia <= xia) { B r; Arr* ra; - if (reusable(x) && xia==nia) { r = x; decSh(v(x)); ra = (Arr*)v(r); } + if (reusable(x) && xia==nia) { r = REUSE(x); decSh(v(x)); ra = (Arr*)v(r); } else { ra = TI(x,slice)(x, 0, nia); r = taga(ra); } arr_shSetU(ra, nr, sh); return r; @@ -926,7 +926,7 @@ B pick_ucw(B t, B o, B w, B x) { B xf = getFillQ(x); B arg = IGet(x, wi); B rep = c1(o, arg); - if (reusable(x) && TI(x,canStore)(rep)) { + if (reusable(x) && TI(x,canStore)(rep)) { REUSE(x); if (TI(x,elType)==el_i8 ) { i8* xp = i8any_ptr (x); xp[wi] = o2iu(rep); return x; } else if (TI(x,elType)==el_i16) { i16* xp = i16any_ptr(x); xp[wi] = o2iu(rep); return x; } else if (TI(x,elType)==el_i32) { i32* xp = i32any_ptr(x); xp[wi] = o2iu(rep); return x; } @@ -1004,9 +1004,9 @@ B select_ucw(B t, B o, B w, B x) { i32* wp = i32any_ptr(w); if (rere?xe:re; - bool re = reusable(x); + bool reuse = reusable(x); if (me==el_i32) { - I32Arr* xn = re? toI32Arr(x) : cpyI32Arr(x); + I32Arr* xn = reuse? toI32Arr(REUSE(x)) : cpyI32Arr(x); rep = toI32Any(rep); i32* rp = i32any_ptr(rep); for (usz i = 0; i < wia; i++) { i64 cw = wp[i]; if (RARE(cw<0)) cw+= (i64)xia; // we're free to assume w is valid @@ -1016,7 +1016,7 @@ B select_ucw(B t, B o, B w, B x) { } dec(w); dec(rep); FREE_CHECK; return taga(xn); } else if (me==el_i16) { - I16Arr* xn = re? toI16Arr(x) : cpyI16Arr(x); + I16Arr* xn = reuse? toI16Arr(REUSE(x)) : cpyI16Arr(x); rep = toI16Any(rep); i16* rp = i16any_ptr(rep); for (usz i = 0; i < wia; i++) { i64 cw = wp[i]; if (RARE(cw<0)) cw+= (i64)xia; @@ -1026,7 +1026,7 @@ B select_ucw(B t, B o, B w, B x) { } dec(w); dec(rep); FREE_CHECK; return taga(xn); } else if (me==el_i8) { - I8Arr* xn = re? toI8Arr(x) : cpyI8Arr(x); + I8Arr* xn = reuse? toI8Arr(REUSE(x)) : cpyI8Arr(x); rep = toI8Any(rep); i8* rp = i8any_ptr(rep); for (usz i = 0; i < wia; i++) { i64 cw = wp[i]; if (RARE(cw<0)) cw+= (i64)xia; @@ -1039,7 +1039,7 @@ B select_ucw(B t, B o, B w, B x) { } if (reusable(x) && xe==re) { if (v(x)->type==t_harr) { - B* xp = harr_ptr(x); + B* xp = harr_ptr(REUSE(x)); SGet(rep) for (usz i = 0; i < wia; i++) { i64 cw = wp[i]; if (RARE(cw<0)) cw+= (i64)xia; diff --git a/src/core/fillarr.c b/src/core/fillarr.c index 08dea22e..407a2b91 100644 --- a/src/core/fillarr.c +++ b/src/core/fillarr.c @@ -115,7 +115,7 @@ B withFill(B x, B fill) { // consumes both case t_c32arr: case t_c32slice: case t_c16arr: case t_c16slice: case t_c8arr: case t_c8slice: if(fill.u == m_c32(' ').u) return x; break; case t_fillslice: if (fillEqual(((FillArr*)c(Slice,x)->p)->fill, fill)) { dec(fill); return x; } break; case t_fillarr: if (fillEqual(c(FillArr,x)->fill, fill)) { dec(fill); return x; } - if (reusable(x)) { + if (reusable(x)) { // keeping flags is fine probably dec(c(FillArr, x)->fill); c(FillArr, x)->fill = fill; return x; @@ -124,10 +124,10 @@ B withFill(B x, B fill) { // consumes both } usz ia = a(x)->ia; if (isNum(fill)) { - x = num_squeeze(x); + x = num_squeezeChk(x); if (elNum(TI(x,elType))) return x; } else if (isC32(fill)) { - x = chr_squeeze(x); + x = chr_squeezeChk(x); if (elChr(TI(x,elType))) return x; } FillArr* r = m_arr(fsizeof(FillArr,a,B,ia), t_fillarr, ia); diff --git a/src/core/stuff.c b/src/core/stuff.c index a1e6a35d..89def0eb 100644 --- a/src/core/stuff.c +++ b/src/core/stuff.c @@ -200,7 +200,7 @@ NOINLINE B do_fmt(B s, char* p, va_list a) { AFMT("%f", o2f(b)); } else { assert(isArr(b) && rnk(b)==1); if (TI(b,elType)==el_c32) AJOIN(inc(b)); - else AJOIN(chr_squeeze(inc(b))); + else AJOIN(chr_squeezeChk(inc(b))); } break; } @@ -481,7 +481,7 @@ B num_squeeze(B x) { u8 xe = TI(x,elType); assert(xe!=el_bit); - if (xe==el_i8) return x; + if (xe==el_i8) goto r_x; // TODO fast paths for xeia; u8 xe = TI(x,elType); - if (xe==el_c8) return x; + if (xe==el_c8) goto r_x; // TODO fast paths for xe == el_c8/el_c16/el_c32 usz i = 0; i32 or = 0; @@ -540,27 +541,27 @@ B chr_squeeze(B x) { B* xp = arr_bptr(x); if (xp!=NULL) { for (; i < ia; i++) { - if (!isC32(xp[i])) return x; + if (!isC32(xp[i])) goto r_x; or|= o2cu(xp[i]); } } else { SGetU(x) for (; i < ia; i++) { B cr = GetU(x,i); - if (!isC32(cr)) return x; + if (!isC32(cr)) goto r_x; or|= o2cu(cr); } } - if (or<=U8_MAX ) return toC8Any(x); - else if (or<=U16_MAX) return toC16Any(x); - else return toC32Any(x); + if (or<=U8_MAX ) return FL_SET(toC8Any(x), fl_squoze); + else if (or<=U16_MAX) return FL_SET(toC16Any(x), fl_squoze); + else return FL_SET(toC32Any(x), fl_squoze); + r_x: return FL_SET(x, fl_squoze); } B any_squeeze(B x) { assert(isArr(x)); - u8 xe = TI(x,elType); - assert(xe!=el_bit); - if (a(x)->ia==0) return x; + if (FL_HAS(x,fl_squoze)) return x; + if (a(x)->ia==0) return FL_SET(x, fl_squoze); SGetU(x) B x0 = GetU(x, 0); if (isNum(x0)) return num_squeeze(x); diff --git a/src/core/stuff.h b/src/core/stuff.h index 3dc6e13e..fdf05b99 100644 --- a/src/core/stuff.h +++ b/src/core/stuff.h @@ -138,8 +138,10 @@ char* format_pm2(u8 u); bool isPureFn(B x); // doesn't consume B bqn_merge(B x); // consumes B any_squeeze(B x); // consumes; accepts any array, returns one with the smallest type (doesn't recurse!) -B num_squeeze(B x); // consumes; -B chr_squeeze(B x); // consumes +B num_squeeze(B x); // consumes; accepts any array, but only tries to squeeze numerical values; doesn't check for fl_squoze +B chr_squeeze(B x); // consumes; accepts any array, but only tries to squeeze character values; doesn't check for fl_squoze +static inline B num_squeezeChk(B x) { return FL_HAS(x,fl_squoze)? x : num_squeeze(x); } +static inline B chr_squeezeChk(B x) { return FL_HAS(x,fl_squoze)? x : chr_squeeze(x); } B def_fn_uc1(B t, B o, B x); B def_fn_ucw(B t, B o, B w, B x); B def_m1_uc1(B t, B o, B f, B x); diff --git a/src/h.h b/src/h.h index 3b570b20..54108bfb 100644 --- a/src/h.h +++ b/src/h.h @@ -440,8 +440,19 @@ typedef B (*M2C2)(Md2D*, B, B); #define IGet(X,N)({ Arr* x_ = a(X); TIv(x_,get)(x_,N); }) #define Get(X,N) X##_get(X##_arr,N) -// refcount + +enum Flags { + fl_squoze=1, + fl_asc=2, // sorted ascending (non-descending) + fl_dsc=4, // sorted descending (non-ascending) +}; +#define FL_SET(X,F) ({ B x_ = (X); v(x_)->flags|= (F); x_; }) +#define FL_KEEP(X,F) v(X)->flags&= (F) +#define FL_HAS(X,F) ((v(X)->flags&(F)) != 0) + +// refcount stuff static bool reusable(B x) { return v(x)->refc==1; } +#define REUSE(X) ({ B x_ = (X); v(x_)->flags = 0; x_; }) #define DEF_FREE(TY) static inline void TY##_freeO(Value* x); static void TY##_freeF(Value* x) { TY##_freeO(x); mm_free(x); } static inline void TY##_freeO(Value* x) static inline void value_free(Value* x) { // TIv(x,freeO)(x); mm_free(x); diff --git a/src/utils/each.h b/src/utils/each.h index 16ba0cb5..16de2637 100644 --- a/src/utils/each.h +++ b/src/utils/each.h @@ -21,7 +21,7 @@ static B eachd_fn(BBB2B f, B fo, B w, B x) { // consumes w,x; assumes at least o bool rw = rM==wr && ((v(w)->type==t_harr) & reusable(w)); // v(…) is safe as rank>0 bool rx = rM==xr && ((v(x)->type==t_harr) & reusable(x)); if (rw|rx && (wr==xr | rm==0)) { - HArr_p r = harr_parts(rw? w : x); + HArr_p r = harr_parts(REUSE(rw? w : x)); usz ria = r.c->ia; if (wr==0) { B c=Get(w, 0); for(usz i = 0; i < ria; i++) r.a[i] = f(fo, inc(c), hmv(r,i)); dec(c); } else if (xr==0) { B c=Get(x, 0); for(usz i = 0; i < ria; i++) r.a[i] = f(fo, hmv(r,i), inc(c) ); dec(c); } @@ -66,7 +66,7 @@ static B eachm_fn(BB2B f, B fo, B x) { // consumes x; x must be array if (reuse) { dec(xp[i]); xp[i++] = cr; for (; i < ia; i++) xp[i] = f(fo, mv(xp,i)); - return x; + return REUSE(x); } else { rH = m_harrs(ia, &i); rH.a[i++] = cr; @@ -76,7 +76,7 @@ static B eachm_fn(BB2B f, B fo, B x) { // consumes x; x must be array } else if (TI(x,elType)==el_i32) { i32* xp = i32any_ptr(x); B r; i32* rp; - if (reuse && v(x)->type==t_i32arr) { r=inc(x); rp = xp; } + if (reuse && v(x)->type==t_i32arr) { r=inc(REUSE(x)); rp = xp; } else r = m_i32arrc(&rp, x); rp[i++] = o2iu(cr); for (; i < ia; i++) { @@ -94,7 +94,7 @@ static B eachm_fn(BB2B f, B fo, B x) { // consumes x; x must be array } else if (TI(x,elType)==el_f64) { f64* xp = f64any_ptr(x); B r; f64* rp; - if (reuse && v(x)->type==t_f64arr) { r=inc(x); rp = xp; } + if (reuse && v(x)->type==t_f64arr) { r=inc(REUSE(x)); rp = xp; } else r = m_f64arrc(&rp, x); rp[i++] = o2fu(cr); for (; i < ia; i++) { @@ -116,7 +116,7 @@ static B eachm_fn(BB2B f, B fo, B x) { // consumes x; x must be array c(FillArr,x)->fill = bi_noFill; dec(xp[i]); xp[i++] = cr; for (; i < ia; i++) xp[i] = f(fo, mv(xp,i)); - return x; + return REUSE(x); } else { HArr_p rp = m_harrs(ia, &i); rp.a[i++] = cr;