mut
This commit is contained in:
parent
6c2ed64ab4
commit
4783812eaf
@ -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_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_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_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);
|
dec(x);
|
||||||
return bi_noFill;
|
return bi_noFill;
|
||||||
}
|
}
|
||||||
@ -118,6 +119,7 @@ B withFill(B x, B fill) { // consumes both
|
|||||||
#endif
|
#endif
|
||||||
if (noFill(fill) && v(x)->type!=t_fillarr && v(x)->type!=t_fillslice) return x;
|
if (noFill(fill) && v(x)->type!=t_fillarr && v(x)->type!=t_fillslice) return x;
|
||||||
switch(v(x)->type) {
|
switch(v(x)->type) {
|
||||||
|
case t_f64arr : case t_f64slice:
|
||||||
case t_i32arr : case t_i32slice: if(fill.u == m_i32(0 ).u) return x; break;
|
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_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_fillslice: if (equal(c(FillArr,c(Slice,x)->p)->fill, fill)) { dec(fill); return x; } break;
|
||||||
|
|||||||
28
src/h.h
28
src/h.h
@ -72,6 +72,15 @@ enum Type {
|
|||||||
#endif
|
#endif
|
||||||
t_COUNT
|
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) {
|
char* format_type(u8 u) {
|
||||||
switch(u) { default: return"(unknown type)";
|
switch(u) { default: return"(unknown type)";
|
||||||
case t_empty:return"empty"; case t_shape:return"shape";
|
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
|
void print(B x); // doesn't consume
|
||||||
bool equal(B w, B x); // doesn't consume
|
bool equal(B w, B x); // doesn't consume
|
||||||
void arr_print(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
|
bool eqShape(B w, B x); // doesn't consume
|
||||||
usz arr_csz(B x); // doesn't consume
|
usz arr_csz(B x); // doesn't consume
|
||||||
bool eqShPrefix(usz* w, usz* x, ur len);
|
bool eqShPrefix(usz* w, usz* x, ur len);
|
||||||
@ -228,12 +238,14 @@ B catchMessage;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define c(T,x) ((T*)((x).u&0xFFFFFFFFFFFFull))
|
#define c(T,X) ((T*)((X).u&0xFFFFFFFFFFFFull))
|
||||||
#define v(x) c(Value, x)
|
#define v(X) c(Value, X)
|
||||||
#define a(x) c(Arr , x)
|
#define a(X) c(Arr , X)
|
||||||
#define rnk(x ) (v(x)->extra) // expects argument to be Arr
|
#define prnk(X ) (X->extra)
|
||||||
#define srnk(x,r) (v(x)->extra=(r))
|
#define sprnk(X,R) (X->extra=(R))
|
||||||
#define VT(x,t) assert(isVal(x) && v(x)->type==t)
|
#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();
|
void print_vmStack();
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -358,9 +370,11 @@ typedef struct TypeInfo {
|
|||||||
BB2B m1_d; // consume all args; (m, f)
|
BB2B m1_d; // consume all args; (m, f)
|
||||||
BBB2B m2_d; // consume all args; (m, f, g)
|
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
|
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 identity; // return identity element of this function; doesn't consume
|
||||||
|
|
||||||
|
B2b canStore; // doesn't consume
|
||||||
|
u8 elType;
|
||||||
|
|
||||||
B2v print; // doesn't consume
|
B2v print; // doesn't consume
|
||||||
B2v visit; // call mm_visit for all referents
|
B2v visit; // call mm_visit for all referents
|
||||||
B2B decompose; // consumes; must return a HArr
|
B2B decompose; // consumes; must return a HArr
|
||||||
|
|||||||
@ -74,5 +74,6 @@ static inline void i32arr_init() {
|
|||||||
ti[t_i32arr].print = arr_print; ti[t_i32slice].print = arr_print;
|
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].isArr = true; ti[t_i32slice].isArr = true;
|
||||||
ti[t_i32arr].arrD1 = true; ti[t_i32slice].arrD1 = 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;
|
ti[t_i32arr].canStore = i32arr_canStore;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,6 +28,7 @@
|
|||||||
#include "i32arr.c"
|
#include "i32arr.c"
|
||||||
#include "c32arr.c"
|
#include "c32arr.c"
|
||||||
#include "f64arr.c"
|
#include "f64arr.c"
|
||||||
|
#include "mut.c"
|
||||||
#include "utf.c"
|
#include "utf.c"
|
||||||
#include "derv.c"
|
#include "derv.c"
|
||||||
#include "fns.c"
|
#include "fns.c"
|
||||||
|
|||||||
108
src/mut.c
Normal file
108
src/mut.c
Normal 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
|
||||||
|
}
|
||||||
38
src/sfns.c
38
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");
|
if (rr>UR_MAX) thrM("⊏: Result rank too large");
|
||||||
usz csz = arr_csz(x);
|
usz csz = arr_csz(x);
|
||||||
usz cam = a(x)->sh[0];
|
usz cam = a(x)->sh[0];
|
||||||
usz ria = wia*csz;
|
MAKE_MUT(r, wia*csz);
|
||||||
HArr_p r = m_harrUp(ria);
|
mut_to(r, fillElType(xf));
|
||||||
usz* rsh = arr_shAllocR(r.b, rr);
|
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) {
|
if (rsh) {
|
||||||
memcpy(rsh , a(w)->sh , wr *sizeof(usz));
|
memcpy(rsh , a(w)->sh , wr *sizeof(usz));
|
||||||
memcpy(rsh+wr, a(x)->sh+1, (xr-1)*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);
|
dec(w); dec(x);
|
||||||
return withFill(r.b,xf);
|
return withFill(rb,xf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
base:
|
base:
|
||||||
@ -342,13 +343,14 @@ B drop_c2(B t, B w, B x) {
|
|||||||
}
|
}
|
||||||
B join_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");
|
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 wia = a(w)->ia;
|
||||||
usz xia = a(x)->ia; BS2B xget = TI(x).get;
|
usz xia = a(x)->ia;
|
||||||
HArr_p r = m_harrUv(wia+xia);
|
MAKE_MUT(r, wia+xia);
|
||||||
for (i64 i = 0; i < wia; i++) r.a[i ] = wget(w, i);
|
mut_to(r, el_or(TI(w).elType, TI(x).elType));
|
||||||
for (i64 i = 0; i < xia; i++) r.a[i+wia] = xget(x, i);
|
mut_copy(r, 0, w, 0, wia);
|
||||||
|
mut_copy(r, wia, x, 0, xia);
|
||||||
dec(x); dec(w);
|
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);
|
#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);
|
||||||
|
|||||||
@ -118,6 +118,12 @@ usz arr_csz(B x) {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u8 fillElType(B x) {
|
||||||
|
if (isNum(x)) return el_i32;
|
||||||
|
if (isC32(x)) return el_c32;
|
||||||
|
return el_B;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -182,6 +188,7 @@ static inline void hdr_init() {
|
|||||||
ti[i].m2_d = def_m2_d;
|
ti[i].m2_d = def_m2_d;
|
||||||
ti[i].isArr = false;
|
ti[i].isArr = false;
|
||||||
ti[i].arrD1 = false;
|
ti[i].arrD1 = false;
|
||||||
|
ti[i].elType = el_B;
|
||||||
ti[i].identity = def_identity;
|
ti[i].identity = def_identity;
|
||||||
ti[i].decompose = def_decompose;
|
ti[i].decompose = def_decompose;
|
||||||
ti[i].slice = def_slice;
|
ti[i].slice = def_slice;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user