new mut interface
This commit is contained in:
parent
09fe162b73
commit
9d3067fa4b
@ -12,7 +12,7 @@ static Arr* take_impl(usz ria, B x) { // consumes x; returns v↑⥊𝕩 without
|
||||
mut_copyG(r, 0, x, 0, xia);
|
||||
mut_fill(r, xia, xf, ria-xia);
|
||||
dec(x);
|
||||
if (r->type!=el_B) { dec(xf); return mut_fp(r); }
|
||||
if (r->fns->elType!=el_B) { dec(xf); return mut_fp(r); }
|
||||
return a(withFill(mut_fv(r), xf));
|
||||
} else {
|
||||
return TI(x,slice)(x,0,ria);
|
||||
@ -1296,7 +1296,7 @@ B slash_ucw(B t, B o, B w, B x) {
|
||||
if (a(w)->type == t_bitarr) {
|
||||
u64* d = bitarr_ptr(w);
|
||||
if (TI(x,elType)<=el_i32 && TI(rep,elType)<=el_i32) {
|
||||
if (r->type!=el_i32) mut_to(r, el_i32);
|
||||
if (r->fns->elType!=el_i32) mut_to(r, el_i32);
|
||||
i32* rp = r->ai32;
|
||||
x = toI32Any(x); i32* xp = i32any_ptr(x);
|
||||
rep = toI32Any(rep); i32* np = i32any_ptr(rep);
|
||||
|
||||
221
src/utils/mut.c
221
src/utils/mut.c
@ -1,78 +1,13 @@
|
||||
#include "../core.h"
|
||||
#include "mut.h"
|
||||
|
||||
void mut_copyG(Mut* m, usz ms, B x, usz xs, usz l) { assert(isArr(x));
|
||||
// printf("mut_%d[%d…%d] ← %s[%d…%d]\n", m->type, ms, ms+l, type_repr(xt), xs, xs+l); fflush(stdout);
|
||||
u8 xt = v(x)->type;
|
||||
switch(m->type) { default: UD;
|
||||
case el_bit: bit_cpy(m->abit, ms, bitarr_ptr(x), xs, l); return;
|
||||
case el_i8: { i8* rp = m->ai8+ms;
|
||||
switch (xt) { default: UD;
|
||||
case t_bitarr: { u64* xp = bitarr_ptr(x); for (usz i = 0; i < l; i++) rp[i] = bitp_get(xp, xs+i); return; }
|
||||
case t_i8arr: case t_i8slice: { i8* xp = i8any_ptr(x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
}
|
||||
}
|
||||
case el_i16: { i16* rp = m->ai16+ms;
|
||||
switch (xt) { default: UD;
|
||||
case t_bitarr: { u64* xp = bitarr_ptr(x); for (usz i = 0; i < l; i++) rp[i] = bitp_get(xp, xs+i); return; }
|
||||
case t_i8arr: case t_i8slice: { i8* xp = i8any_ptr (x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
case t_i16arr: case t_i16slice: { i16* xp = i16any_ptr(x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
}
|
||||
}
|
||||
case el_i32: { i32* rp = m->ai32+ms;
|
||||
switch (xt) { default: UD;
|
||||
case t_bitarr: { u64* xp = bitarr_ptr(x); for (usz i = 0; i < l; i++) rp[i] = bitp_get(xp, xs+i); return; }
|
||||
case t_i8arr: case t_i8slice: { i8* xp = i8any_ptr (x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
case t_i16arr: case t_i16slice: { i16* xp = i16any_ptr(x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
case t_i32arr: case t_i32slice: { i32* xp = i32any_ptr(x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
}
|
||||
}
|
||||
case el_f64: {
|
||||
f64* rp = m->af64+ms;
|
||||
switch (xt) { default: UD;
|
||||
case t_bitarr: { u64* xp = bitarr_ptr(x); for (usz i = 0; i < l; i++) rp[i] = bitp_get(xp, xs+i); return; }
|
||||
case t_i8arr: case t_i8slice: { i8* xp = i8any_ptr (x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
case t_i16arr: case t_i16slice: { i16* xp = i16any_ptr(x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
case t_i32arr: case t_i32slice: { i32* xp = i32any_ptr(x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
case t_f64arr: case t_f64slice: { f64* xp = f64any_ptr(x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
}
|
||||
}
|
||||
case el_c8: { u8* rp = m->ac8+ms; u8* xp = c8any_ptr(x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
case el_c16: { u16* rp = m->ac16+ms;
|
||||
switch (xt) { default: UD;
|
||||
case t_c8arr: case t_c8slice: { u8* xp = c8any_ptr (x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
case t_c16arr: case t_c16slice: { u16* xp = c16any_ptr(x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
}
|
||||
}
|
||||
case el_c32: { u32* rp = m->ac32+ms;
|
||||
switch (xt) { default: UD;
|
||||
case t_c8arr: case t_c8slice: { u8* xp = c8any_ptr (x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
case t_c16arr: case t_c16slice: { u16* xp = c16any_ptr(x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
case t_c32arr: case t_c32slice: { u32* xp = c32any_ptr(x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
}
|
||||
}
|
||||
case el_B: {
|
||||
B* mpo = m->aB+ms;
|
||||
B* xp = arr_bptr(x);
|
||||
if (xp!=NULL) {
|
||||
memcpy(mpo, xp+xs, l*sizeof(B));
|
||||
for (usz i = 0; i < l; i++) inc(mpo[i]);
|
||||
return;
|
||||
}
|
||||
SGet(x)
|
||||
for (usz i = 0; i < l; i++) mpo[i] = Get(x,i+xs);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NOINLINE void mut_to(Mut* m, u8 n) {
|
||||
u8 o = m->type;
|
||||
u8 o = m->fns->elType;
|
||||
assert(o!=el_B);
|
||||
if (o==el_MAX) {
|
||||
mut_init(m, n);
|
||||
} else {
|
||||
m->type = n;
|
||||
m->fns = &mutFns[n];
|
||||
sprnk(m->val, 1);
|
||||
m->val->sh = &m->val->ia;
|
||||
#ifdef USE_VALGRIND
|
||||
@ -109,10 +44,139 @@ NOINLINE B vec_addR(B w, B x) {
|
||||
}
|
||||
|
||||
NOINLINE void mut_pfree(Mut* m, usz n) { // free the first n elements
|
||||
if (m->type==el_B) harr_pfree(taga(m->val), n);
|
||||
if (m->fns->elType==el_B) harr_pfree(taga(m->val), n);
|
||||
else mm_free((Value*) m->val);
|
||||
}
|
||||
|
||||
|
||||
B vec_join(B w, B x) {
|
||||
return vec_join_inline(w, x);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define CHK(REQ,NEL,N,...) if (!(REQ)) mut_to(m, NEL); m->fns->m_##N##G(m, __VA_ARGS__);
|
||||
#define CHK_S(REQ,X,N,...) CHK(REQ, el_or(m->fns->elType, selfElType(X)), N, __VA_ARGS__)
|
||||
|
||||
|
||||
#define DEF(RT, N, TY, INIT, CHK, EL, ARGS, ...) \
|
||||
static RT m_##N##G_##TY ARGS; \
|
||||
static RT m_##N##_##TY ARGS { INIT \
|
||||
if (RARE(!(CHK))) { \
|
||||
mut_to(m, EL); \
|
||||
m->fns->m_##N##G(m, __VA_ARGS__); \
|
||||
} else { \
|
||||
m_##N##G_##TY(m, __VA_ARGS__); \
|
||||
} \
|
||||
} \
|
||||
static RT m_##N##G_##TY ARGS
|
||||
|
||||
#define DEF_S( RT, N, TY, CHK, X, ARGS, ...) DEF(RT, N, TY, , CHK, selfElType(X), ARGS, __VA_ARGS__)
|
||||
#define DEF_E( RT, N, TY, CHK, X, ARGS, ...) DEF(RT, N, TY, , CHK, TI(X,elType), ARGS, __VA_ARGS__)
|
||||
#define DEF_G( RT, N, TY, ARGS ) \
|
||||
static RT m_##N##G_##TY ARGS; \
|
||||
static RT (*m_##N##_##TY) ARGS = m_##N##G_##TY; \
|
||||
static RT m_##N##G_##TY ARGS
|
||||
|
||||
DEF_S(void, set, MAX, false, x, (Mut* m, usz ms, B x), ms, x) { err("m_setG_MAX"); }
|
||||
DEF_S(void, set, bit, q_bit(x), x, (Mut* m, usz ms, B x), ms, x) { bitp_set(m->abit, ms, o2bu(x)); }
|
||||
DEF_S(void, set, i8, q_i8 (x), x, (Mut* m, usz ms, B x), ms, x) { m->ai8 [ms] = o2iu(x); }
|
||||
DEF_S(void, set, i16, q_i16(x), x, (Mut* m, usz ms, B x), ms, x) { m->ai16[ms] = o2iu(x); }
|
||||
DEF_S(void, set, i32, q_i32(x), x, (Mut* m, usz ms, B x), ms, x) { m->ai32[ms] = o2iu(x); }
|
||||
DEF_S(void, set, c8, q_c8 (x), x, (Mut* m, usz ms, B x), ms, x) { m->ac8 [ms] = o2cu(x); }
|
||||
DEF_S(void, set, c16, q_c16(x), x, (Mut* m, usz ms, B x), ms, x) { m->ac16[ms] = o2cu(x); }
|
||||
DEF_S(void, set, c32, q_c32(x), x, (Mut* m, usz ms, B x), ms, x) { m->ac32[ms] = o2cu(x); }
|
||||
DEF_S(void, set, f64, q_f64(x), x, (Mut* m, usz ms, B x), ms, x) { m->af64[ms] = o2fu(x); }
|
||||
DEF_G(void, set, B, (Mut* m, usz ms, B x) ) { m->aB[ms] = x; }
|
||||
|
||||
DEF_S(void, fill, MAX, false, x, (Mut* m, usz ms, B x, usz l), ms, x, l) { err("m_fillG_MAX"); }
|
||||
DEF_S(void, fill, bit, q_bit(x), x, (Mut* m, usz ms, B x, usz l), ms, x, l) { u64* p = m->abit; bool v = o2bu(x); for (usz i = 0; i < l; i++) bitp_set(p, ms+i, v); }
|
||||
DEF_S(void, fill, i8 , q_i8 (x), x, (Mut* m, usz ms, B x, usz l), ms, x, l) { i8* p = m->ai8 +ms; i8 v = o2iu(x); for (usz i = 0; i < l; i++) p[i] = v; }
|
||||
DEF_S(void, fill, i16, q_i16(x), x, (Mut* m, usz ms, B x, usz l), ms, x, l) { i16* p = m->ai16+ms; i16 v = o2iu(x); for (usz i = 0; i < l; i++) p[i] = v; }
|
||||
DEF_S(void, fill, i32, q_i32(x), x, (Mut* m, usz ms, B x, usz l), ms, x, l) { i32* p = m->ai32+ms; i32 v = o2iu(x); for (usz i = 0; i < l; i++) p[i] = v; }
|
||||
DEF_S(void, fill, c8 , q_c8 (x), x, (Mut* m, usz ms, B x, usz l), ms, x, l) { u8* p = m->ac8 +ms; u8 v = o2cu(x); for (usz i = 0; i < l; i++) p[i] = v; }
|
||||
DEF_S(void, fill, c16, q_c16(x), x, (Mut* m, usz ms, B x, usz l), ms, x, l) { u16* p = m->ac16+ms; u16 v = o2cu(x); for (usz i = 0; i < l; i++) p[i] = v; }
|
||||
DEF_S(void, fill, c32, q_c32(x), x, (Mut* m, usz ms, B x, usz l), ms, x, l) { u32* p = m->ac32+ms; u32 v = o2cu(x); for (usz i = 0; i < l; i++) p[i] = v; }
|
||||
DEF_S(void, fill, f64, isF64(x), x, (Mut* m, usz ms, B x, usz l), ms, x, l) { f64* p = m->af64+ms; f64 v = o2fu(x); for (usz i = 0; i < l; i++) p[i] = v; }
|
||||
DEF_G(void, fill, B , (Mut* m, usz ms, B x, usz l) ) {
|
||||
B* p = m->aB+ms;
|
||||
for (usz i = 0; i < l; i++) p[i] = x;
|
||||
if (isVal(x)) for (usz i = 0; i < l; i++) inc(x);
|
||||
return;
|
||||
}
|
||||
|
||||
#define DEF_COPY(TY, BODY) DEF(void, copy, TY, u8 xe=TI(x,elType); u8 ne=el_or(xe,el_##TY);, ne==el_##TY, ne, (Mut* m, usz ms, B x, usz xs, usz l), ms, x, xs, l) { u8 xt=v(x)->type; (void)xt; BODY }
|
||||
DEF_COPY(bit, { bit_cpy(m->abit, ms, bitarr_ptr(x), xs, l); return; })
|
||||
DEF_COPY(i8 , { i8* rp = m->ai8+ms;
|
||||
switch (xt) { default: UD;
|
||||
case t_bitarr: { u64* xp = bitarr_ptr(x); for (usz i = 0; i < l; i++) rp[i] = bitp_get(xp, xs+i); return; }
|
||||
case t_i8arr: case t_i8slice: { i8* xp = i8any_ptr(x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
}
|
||||
})
|
||||
DEF_COPY(i16, { i16* rp = m->ai16+ms;
|
||||
switch (xt) { default: UD;
|
||||
case t_bitarr: { u64* xp = bitarr_ptr(x); for (usz i = 0; i < l; i++) rp[i] = bitp_get(xp, xs+i); return; }
|
||||
case t_i8arr: case t_i8slice: { i8* xp = i8any_ptr (x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
case t_i16arr: case t_i16slice: { i16* xp = i16any_ptr(x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
}
|
||||
})
|
||||
DEF_COPY(i32, { i32* rp = m->ai32+ms;
|
||||
switch (xt) { default: UD;
|
||||
case t_bitarr: { u64* xp = bitarr_ptr(x); for (usz i = 0; i < l; i++) rp[i] = bitp_get(xp, xs+i); return; }
|
||||
case t_i8arr: case t_i8slice: { i8* xp = i8any_ptr (x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
case t_i16arr: case t_i16slice: { i16* xp = i16any_ptr(x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
case t_i32arr: case t_i32slice: { i32* xp = i32any_ptr(x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
}
|
||||
})
|
||||
DEF_COPY(f64, { f64* rp = m->af64+ms;
|
||||
switch (xt) { default: UD;
|
||||
case t_bitarr: { u64* xp = bitarr_ptr(x); for (usz i = 0; i < l; i++) rp[i] = bitp_get(xp, xs+i); return; }
|
||||
case t_i8arr: case t_i8slice: { i8* xp = i8any_ptr (x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
case t_i16arr: case t_i16slice: { i16* xp = i16any_ptr(x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
case t_i32arr: case t_i32slice: { i32* xp = i32any_ptr(x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
case t_f64arr: case t_f64slice: { f64* xp = f64any_ptr(x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
}
|
||||
})
|
||||
DEF_COPY(c8 , { u8* rp = m->ac8+ms; u8* xp = c8any_ptr(x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; })
|
||||
DEF_COPY(c16, { u16* rp = m->ac16+ms;
|
||||
switch (xt) { default: UD;
|
||||
case t_c8arr: case t_c8slice: { u8* xp = c8any_ptr (x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
case t_c16arr: case t_c16slice: { u16* xp = c16any_ptr(x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
}
|
||||
})
|
||||
DEF_COPY(c32, { u32* rp = m->ac32+ms;
|
||||
switch (xt) { default: UD;
|
||||
case t_c8arr: case t_c8slice: { u8* xp = c8any_ptr (x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
case t_c16arr: case t_c16slice: { u16* xp = c16any_ptr(x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
case t_c32arr: case t_c32slice: { u32* xp = c32any_ptr(x); for (usz i = 0; i < l; i++) rp[i] = xp[i+xs]; return; }
|
||||
}
|
||||
})
|
||||
DEF_E(void, copy, MAX, false, x, (Mut* m, usz ms, B x, usz xs, usz l), ms, x, xs, l) { err("m_copyG_MAX"); }
|
||||
DEF_G(void, copy, B, (Mut* m, usz ms, B x, usz xs, usz l)) {
|
||||
B* mpo = m->aB+ms;
|
||||
B* xp = arr_bptr(x);
|
||||
if (xp!=NULL) {
|
||||
memcpy(mpo, xp+xs, l*sizeof(B));
|
||||
for (usz i = 0; i < l; i++) inc(mpo[i]);
|
||||
return;
|
||||
}
|
||||
SGet(x)
|
||||
for (usz i = 0; i < l; i++) mpo[i] = Get(x,i+xs);
|
||||
return;
|
||||
}
|
||||
|
||||
static B m_getU_MAX(Mut* m, usz ms) { err("m_setG_MAX"); }
|
||||
static B m_getU_bit(Mut* m, usz ms) { return m_i32(bitp_get(m->abit, ms)); }
|
||||
static B m_getU_i8 (Mut* m, usz ms) { return m_i32(m->ai8 [ms]); }
|
||||
static B m_getU_i16(Mut* m, usz ms) { return m_i32(m->ai16[ms]); }
|
||||
static B m_getU_i32(Mut* m, usz ms) { return m_i32(m->ai32[ms]); }
|
||||
static B m_getU_c8 (Mut* m, usz ms) { return m_c32(m->ac8 [ms]); }
|
||||
static B m_getU_c16(Mut* m, usz ms) { return m_c32(m->ac16[ms]); }
|
||||
static B m_getU_c32(Mut* m, usz ms) { return m_c32(m->ac32[ms]); }
|
||||
static B m_getU_f64(Mut* m, usz ms) { return m_f64(m->af64[ms]); }
|
||||
static B m_getU_B (Mut* m, usz ms) { return m->aB[ms]; }
|
||||
|
||||
MutFns mutFns[el_MAX+1];
|
||||
u8 el_orArr[el_MAX*16 + el_MAX+1];
|
||||
void mutF_init() {
|
||||
for (u8 i = 0; i <= el_MAX; i++) {
|
||||
@ -125,9 +189,20 @@ void mutF_init() {
|
||||
el_orArr[i*16 + j] = el;
|
||||
}
|
||||
}
|
||||
#define FOR_TY(A) A(MAX) A(bit) A(i8) A(i16) A(i32) A(c8) A(c16) A(c32) A(f64) A(B)
|
||||
#define F(T,N) mutFns[el_##T].m_##N = m_##N##_##T;
|
||||
#define G(T) F(T,set) F(T,setG) F(T,getU) F(T,fill) F(T,fillG) F(T,copy) F(T,copyG)
|
||||
FOR_TY(G)
|
||||
#undef G
|
||||
#undef F
|
||||
mutFns[el_bit].elType = el_bit; mutFns[el_bit].valType = t_bitarr;
|
||||
mutFns[el_i8 ].elType = el_i8 ; mutFns[el_i8 ].valType = t_i8arr;
|
||||
mutFns[el_i16].elType = el_i16; mutFns[el_i16].valType = t_i16arr;
|
||||
mutFns[el_i32].elType = el_i32; mutFns[el_i32].valType = t_i32arr;
|
||||
mutFns[el_c8 ].elType = el_c8 ; mutFns[el_c8 ].valType = t_c8arr;
|
||||
mutFns[el_c16].elType = el_c16; mutFns[el_c16].valType = t_c16arr;
|
||||
mutFns[el_c32].elType = el_c32; mutFns[el_c32].valType = t_c32arr;
|
||||
mutFns[el_f64].elType = el_f64; mutFns[el_f64].valType = t_f64arr;
|
||||
mutFns[el_B ].elType = el_B ; mutFns[el_B ].valType = t_harr;
|
||||
mutFns[el_MAX].elType = el_MAX; mutFns[el_MAX].valType = t_COUNT;
|
||||
}
|
||||
|
||||
|
||||
B vec_join(B w, B x) {
|
||||
return vec_join_inline(w, x);
|
||||
}
|
||||
173
src/utils/mut.h
173
src/utils/mut.h
@ -12,9 +12,27 @@ mut_pfree must be used to free a partially finished `mut` instance safely (e.g.
|
||||
methods ending with G expect that mut_init has been called with a type that can fit the elements that it'll set
|
||||
|
||||
*/
|
||||
typedef struct Mut Mut;
|
||||
typedef struct MutFns MutFns;
|
||||
typedef void (*MSB2v)(Mut*, usz, B);
|
||||
typedef void (*MSBS2v)(Mut*, usz, B, usz);
|
||||
typedef void (*MSBSS2v)(Mut*, usz, B, usz, usz);
|
||||
typedef B (*MS2B)(Mut*, usz);
|
||||
struct MutFns {
|
||||
u8 elType;
|
||||
u8 valType;
|
||||
MSB2v m_set;
|
||||
MSB2v m_setG;
|
||||
MS2B m_getU;
|
||||
MSBS2v m_fill;
|
||||
MSBS2v m_fillG;
|
||||
MSBSS2v m_copy;
|
||||
MSBSS2v m_copyG;
|
||||
};
|
||||
extern MutFns mutFns[el_MAX+1];
|
||||
|
||||
typedef struct Mut {
|
||||
u8 type;
|
||||
struct Mut {
|
||||
MutFns* fns;
|
||||
usz ia;
|
||||
Arr* val;
|
||||
union {
|
||||
@ -23,54 +41,53 @@ typedef struct Mut {
|
||||
u8* ac8; u16* ac16; u32* ac32;
|
||||
f64* af64; u64* abit;
|
||||
};
|
||||
} Mut;
|
||||
#define MAKE_MUT(N, IA) Mut N##_val; N##_val.type = el_MAX; N##_val.ia = (IA); Mut* N = &N##_val;
|
||||
};
|
||||
#define MAKE_MUT(N, IA) Mut N##_val; N##_val.fns = &mutFns[el_MAX]; N##_val.ia = (IA); Mut* N = &N##_val;
|
||||
|
||||
static void mut_init(Mut* m, u8 n) {
|
||||
m->type = n;
|
||||
m->fns = &mutFns[n];
|
||||
usz ia = m->ia;
|
||||
u8 ty;
|
||||
usz sz;
|
||||
// hack around inlining of the allocator too many times
|
||||
switch(n) { default: UD;
|
||||
case el_bit: ty = t_bitarr; sz = BITARR_SZ( ia); break;
|
||||
case el_i8: ty = t_i8arr ; sz = TYARR_SZ(I8, ia); break;
|
||||
case el_i16: ty = t_i16arr; sz = TYARR_SZ(I16,ia); break;
|
||||
case el_i32: ty = t_i32arr; sz = TYARR_SZ(I32,ia); break;
|
||||
case el_c8: ty = t_c8arr ; sz = TYARR_SZ(C8, ia); break;
|
||||
case el_c16: ty = t_c16arr; sz = TYARR_SZ(C16,ia); break;
|
||||
case el_c32: ty = t_c32arr; sz = TYARR_SZ(C32,ia); break;
|
||||
case el_f64: ty = t_f64arr; sz = TYARR_SZ(F64,ia); break;
|
||||
case el_bit: sz = BITARR_SZ( ia); break;
|
||||
case el_i8: sz = TYARR_SZ(I8, ia); break;
|
||||
case el_i16: sz = TYARR_SZ(I16,ia); break;
|
||||
case el_i32: sz = TYARR_SZ(I32,ia); break;
|
||||
case el_c8: sz = TYARR_SZ(C8, ia); break;
|
||||
case el_c16: sz = TYARR_SZ(C16,ia); break;
|
||||
case el_c32: sz = TYARR_SZ(C32,ia); break;
|
||||
case el_f64: sz = TYARR_SZ(F64,ia); break;
|
||||
case el_B:;
|
||||
HArr_p t = m_harrUp(ia);
|
||||
m->val = (Arr*)t.c;
|
||||
m->aB = t.c->a;
|
||||
return;
|
||||
}
|
||||
Arr* a = m_arr(sz, ty, ia);
|
||||
Arr* a = m_arr(sz, m->fns->valType, ia);
|
||||
m->val = a;
|
||||
m->a = ((TyArr*)a)->a;
|
||||
}
|
||||
void mut_to(Mut* m, u8 n);
|
||||
|
||||
static B mut_fv(Mut* m) { assert(m->type!=el_MAX);
|
||||
static B mut_fv(Mut* m) { assert(m->fns->elType!=el_MAX);
|
||||
Arr* a = m->val;
|
||||
a->sh = &a->ia;
|
||||
sprnk(a, 1);
|
||||
return taga(a);
|
||||
}
|
||||
static B mut_fc(Mut* m, B x) { assert(m->type!=el_MAX);
|
||||
static B mut_fc(Mut* m, B x) { assert(m->fns->elType!=el_MAX);
|
||||
Arr* a = m->val;
|
||||
arr_shCopy(a, x);
|
||||
return taga(a);
|
||||
}
|
||||
static B mut_fcd(Mut* m, B x) { assert(m->type!=el_MAX);
|
||||
static B mut_fcd(Mut* m, B x) { assert(m->fns->elType!=el_MAX);
|
||||
Arr* a = m->val;
|
||||
arr_shCopy(a, x);
|
||||
dec(x);
|
||||
return taga(a);
|
||||
}
|
||||
static Arr* mut_fp(Mut* m) { assert(m->type!=el_MAX);
|
||||
static Arr* mut_fp(Mut* m) { assert(m->fns->elType!=el_MAX);
|
||||
return m->val;
|
||||
}
|
||||
|
||||
@ -81,85 +98,39 @@ static u8 el_or(u8 a, u8 b) {
|
||||
|
||||
void mut_pfree(Mut* m, usz n);
|
||||
|
||||
static void mut_set(Mut* m, usz ms, B x) { // consumes x; sets m[ms] to x
|
||||
again:;
|
||||
switch(m->type) { default: UD;
|
||||
case el_MAX: goto change;
|
||||
case el_bit: if (!q_bit(x)) goto change; bitp_set(m->abit, ms, o2bu(x)); return;
|
||||
case el_i8: if (!q_i8 (x)) goto change; m->ai8 [ms] = o2iu(x); return;
|
||||
case el_i16: if (!q_i16(x)) goto change; m->ai16[ms] = o2iu(x); return;
|
||||
case el_i32: if (!q_i32(x)) goto change; m->ai32[ms] = o2iu(x); return;
|
||||
case el_c8: if (!q_c8 (x)) goto change; m->ac8 [ms] = o2cu(x); return;
|
||||
case el_c16: if (!q_c16(x)) goto change; m->ac16[ms] = o2cu(x); return;
|
||||
case el_c32: if (!q_c32(x)) goto change; m->ac32[ms] = o2cu(x); return;
|
||||
case el_f64: if (!q_f64(x)) goto change; m->af64[ms] = o2fu(x); return;
|
||||
case el_B: {
|
||||
m->aB[ms] = x;
|
||||
return;
|
||||
}
|
||||
}
|
||||
change:
|
||||
mut_to(m, el_or(m->type, selfElType(x)));
|
||||
goto again;
|
||||
}
|
||||
static void mut_setG(Mut* m, usz ms, B x) { // consumes; sets m[ms] to x, assumes the current type can store it
|
||||
switch(m->type) { default: UD;
|
||||
case el_bit: { assert(q_bit(x)); bitp_set(m->abit, ms, o2bu(x)); return; }
|
||||
case el_i8 : { assert(q_i8 (x)); m->ai8 [ms] = o2iu(x); return; }
|
||||
case el_i16: { assert(q_i16(x)); m->ai16[ms] = o2iu(x); return; }
|
||||
case el_i32: { assert(q_i32(x)); m->ai32[ms] = o2iu(x); return; }
|
||||
case el_c8 : { assert(q_c8 (x)); m->ac8 [ms] = o2cu(x); return; }
|
||||
case el_c16: { assert(q_c16(x)); m->ac16[ms] = o2cu(x); return; }
|
||||
case el_c32: { assert(q_c32(x)); m->ac32[ms] = o2cu(x); return; }
|
||||
case el_f64: { assert(q_f64(x)); m->af64[ms] = o2fu(x); return; }
|
||||
case el_B: {
|
||||
m->aB[ms] = x;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
static void mut_rm(Mut* m, usz ms) { // clears the object at position ms
|
||||
if (m->type == el_B) dec(m->aB[ms]);
|
||||
}
|
||||
static B mut_getU(Mut* m, usz ms) {
|
||||
switch(m->type) { default: UD;
|
||||
case el_bit: return m_i32(bitp_get(m->abit, ms));
|
||||
case el_i8: return m_i32(m->ai8 [ms]);
|
||||
case el_i16: return m_i32(m->ai16[ms]);
|
||||
case el_i32: return m_i32(m->ai32[ms]);
|
||||
case el_c8: return m_c32(m->ac8 [ms]);
|
||||
case el_c16: return m_c32(m->ac16[ms]);
|
||||
case el_c32: return m_c32(m->ac32[ms]);
|
||||
case el_f64: return m_f64(m->af64[ms]);
|
||||
case el_B: return m->aB[ms];
|
||||
}
|
||||
}
|
||||
// do N = OBJ; F, while asserting that OBJ won't change during F
|
||||
#define CONST_OP(N, OBJ, F) ({ \
|
||||
__auto_type N = OBJ; \
|
||||
F; \
|
||||
if (N!=OBJ) __builtin_unreachable(); \
|
||||
})
|
||||
|
||||
#define MUTG(NAME, ...) CONST_OP(f, m->fns->m_##NAME##G, f(__VA_ARGS__))
|
||||
|
||||
// consumes x; sets m[ms] to x
|
||||
static void mut_set(Mut* m, usz ms, B x) { m->fns->m_set(m, ms, x); }
|
||||
|
||||
|
||||
// clears the object (decrements its refcount) at position ms
|
||||
static void mut_rm(Mut* m, usz ms) { if (m->fns->elType == el_B) dec(m->aB[ms]); }
|
||||
|
||||
// gets object at position ms, without increasing refcount
|
||||
static B mut_getU(Mut* m, usz ms) { return m->fns->m_getU(m, ms); }
|
||||
|
||||
static void mut_fillG(Mut* m, usz ms, B x, usz l) { // doesn't consume x
|
||||
switch(m->type) { default: UD;
|
||||
case el_bit: { assert(q_bit(x)); u64* p = m->abit; bool v = o2bu(x); for (usz i = 0; i < l; i++) bitp_set(p, ms+i, v); return; }
|
||||
case el_i8: { assert(q_i8 (x)); i8* p = m->ai8 +ms; i8 v = o2iu(x); for (usz i = 0; i < l; i++) p[i] = v; return; }
|
||||
case el_i16: { assert(q_i16(x)); i16* p = m->ai16+ms; i16 v = o2iu(x); for (usz i = 0; i < l; i++) p[i] = v; return; }
|
||||
case el_i32: { assert(q_i32(x)); i32* p = m->ai32+ms; i32 v = o2iu(x); for (usz i = 0; i < l; i++) p[i] = v; return; }
|
||||
case el_c8: { assert(q_c8 (x)); u8* p = m->ac8 +ms; u8 v = o2cu(x); for (usz i = 0; i < l; i++) p[i] = v; return; }
|
||||
case el_c16: { assert(q_c16(x)); u16* p = m->ac16+ms; u16 v = o2cu(x); for (usz i = 0; i < l; i++) p[i] = v; return; }
|
||||
case el_c32: { assert(q_c32(x)); u32* p = m->ac32+ms; u32 v = o2cu(x); for (usz i = 0; i < l; i++) p[i] = v; return; }
|
||||
case el_f64: { assert(isF64(x)); f64* p = m->af64+ms; f64 v = o2fu(x); for (usz i = 0; i < l; i++) p[i] = v; return; }
|
||||
case el_B: {
|
||||
B* p = m->aB+ms;
|
||||
for (usz i = 0; i < l; i++) p[i] = x;
|
||||
if (isVal(x)) for (usz i = 0; i < l; i++) inc(x);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// doesn't consume; fills m[ms…ms+l] with x
|
||||
static void mut_fill(Mut* m, usz ms, B x, usz l) {
|
||||
u8 nmt = el_or(m->type, selfElType(x));
|
||||
if (nmt!=m->type) mut_to(m, nmt);
|
||||
mut_fillG(m, ms, x, l);
|
||||
}
|
||||
static void mut_fill(Mut* m, usz ms, B x, usz l) { m->fns->m_fill(m, ms, x, l); }
|
||||
|
||||
// expects x to be an array, each position must be written to precisely once
|
||||
// doesn't consume x
|
||||
static void mut_copy(Mut* m, usz ms, B x, usz xs, usz l) { assert(isArr(x)); m->fns->m_copy(m, ms, x, xs, l); }
|
||||
|
||||
// mut_set but assumes the type of x already fits in m
|
||||
static void mut_setG(Mut* m, usz ms, B x) { MUTG(set, m, ms, x); }
|
||||
// mut_fill but assumes the type of x already fits in m
|
||||
static void mut_fillG(Mut* m, usz ms, B x, usz l) { MUTG(fill, m, ms, x, l); }
|
||||
// mut_copy but assumes the type of x already fits in m
|
||||
static void mut_copyG(Mut* m, usz ms, B x, usz xs, usz l) { MUTG(copy, m, ms, x, xs, l); }
|
||||
|
||||
static void bit_cpy(u64* r, usz rs, u64* x, usz xs, usz l) { // TODO rewrite this whole thing to be all fancy
|
||||
u64 i = rs;
|
||||
@ -178,18 +149,6 @@ static void bit_cpy(u64* r, usz rs, u64* x, usz xs, usz l) { // TODO rewrite thi
|
||||
for (; i<re; i++) bitp_set(r, i, bitp_get(x, i+d));
|
||||
}
|
||||
|
||||
// mut_copy but x is guaranteed to be a subtype of m
|
||||
void mut_copyG(Mut* m, usz ms, B x, usz xs, usz l);
|
||||
|
||||
// expects x to be an array, each position must be written to precisely once
|
||||
// doesn't consume x
|
||||
static void mut_copy(Mut* m, usz ms, B x, usz xs, usz l) { assert(isArr(x));
|
||||
u8 nmt = el_or(m->type, TI(x,elType));
|
||||
if (nmt!=m->type) mut_to(m, nmt);
|
||||
mut_copyG(m, ms, x, xs, l);
|
||||
}
|
||||
|
||||
|
||||
B vec_join(B w, B x); // consumes both
|
||||
FORCE_INLINE B vec_join_inline(B w, B x) {
|
||||
usz wia = a(w)->ia;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user