This commit is contained in:
dzaima 2021-09-16 23:20:58 +03:00
parent 427d508324
commit 62a96f1196
7 changed files with 53 additions and 39 deletions

View File

@ -121,7 +121,7 @@ B scan_c1(Md1D* d, B x) { B f = d->f;
bool reuse = v(x)->type==t_harr && reusable(x); bool reuse = v(x)->type==t_harr && reusable(x);
usz i = 0; 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); AS2B xget = reuse? TI(x,getU) : TI(x,get); Arr* xa = a(x);
BBB2B fc2 = c2fn(f); BBB2B fc2 = c2fn(f);
@ -163,7 +163,7 @@ B scan_c2(Md1D* d, B w, B x) { B f = d->f;
base:; base:;
bool reuse = (v(x)->type==t_harr && reusable(x)) | !ia; bool reuse = (v(x)->type==t_harr && reusable(x)) | !ia;
usz i = 0; 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); AS2B xget = reuse? TI(x,getU) : TI(x,get); Arr* xa = a(x);
BBB2B fc2 = c2fn(f); BBB2B fc2 = c2fn(f);

View File

@ -46,7 +46,7 @@ B shape_c1(B t, B x) {
dec(x); dec(x);
return unitV1(n); return unitV1(n);
} }
if (reusable(x)) { if (reusable(x)) { FL_KEEP(x, fl_squoze);
decSh(v(x)); arr_shVec(a(x)); decSh(v(x)); arr_shVec(a(x));
return x; return x;
} }
@ -138,7 +138,7 @@ B shape_c2(B t, B w, B x) {
} else { } else {
if (nia <= xia) { if (nia <= xia) {
B r; Arr* ra; 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); } else { ra = TI(x,slice)(x, 0, nia); r = taga(ra); }
arr_shSetU(ra, nr, sh); arr_shSetU(ra, nr, sh);
return r; return r;
@ -926,7 +926,7 @@ B pick_ucw(B t, B o, B w, B x) {
B xf = getFillQ(x); B xf = getFillQ(x);
B arg = IGet(x, wi); B arg = IGet(x, wi);
B rep = c1(o, arg); 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; } 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_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; } 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); i32* wp = i32any_ptr(w);
if (re<el_f64 && xe<el_f64) { if (re<el_f64 && xe<el_f64) {
u8 me = xe>re?xe:re; u8 me = xe>re?xe:re;
bool re = reusable(x); bool reuse = reusable(x);
if (me==el_i32) { 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); rep = toI32Any(rep); i32* rp = i32any_ptr(rep);
for (usz i = 0; i < wia; i++) { 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 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); dec(w); dec(rep); FREE_CHECK; return taga(xn);
} else if (me==el_i16) { } 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); rep = toI16Any(rep); i16* rp = i16any_ptr(rep);
for (usz i = 0; i < wia; i++) { for (usz i = 0; i < wia; i++) {
i64 cw = wp[i]; if (RARE(cw<0)) cw+= (i64)xia; 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); dec(w); dec(rep); FREE_CHECK; return taga(xn);
} else if (me==el_i8) { } 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); rep = toI8Any(rep); i8* rp = i8any_ptr(rep);
for (usz i = 0; i < wia; i++) { for (usz i = 0; i < wia; i++) {
i64 cw = wp[i]; if (RARE(cw<0)) cw+= (i64)xia; 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 (reusable(x) && xe==re) {
if (v(x)->type==t_harr) { if (v(x)->type==t_harr) {
B* xp = harr_ptr(x); B* xp = harr_ptr(REUSE(x));
SGet(rep) SGet(rep)
for (usz i = 0; i < wia; i++) { for (usz i = 0; i < wia; i++) {
i64 cw = wp[i]; if (RARE(cw<0)) cw+= (i64)xia; i64 cw = wp[i]; if (RARE(cw<0)) cw+= (i64)xia;

View File

@ -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_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_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; } 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); dec(c(FillArr, x)->fill);
c(FillArr, x)->fill = fill; c(FillArr, x)->fill = fill;
return x; return x;
@ -124,10 +124,10 @@ B withFill(B x, B fill) { // consumes both
} }
usz ia = a(x)->ia; usz ia = a(x)->ia;
if (isNum(fill)) { if (isNum(fill)) {
x = num_squeeze(x); x = num_squeezeChk(x);
if (elNum(TI(x,elType))) return x; if (elNum(TI(x,elType))) return x;
} else if (isC32(fill)) { } else if (isC32(fill)) {
x = chr_squeeze(x); x = chr_squeezeChk(x);
if (elChr(TI(x,elType))) return x; if (elChr(TI(x,elType))) return x;
} }
FillArr* r = m_arr(fsizeof(FillArr,a,B,ia), t_fillarr, ia); FillArr* r = m_arr(fsizeof(FillArr,a,B,ia), t_fillarr, ia);

View File

@ -200,7 +200,7 @@ NOINLINE B do_fmt(B s, char* p, va_list a) {
AFMT("%f", o2f(b)); AFMT("%f", o2f(b));
} else { assert(isArr(b) && rnk(b)==1); } else { assert(isArr(b) && rnk(b)==1);
if (TI(b,elType)==el_c32) AJOIN(inc(b)); if (TI(b,elType)==el_c32) AJOIN(inc(b));
else AJOIN(chr_squeeze(inc(b))); else AJOIN(chr_squeezeChk(inc(b)));
} }
break; break;
} }
@ -481,7 +481,7 @@ B num_squeeze(B x) {
u8 xe = TI(x,elType); u8 xe = TI(x,elType);
assert(xe!=el_bit); assert(xe!=el_bit);
if (xe==el_i8) return x; if (xe==el_i8) goto r_x;
// TODO fast paths for xe<el_f64 // TODO fast paths for xe<el_f64
usz i = 0; usz i = 0;
i32 or = 0; // using bitwise or as a heuristical ⌈´|𝕩 i32 or = 0; // using bitwise or as a heuristical ⌈´|𝕩
@ -490,7 +490,7 @@ B num_squeeze(B x) {
for (; i < ia; i++) { for (; i < ia; i++) {
f64 cf = xp[i]; f64 cf = xp[i];
i32 c = (i32)cf; i32 c = (i32)cf;
if (c!=cf) return x; // already f64 if (c!=cf) goto r_x; // already f64
or|= c<0?-c:c; or|= c<0?-c:c;
} }
goto r_or; goto r_or;
@ -500,7 +500,7 @@ B num_squeeze(B x) {
if (xp!=NULL) { if (xp!=NULL) {
for (; i < ia; i++) { for (; i < ia; i++) {
if (RARE(!q_i32(xp[i]))) { if (RARE(!q_i32(xp[i]))) {
while (i<ia) if (!isF64(xp[i++])) return x; while (i<ia) if (!isF64(xp[i++])) goto r_x;
goto r_f64; goto r_f64;
} }
i32 c = o2iu(xp[i]); i32 c = o2iu(xp[i]);
@ -513,7 +513,7 @@ B num_squeeze(B x) {
for (; i < ia; i++) { for (; i < ia; i++) {
B cr = GetU(x,i); B cr = GetU(x,i);
if (RARE(!q_i32(cr))) { if (RARE(!q_i32(cr))) {
while (i<ia) if (!isF64(GetU(x,i++))) return x; while (i<ia) if (!isF64(GetU(x,i++))) goto r_x;
goto r_f64; goto r_f64;
} }
i32 c = o2iu(cr); i32 c = o2iu(cr);
@ -524,15 +524,16 @@ B num_squeeze(B x) {
else if (or<=I16_MAX) goto r_i16; else if (or<=I16_MAX) goto r_i16;
else goto r_i32; else goto r_i32;
r_i8 : return toI8Any(x); r_x : return FL_SET(x, fl_squoze);
r_i16: return toI16Any(x); r_i8 : return FL_SET(toI8Any (x), fl_squoze);
r_i32: return toI32Any(x); r_i16: return FL_SET(toI16Any(x), fl_squoze);
r_f64: return toF64Any(x); r_i32: return FL_SET(toI32Any(x), fl_squoze);
r_f64: return FL_SET(toF64Any(x), fl_squoze);
} }
B chr_squeeze(B x) { B chr_squeeze(B x) {
usz ia = a(x)->ia; usz ia = a(x)->ia;
u8 xe = TI(x,elType); 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 // TODO fast paths for xe == el_c8/el_c16/el_c32
usz i = 0; usz i = 0;
i32 or = 0; i32 or = 0;
@ -540,27 +541,27 @@ B chr_squeeze(B x) {
B* xp = arr_bptr(x); B* xp = arr_bptr(x);
if (xp!=NULL) { if (xp!=NULL) {
for (; i < ia; i++) { for (; i < ia; i++) {
if (!isC32(xp[i])) return x; if (!isC32(xp[i])) goto r_x;
or|= o2cu(xp[i]); or|= o2cu(xp[i]);
} }
} else { } else {
SGetU(x) SGetU(x)
for (; i < ia; i++) { for (; i < ia; i++) {
B cr = GetU(x,i); B cr = GetU(x,i);
if (!isC32(cr)) return x; if (!isC32(cr)) goto r_x;
or|= o2cu(cr); or|= o2cu(cr);
} }
} }
if (or<=U8_MAX ) return toC8Any(x); if (or<=U8_MAX ) return FL_SET(toC8Any(x), fl_squoze);
else if (or<=U16_MAX) return toC16Any(x); else if (or<=U16_MAX) return FL_SET(toC16Any(x), fl_squoze);
else return toC32Any(x); else return FL_SET(toC32Any(x), fl_squoze);
r_x: return FL_SET(x, fl_squoze);
} }
B any_squeeze(B x) { B any_squeeze(B x) {
assert(isArr(x)); assert(isArr(x));
u8 xe = TI(x,elType); if (FL_HAS(x,fl_squoze)) return x;
assert(xe!=el_bit); if (a(x)->ia==0) return FL_SET(x, fl_squoze);
if (a(x)->ia==0) return x;
SGetU(x) SGetU(x)
B x0 = GetU(x, 0); B x0 = GetU(x, 0);
if (isNum(x0)) return num_squeeze(x); if (isNum(x0)) return num_squeeze(x);

View File

@ -138,8 +138,10 @@ char* format_pm2(u8 u);
bool isPureFn(B x); // doesn't consume bool isPureFn(B x); // doesn't consume
B bqn_merge(B x); // consumes 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 any_squeeze(B x); // consumes; accepts any array, returns one with the smallest type (doesn't recurse!)
B num_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 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_uc1(B t, B o, B x);
B def_fn_ucw(B t, B o, B w, 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); B def_m1_uc1(B t, B o, B f, B x);

13
src/h.h
View File

@ -440,8 +440,19 @@ typedef B (*M2C2)(Md2D*, B, B);
#define IGet(X,N)({ Arr* x_ = a(X); TIv(x_,get)(x_,N); }) #define IGet(X,N)({ Arr* x_ = a(X); TIv(x_,get)(x_,N); })
#define Get(X,N) X##_get(X##_arr,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; } 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) #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) { static inline void value_free(Value* x) {
// TIv(x,freeO)(x); mm_free(x); // TIv(x,freeO)(x); mm_free(x);

View File

@ -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 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)); bool rx = rM==xr && ((v(x)->type==t_harr) & reusable(x));
if (rw|rx && (wr==xr | rm==0)) { 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; 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); } 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); } 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) { if (reuse) {
dec(xp[i]); xp[i++] = cr; dec(xp[i]); xp[i++] = cr;
for (; i < ia; i++) xp[i] = f(fo, mv(xp,i)); for (; i < ia; i++) xp[i] = f(fo, mv(xp,i));
return x; return REUSE(x);
} else { } else {
rH = m_harrs(ia, &i); rH = m_harrs(ia, &i);
rH.a[i++] = cr; 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) { } else if (TI(x,elType)==el_i32) {
i32* xp = i32any_ptr(x); i32* xp = i32any_ptr(x);
B r; i32* rp; 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); else r = m_i32arrc(&rp, x);
rp[i++] = o2iu(cr); rp[i++] = o2iu(cr);
for (; i < ia; i++) { 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) { } else if (TI(x,elType)==el_f64) {
f64* xp = f64any_ptr(x); f64* xp = f64any_ptr(x);
B r; f64* rp; 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); else r = m_f64arrc(&rp, x);
rp[i++] = o2fu(cr); rp[i++] = o2fu(cr);
for (; i < ia; i++) { 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; c(FillArr,x)->fill = bi_noFill;
dec(xp[i]); xp[i++] = cr; dec(xp[i]); xp[i++] = cr;
for (; i < ia; i++) xp[i] = f(fo, mv(xp,i)); for (; i < ia; i++) xp[i] = f(fo, mv(xp,i));
return x; return REUSE(x);
} else { } else {
HArr_p rp = m_harrs(ia, &i); HArr_p rp = m_harrs(ia, &i);
rp.a[i++] = cr; rp.a[i++] = cr;