From 4783812eaf75108ccf52738b1f88dbb44fad238f Mon Sep 17 00:00:00 2001 From: dzaima Date: Thu, 29 Apr 2021 23:41:16 +0300 Subject: [PATCH] mut --- src/fillarr.c | 6 ++- src/h.h | 28 +++++++++---- src/i32arr.c | 1 + src/main.c | 1 + src/mut.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/sfns.c | 38 +++++++++--------- src/stuff.c | 9 ++++- 7 files changed, 163 insertions(+), 28 deletions(-) create mode 100644 src/mut.c diff --git a/src/fillarr.c b/src/fillarr.c index 25b82bf8..505afbc3 100644 --- a/src/fillarr.c +++ b/src/fillarr.c @@ -29,6 +29,7 @@ B getFill(B x) { // consumes; can return bi_noFill if (t==t_fillslice) { B r = inc(c(FillArr,c(Slice,x)->p)->fill); dec(x); return r; } if (t==t_c32arr || t==t_c32slice) { dec(x); return m_c32(' '); } if (t==t_i32arr || t==t_i32slice) { dec(x); return m_f64(0 ); } + if (t==t_f64arr || t==t_f64slice) { dec(x); return m_f64(0 ); } dec(x); return bi_noFill; } @@ -118,8 +119,9 @@ B withFill(B x, B fill) { // consumes both #endif if (noFill(fill) && v(x)->type!=t_fillarr && v(x)->type!=t_fillslice) return x; switch(v(x)->type) { - case t_i32arr : case t_i32slice : if(fill.u == m_i32(0 ).u) return x; break; - case t_c32arr : case t_c32slice : if(fill.u == m_c32(' ').u) return x; break; + case t_f64arr : case t_f64slice: + case t_i32arr : case t_i32slice: if(fill.u == m_i32(0 ).u) return x; break; + case t_c32arr : case t_c32slice: if(fill.u == m_c32(' ').u) return x; break; case t_fillslice: if (equal(c(FillArr,c(Slice,x)->p)->fill, fill)) { dec(fill); return x; } break; case t_fillarr: if (equal(c(FillArr,x)->fill, fill)) { dec(fill); return x; } if (reusable(x)) { diff --git a/src/h.h b/src/h.h index d22f3968..3a19c4fe 100644 --- a/src/h.h +++ b/src/h.h @@ -72,6 +72,15 @@ enum Type { #endif t_COUNT }; + +enum ElType { // a⌈b shall return the type that can store both, if possible + el_i32=0, + el_f64=1, + el_c32=2, + el_B =3, + el_MAX=4 // also used for incomplete in mut.c +}; + char* format_type(u8 u) { switch(u) { default: return"(unknown type)"; case t_empty:return"empty"; case t_shape:return"shape"; @@ -204,6 +213,7 @@ void printRaw(B x); // doesn't consume void print(B x); // doesn't consume bool equal(B w, B x); // doesn't consume void arr_print(B x); // doesn't consume +u8 fillElType(B x); // doesn't consume bool eqShape(B w, B x); // doesn't consume usz arr_csz(B x); // doesn't consume bool eqShPrefix(usz* w, usz* x, ur len); @@ -228,12 +238,14 @@ B catchMessage; -#define c(T,x) ((T*)((x).u&0xFFFFFFFFFFFFull)) -#define v(x) c(Value, x) -#define a(x) c(Arr , x) -#define rnk(x ) (v(x)->extra) // expects argument to be Arr -#define srnk(x,r) (v(x)->extra=(r)) -#define VT(x,t) assert(isVal(x) && v(x)->type==t) +#define c(T,X) ((T*)((X).u&0xFFFFFFFFFFFFull)) +#define v(X) c(Value, X) +#define a(X) c(Arr , X) +#define prnk(X ) (X->extra) +#define sprnk(X,R) (X->extra=(R)) +#define rnk(X ) prnk(v(X)) +#define srnk(X,R) sprnk(v(X),R) +#define VT(X,T) assert(isVal(X) && v(X)->type==(T)) void print_vmStack(); #ifdef DEBUG @@ -358,9 +370,11 @@ typedef struct TypeInfo { BB2B m1_d; // consume all args; (m, f) BBB2B m2_d; // consume all args; (m, f, g) BS2B slice; // consumes; create slice from given starting position; add ia, rank, shape yourself; may not actually be a Slice object - B2b canStore; // doesn't consume B2B identity; // return identity element of this function; doesn't consume + B2b canStore; // doesn't consume + u8 elType; + B2v print; // doesn't consume B2v visit; // call mm_visit for all referents B2B decompose; // consumes; must return a HArr diff --git a/src/i32arr.c b/src/i32arr.c index 31152201..61364c12 100644 --- a/src/i32arr.c +++ b/src/i32arr.c @@ -74,5 +74,6 @@ static inline void i32arr_init() { ti[t_i32arr].print = arr_print; ti[t_i32slice].print = arr_print; ti[t_i32arr].isArr = true; ti[t_i32slice].isArr = true; ti[t_i32arr].arrD1 = true; ti[t_i32slice].arrD1 = true; + ti[t_i32arr].elType = el_i32; ti[t_i32slice].elType = el_i32; ti[t_i32arr].canStore = i32arr_canStore; } diff --git a/src/main.c b/src/main.c index 82ea6e12..1871fb85 100644 --- a/src/main.c +++ b/src/main.c @@ -28,6 +28,7 @@ #include "i32arr.c" #include "c32arr.c" #include "f64arr.c" +#include "mut.c" #include "utf.c" #include "derv.c" #include "fns.c" diff --git a/src/mut.c b/src/mut.c new file mode 100644 index 00000000..8ad6b684 --- /dev/null +++ b/src/mut.c @@ -0,0 +1,108 @@ +typedef struct Mut { + u8 type; + usz ia; + Arr* val; +} Mut; +#define MAKE_MUT(N, IA) Mut N##_val; N##_val.type = el_MAX; N##_val.ia = (IA); Mut* N = &N##_val; + +void mut_to(Mut* m, u8 n) { + u8 o = m->type; + m->type = n; + if (o==el_MAX) { + switch(n) { default: UD; + case el_i32: m->val = a(m_i32arrp(m->ia)) ; return; + case el_f64: m->val = a(m_f64arrp(m->ia)) ; return; + case el_c32: m->val = a(m_c32arrp(m->ia)) ; return; + case el_B : m->val = (Arr*)m_harrUp(m->ia).c; return; + } + } else { + sprnk(m->val, 1); + m->val->sh = &m->val->ia; + switch(n) { default: UD; + case el_i32: m->val = (Arr*)toI32Arr(tag(m->val, ARR_TAG)); return; + case el_f64: m->val = (Arr*)toF64Arr(tag(m->val, ARR_TAG)); return; + case el_c32: m->val = (Arr*)toC32Arr(tag(m->val, ARR_TAG)); return; + case el_B : m->val = (Arr*)toHArr (tag(m->val, ARR_TAG)); return; + } + } +} + +B mut_fv(Mut* m) { + assert(m->type!=el_MAX); + m->val->sh = &m->val->ia; + B r = tag(m->val, ARR_TAG); + srnk(r, 1); + return r; +} +B mut_fp(Mut* m) { + assert(m->type!=el_MAX); + return tag(m->val, ARR_TAG); +} + +u8 el_or(u8 a, u8 b) { + #define M(X) if(b==X) return b>X?b:X; + switch (a) { + 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 +} + +// expects x to be an array, each position must be written to precisely once +// doesn't consume x +void mut_copy(Mut* m, usz ms, B x, usz xs, usz l) { + assert(isArr(x)); + u8 xt = v(x)->type; + u8 xe = ti[xt].elType; + // printf("mut_%d[%d…%d] ← %s[%d…%d]\n", m->type, ms, ms+l, format_type(xt), xs, xs+l); fflush(stdout); + again: + #define AGAIN { mut_to(m, el_or(m->type, xe)); goto again; } + // TODO try harder to not bump type + switch(m->type) { + case el_MAX: AGAIN; + + case el_i32: { + i32* xp; + if (xt==t_i32arr) xp = i32arr_ptr(x); + else if (xt==t_i32slice) xp = c(I32Slice,x)->a; + else AGAIN; + memcpy(((I32Arr*)m->val)->a+ms, xp+xs, l*4); + return; + } + case el_c32: { + u32* xp; + if (xt==t_c32arr) xp = c32arr_ptr(x); + else if (xt==t_c32slice) xp = c(C32Slice,x)->a; + else AGAIN; + memcpy(((C32Arr*)m->val)->a+ms, xp+xs, l*4); + return; + } + case el_f64: { + f64* xp; + if (xt==t_f64arr) xp = f64arr_ptr(x); + else if (xt==t_f64slice) xp = c(F64Slice,x)->a; + else AGAIN; + memcpy(((F64Arr*)m->val)->a+ms, xp+xs, l*8); + return; + } + case el_B: { + B* mpo = ((HArr*)m->val)->a+ms; + B* xp; + if (xt==t_harr) xp = harr_ptr(x); + else if (xt==t_hslice) xp = c(HSlice,x)->a; + else { + BS2B xget = ti[xt].get; + for (usz i = 0; i < l; i++) mpo[i] = xget(x,i+xs); + return; + } + memcpy(mpo, xp+xs, l*sizeof(B*)); + for (usz i = 0; i < l; i++) inc(mpo[i]); + return; + } + } + #undef AGAIN +} \ No newline at end of file diff --git a/src/sfns.c b/src/sfns.c index d4fb34e3..81bf009e 100644 --- a/src/sfns.c +++ b/src/sfns.c @@ -245,23 +245,24 @@ B select_c2(B t, B w, B x) { if (rr>UR_MAX) thrM("⊏: Result rank too large"); usz csz = arr_csz(x); usz cam = a(x)->sh[0]; - usz ria = wia*csz; - HArr_p r = m_harrUp(ria); - usz* rsh = arr_shAllocR(r.b, rr); + MAKE_MUT(r, wia*csz); + mut_to(r, fillElType(xf)); + for (usz i = 0; i < wia; i++) { + B cw = wgetU(w, i); + if (!isNum(cw)) { harr_pfree(mut_fp(r), i*csz); goto base; } + f64 c = o2f(cw); + if (c<0) c+= cam; + if ((usz)c >= cam) thrM("⊏: Indexing out-of-bounds"); + mut_copy(r, i*csz, x, csz*(usz)c, csz); + } + B rb = mut_fp(r); + usz* rsh = arr_shAllocR(rb, rr); if (rsh) { memcpy(rsh , a(w)->sh , wr *sizeof(usz)); memcpy(rsh+wr, a(x)->sh+1, (xr-1)*sizeof(usz)); } - for (usz i = 0; i < wia; i++) { - B cw = wgetU(w, i); - if (!isNum(cw)) { harr_pfree(r.b, i); goto base; } - f64 c = o2f(cw); - if (c<0) c+= cam; - if ((usz)c >= cam) thrM("⊏: Indexing out-of-bounds"); - for (usz j = 0; j < csz; j++) r.a[i*csz+j] = xget(x, c*csz+j); - } dec(w); dec(x); - return withFill(r.b,xf); + return withFill(rb,xf); } } base: @@ -342,13 +343,14 @@ B drop_c2(B t, B w, B x) { } B join_c2(B t, B w, B x) { if (!isArr(w)|!isArr(x) || rnk(w)!=1 | rnk(x)!=1) thrM("∾: NYI non-vector args"); - usz wia = a(w)->ia; BS2B wget = TI(w).get; - usz xia = a(x)->ia; BS2B xget = TI(x).get; - HArr_p r = m_harrUv(wia+xia); - for (i64 i = 0; i < wia; i++) r.a[i ] = wget(w, i); - for (i64 i = 0; i < xia; i++) r.a[i+wia] = xget(x, i); + usz wia = a(w)->ia; + usz xia = a(x)->ia; + MAKE_MUT(r, wia+xia); + mut_to(r, el_or(TI(w).elType, TI(x).elType)); + mut_copy(r, 0, w, 0, wia); + mut_copy(r, wia, x, 0, xia); dec(x); dec(w); - return r.b; + return mut_fv(r); } #define ba(N) bi_##N = mm_alloc(sizeof(BFn), t_funBI, ftag(FUN_TAG)); c(Fun,bi_##N)->c2 = N##_c2 ;c(Fun,bi_##N)->c1 = N##_c1 ; c(Fun,bi_##N)->extra=pf_##N; c(BFn,bi_##N)->ident=bi_N; gc_add(bi_##N); diff --git a/src/stuff.c b/src/stuff.c index d7ec7a0d..9d4650b7 100644 --- a/src/stuff.c +++ b/src/stuff.c @@ -118,6 +118,12 @@ usz arr_csz(B x) { return r; } +u8 fillElType(B x) { + if (isNum(x)) return el_i32; + if (isC32(x)) return el_c32; + return el_B; +} + #ifdef DEBUG @@ -182,7 +188,8 @@ static inline void hdr_init() { ti[i].m2_d = def_m2_d; ti[i].isArr = false; ti[i].arrD1 = false; - ti[i].identity = def_identity; + ti[i].elType = el_B; + ti[i].identity = def_identity; ti[i].decompose = def_decompose; ti[i].slice = def_slice; ti[i].canStore = def_canStore;