This commit is contained in:
dzaima 2021-04-29 23:41:16 +03:00
parent 6c2ed64ab4
commit 4783812eaf
7 changed files with 163 additions and 28 deletions

View File

@ -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)) {

28
src/h.h
View File

@ -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

View File

@ -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;
}

View File

@ -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"

108
src/mut.c Normal file
View File

@ -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
}

View File

@ -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);

View File

@ -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;