working i8/i16-arrs
This commit is contained in:
parent
80be141968
commit
21ba88751a
@ -80,9 +80,7 @@ Extra functions for converting types:
|
||||
o2cu(x) // B → c32, assumes is valid
|
||||
o2fu(x) // B → f64, assumes is valid
|
||||
o2b(x) // B → bool, throw if impossible
|
||||
q_i32(x) // query if x is convertible to i32
|
||||
q_i64(x) // query if x is convertible to i64
|
||||
q_f64(x) // query if x is convertible to f64 (equivalent to isF64)
|
||||
q_TYPE(x) // query if x is convertible to TYPE (see definitions in h.h)
|
||||
q_N(x) // query if x is · (≡ bi_N)
|
||||
noFill(x) // if x represents undefined fill (returned by getFill*; ≡ bi_noFill)
|
||||
tag(x,*_TAG) // pointer → B
|
||||
|
||||
@ -29,13 +29,23 @@ void ud_rec(B** p, usz d, usz r, i32* pos, usz* sh) {
|
||||
B ud_c1(B t, B x) {
|
||||
if (isAtm(x)) {
|
||||
usz xu = o2s(x);
|
||||
if (RARE(xu>=I32_MAX)) {
|
||||
f64* rp; B r = m_f64arrv(&rp, xu);
|
||||
if (LIKELY(xu<=I8_MAX)) {
|
||||
if (RARE(xu==0)) return emptyIVec();
|
||||
i8* rp; B r = m_i8arrv(&rp, xu);
|
||||
for (usz i = 0; i < xu; i++) rp[i] = i;
|
||||
return r;
|
||||
}
|
||||
if (xu==0) return emptyIVec();
|
||||
i32* rp; B r = m_i32arrv(&rp, xu);
|
||||
if (xu<=I16_MAX) {
|
||||
i16* rp; B r = m_i16arrv(&rp, xu);
|
||||
for (usz i = 0; i < xu; i++) rp[i] = i;
|
||||
return r;
|
||||
}
|
||||
if (xu<=I32_MAX) {
|
||||
i32* rp; B r = m_i32arrv(&rp, xu);
|
||||
for (usz i = 0; i < xu; i++) rp[i] = i;
|
||||
return r;
|
||||
}
|
||||
f64* rp; B r = m_f64arrv(&rp, xu);
|
||||
for (usz i = 0; i < xu; i++) rp[i] = i;
|
||||
return r;
|
||||
}
|
||||
|
||||
12
src/core.h
12
src/core.h
@ -26,9 +26,21 @@
|
||||
#define TYARR_SZ(T,IA) fsizeof(T##Arr, a, T##Atom, IA)
|
||||
#define TYARR_SZ2(T,IA) TYARR_SZ(T,IA)
|
||||
|
||||
#define TU I8
|
||||
#define TP(W,X) W##i8##X
|
||||
#include "core/tyarrTemplate.h"
|
||||
#define TU I16
|
||||
#define TP(W,X) W##i16##X
|
||||
#include "core/tyarrTemplate.h"
|
||||
#define TU I32
|
||||
#define TP(W,X) W##i32##X
|
||||
#include "core/tyarrTemplate.h"
|
||||
#define TU C8
|
||||
#define TP(W,X) W##c8##X
|
||||
#include "core/tyarrTemplate.h"
|
||||
#define TU C16
|
||||
#define TP(W,X) W##c16##X
|
||||
#include "core/tyarrTemplate.h"
|
||||
#define TU C32
|
||||
#define TP(W,X) W##c32##X
|
||||
#include "core/tyarrTemplate.h"
|
||||
|
||||
@ -29,8 +29,8 @@ static bool fillEqual(B w, B x) {
|
||||
static B getFillR(B x) { // doesn't consume; can return bi_noFill
|
||||
if (isArr(x)) {
|
||||
switch(TI(x,elType)) { default: UD;
|
||||
case el_f64: case el_i32: return m_i32(0);
|
||||
case el_c32: return m_c32(' ');
|
||||
case el_i8: case el_i16: case el_i32: case el_f64: return m_i32(0);
|
||||
case el_c8: case el_c16: case el_c32: return m_c32(' ');
|
||||
case el_B:;
|
||||
u8 t = v(x)->type;
|
||||
if (t==t_fillarr ) return inc(c(FillArr,x )->fill);
|
||||
|
||||
@ -355,7 +355,7 @@ NOINLINE bool equal(B w, B x) { // doesn't consume
|
||||
usz ia = a(x)->ia;
|
||||
u8 we = TI(w,elType);
|
||||
u8 xe = TI(x,elType);
|
||||
if (we<=el_f64 && xe<=el_f64) { assert(we==el_i32|we==el_f64); assert(xe==el_i32|xe==el_f64);
|
||||
if (((we==el_f64 | we==el_i32) && (xe==el_f64 | xe==el_i32))) {
|
||||
if (we==el_i32) { i32* wp = i32any_ptr(w);
|
||||
if(xe==el_i32) { i32* xp = i32any_ptr(x); for (usz i = 0; i < ia; i++) if(wp[i]!=xp[i]) return false; }
|
||||
else { f64* xp = f64any_ptr(x); for (usz i = 0; i < ia; i++) if(wp[i]!=xp[i]) return false; }
|
||||
@ -439,8 +439,12 @@ char* format_type(u8 u) {
|
||||
case t_md2BI:return"builtin md2"; case t_md2_block:return"md2 block";
|
||||
case t_fork:return"fork"; case t_atop:return"atop";
|
||||
case t_md1D:return"md1D"; case t_md2D:return"md2D"; case t_md2H:return"md2H";
|
||||
case t_harr :return"harr" ; case t_i8arr :return"i8arr" ; case t_i32arr :return"i32arr" ; case t_fillarr :return"fillarr" ; case t_c32arr :return"c32arr" ; case t_f64arr :return"f64arr" ;
|
||||
case t_hslice:return"hslice"; case t_i8slice:return"i8slice"; case t_i32slice:return"i32slice"; case t_fillslice:return"fillslice"; case t_c32slice:return"c32slice"; case t_f64slice:return"f64slice";
|
||||
case t_i8arr :return"i8arr" ; case t_i16arr :return"i16arr" ; case t_i32arr :return"i32arr" ;
|
||||
case t_i8slice:return"i8slice"; case t_i16slice:return"i16slice"; case t_i32slice:return"i32slice";
|
||||
case t_c8arr :return"c8arr" ; case t_c16arr :return"c16arr" ; case t_c32arr :return"c32arr" ;
|
||||
case t_c8slice:return"c8slice"; case t_c16slice:return"c16slice"; case t_c32slice:return"c32slice";
|
||||
case t_harr :return"harr" ; case t_fillarr :return"fillarr" ; case t_f64arr :return"f64arr" ;
|
||||
case t_hslice:return"hslice"; case t_fillslice:return"fillslice"; case t_f64slice:return"f64slice";
|
||||
case t_comp:return"comp"; case t_block:return"block"; case t_body:return"body"; case t_scope:return"scope"; case t_scopeExt:return"scope extension"; case t_blBlocks: return "block list";
|
||||
case t_ns:return"ns"; case t_nsDesc:return"nsDesc"; case t_fldAlias:return"alias"; case t_hashmap:return"hashmap"; case t_temp:return"temporary"; case t_nfn:return"nfn"; case t_nfnDesc:return"nfnDesc";
|
||||
case t_freed:return"(freed by GC)"; case t_harrPartial:return"partHarr";
|
||||
|
||||
@ -1,13 +1,27 @@
|
||||
#include "../core.h"
|
||||
|
||||
#define TU F64
|
||||
#define TP(W,X) W##f64##X
|
||||
B m_i8(i8 x) { return m_i32(x); } B m_i16(i16 x) { return m_i32(x); }
|
||||
B m_c8(i8 x) { return m_c32(x); } B m_c16(i16 x) { return m_c32(x); }
|
||||
#define TU I8
|
||||
#define TP(W,X) W##i8##X
|
||||
#include "tyarrTemplate.c"
|
||||
#define TU I16
|
||||
#define TP(W,X) W##i16##X
|
||||
#include "tyarrTemplate.c"
|
||||
#define TU I32
|
||||
#define TP(W,X) W##i32##X
|
||||
#include "tyarrTemplate.c"
|
||||
#define TU C8
|
||||
#define TP(W,X) W##c8##X
|
||||
#include "tyarrTemplate.c"
|
||||
#define TU C16
|
||||
#define TP(W,X) W##c16##X
|
||||
#include "tyarrTemplate.c"
|
||||
#define TU C32
|
||||
#define TP(W,X) W##c32##X
|
||||
#include "tyarrTemplate.c"
|
||||
#define TU I32
|
||||
#define TP(W,X) W##i32##X
|
||||
#define TU F64
|
||||
#define TP(W,X) W##f64##X
|
||||
#include "tyarrTemplate.c"
|
||||
|
||||
NOINLINE B m_caf64(usz sz, f64* a) { f64* rp; B r = m_f64arrv(&rp, sz); for (usz i = 0; i < sz; i++) rp[i] = a[i]; return r; }
|
||||
@ -22,6 +36,9 @@ NOINLINE B m_str32(u32* s) {
|
||||
}
|
||||
|
||||
void tyarr_init() {
|
||||
i8arr_init(); i16arr_init(); i32arr_init();
|
||||
c8arr_init(); c16arr_init(); c32arr_init(); f64arr_init();
|
||||
|
||||
{ i32* tmp; bi_emptyIVec = m_i32arrv(&tmp, 0); gc_add(bi_emptyIVec); }
|
||||
{ u32* tmp; bi_emptyCVec = m_c32arrv(&tmp, 0); gc_add(bi_emptyCVec); }
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ static B TP(,arr_get) (B x, usz n) { VTY(x,T_ARR ); return TP(m_,) (c(TArr ,
|
||||
static B TP(,slice_get) (B x, usz n) { VTY(x,T_SLICE); return TP(m_,) (c(TSlice,x)->a[n]); }
|
||||
static bool TP(,arr_canStore) (B x) { return TP(q_,) (x); }
|
||||
|
||||
void TP(,arr_init)() {
|
||||
static void TP(,arr_init)() {
|
||||
TIi(T_ARR,get) = TP(,arr_get); TIi(T_SLICE,get) = TP(,slice_get);
|
||||
TIi(T_ARR,getU) = TP(,arr_get); TIi(T_SLICE,getU) = TP(,slice_get);
|
||||
TIi(T_ARR,slice) = TP(,arr_slice); TIi(T_SLICE,slice) = TP(,slice_slice);
|
||||
|
||||
25
src/h.h
25
src/h.h
@ -100,6 +100,10 @@
|
||||
#define i64 int64_t
|
||||
#define u64 uint64_t
|
||||
#define f64 double
|
||||
#define I8_MAX 127
|
||||
#define I16_MAX 65535
|
||||
#define I8_MIN (-128)
|
||||
#define I16_MIN (-65536)
|
||||
#define I32_MAX ((i32)((1LL<<31)-1))
|
||||
#define I32_MIN ((i32)(-(1LL<<31)))
|
||||
#define I64_MIN ((i64)(1ULL<<63))
|
||||
@ -174,8 +178,8 @@ enum Type {
|
||||
/* 8*/ t_fork, t_atop,
|
||||
/*10*/ t_md1D, t_md2D, t_md2H,
|
||||
|
||||
/*13*/ t_harr , t_i8arr , t_i32arr , t_fillarr , t_c32arr , t_f64arr ,
|
||||
/*19*/ t_hslice, t_i8slice, t_i32slice, t_fillslice, t_c32slice, t_f64slice,
|
||||
/*13*/ t_i8arr , t_i16arr , t_i32arr , t_c8arr , t_c16arr , t_c32arr , t_f64arr , t_harr , t_fillarr ,
|
||||
/*19*/ t_i8slice, t_i16slice, t_i32slice, t_c8slice, t_c16slice, t_c32slice, t_f64slice, t_hslice, t_fillslice,
|
||||
|
||||
/*25*/ t_comp, t_block, t_body, t_scope, t_scopeExt, t_blBlocks,
|
||||
/*31*/ t_ns, t_nsDesc, t_fldAlias, t_vfyObj, t_hashmap, t_temp, t_nfn, t_nfnDesc,
|
||||
@ -187,11 +191,18 @@ enum Type {
|
||||
};
|
||||
|
||||
enum ElType { // a⌈b shall return the type that can store both, if possible; any x<=el_f64 is an integer type
|
||||
el_i32=0,
|
||||
el_f64=1,
|
||||
el_c32=2,
|
||||
el_B =3,
|
||||
el_MAX=4 // also used for incomplete in mut.c
|
||||
el_bit=0, // unused; just here for completeness of ElType
|
||||
el_i8 =1,
|
||||
el_i16=2,
|
||||
el_i32=3,
|
||||
el_f64=4,
|
||||
|
||||
el_c8 =5,
|
||||
el_c16=6,
|
||||
el_c32=7,
|
||||
|
||||
el_B =8,
|
||||
el_MAX=9 // also used for incomplete in mut.c
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#include "utils/file.h"
|
||||
#include "utils/builtins.h"
|
||||
|
||||
#define FOR_INIT(F) F(base) F(harr) F(fillarr) F(i32arr) F(c32arr) F(f64arr) F(tyarr) F(hash) F(sfns) F(fns) F(arith) F(md1) F(md2) F(derv) F(comp) F(rtWrap) F(ns) F(nfn) F(sysfn) F(load) F(sysfnPost)
|
||||
#define FOR_INIT(F) F(base) F(harr) F(mutF) F(fillarr) F(tyarr) F(hash) F(sfns) F(fns) F(arith) F(md1) F(md2) F(derv) F(comp) F(rtWrap) F(ns) F(nfn) F(sysfn) F(load) F(sysfnPost)
|
||||
#define F(X) void X##_init(void);
|
||||
FOR_INIT(F)
|
||||
#undef F
|
||||
@ -227,7 +227,6 @@ void load_init() { // very last init function
|
||||
|
||||
#ifndef NO_RT
|
||||
B provide[] = {bi_type,bi_fill,bi_log,bi_grLen,bi_grOrd,bi_asrt,bi_add,bi_sub,bi_mul,bi_div,bi_pow,bi_floor,bi_eq,bi_le,bi_fne,bi_shape,bi_pick,bi_ud,bi_tbl,bi_scan,bi_fillBy,bi_val,bi_catch};
|
||||
|
||||
#ifndef ALL_R0
|
||||
B runtime_0[] = {bi_floor,bi_ceil,bi_stile,bi_lt,bi_gt,bi_ne,bi_ge,bi_rtack,bi_ltack,bi_join,bi_take,bi_drop,bi_select,bi_const,bi_swap,bi_each,bi_fold,bi_atop,bi_over,bi_before,bi_after,bi_cond,bi_repeat};
|
||||
#else
|
||||
|
||||
@ -24,6 +24,6 @@
|
||||
#include "../ns.c"
|
||||
#include "../nfns.c"
|
||||
#include "../rtwrap.c"
|
||||
#include "../jit/nvm.c"
|
||||
#include "../load.c"
|
||||
#include "../main.c"
|
||||
#include "../jit/nvm.c"
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
/* sfns.c*/A(shape,"⥊") A(pick,"⊑") A(pair,"{𝕨‿𝕩}") A(select,"⊏") A(slash,"/") A(join,"∾") A(couple,"≍") A(shiftb,"»") A(shifta,"«") A(take,"↑") A(drop,"↓") A(group,"⊔") A(reverse,"⌽") \
|
||||
/* sort.c*/A(gradeUp,"⍋") A(gradeDown,"⍒") \
|
||||
/* everything before the definition of •Type is defined to be pure, and everything after is not */ \
|
||||
/* sysfn.c*/M(type,"•Type") M(decp,"•Decompose") M(primInd,"•PrimInd") M(glyph,"•Glyph") A(fill,"•FillFn") M(sys,"•getsys") A(grLen,"•GroupLen") D(grOrd,"•groupOrd") \
|
||||
/* sysfn.c*/M(type,"•Type") M(decp,"•Decompose") M(primInd,"•PrimInd") M(glyph,"•Glyph") A(fill,"•FillFn") M(sys,"•getsys") A(grLen,"•GroupLen") D(grOrd,"•GroupOrd") \
|
||||
/* sysfn.c*/M(repr,"•Repr") M(fmt,"•Fmt") A(asrt,"!") A(casrt,"!") M(out,"•Out") M(show,"•Show") M(bqn,"•BQN") M(sh,"•SH") M(fromUtf8,"•FromUTF8") \
|
||||
/* sysfn.c*/D(cmp,"•Cmp") A(hash,"•Hash") M(unixTime,"•UnixTime") M(monoTime,"•MonoTime") M(delay,"•Delay") M(makeRand,"•MakeRand") M(reBQN,"•ReBQN") M(exit,"•Exit") M(getLine,"•GetLine") \
|
||||
/*internal.c*/M(itype,"•internal.Type") M(refc,"•internal.Refc") M(squeeze,"•internal.Squeeze") M(isPure,"•internal.IsPure") A(info,"•internal.Info") \
|
||||
|
||||
@ -42,3 +42,17 @@ NOINLINE void mut_pfree(Mut* m, usz n) { // free the first n elements
|
||||
if (m->type==el_B) harr_pfree(taga(m->val), n);
|
||||
else mm_free((Value*) m->val);
|
||||
}
|
||||
|
||||
u8 el_orArr[el_MAX*16 + el_MAX];
|
||||
void mutF_init() {
|
||||
for (u8 i = 0; i <= el_MAX; i++) {
|
||||
for (u8 j = 0; j <= el_MAX; j++) {
|
||||
u8 el;
|
||||
if (i==el_MAX|j==el_MAX) el = i>j?j:i;
|
||||
else if (i<=el_f64 && j<=el_f64) el = i>j?i:j;
|
||||
else if (i>=el_c8 && i<=el_c32 && j>=el_c8 && j<=el_c32) el = i>j?i:j;
|
||||
else el = el_B;
|
||||
el_orArr[i*16 + j] = el;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
265
src/utils/mut.h
265
src/utils/mut.h
@ -18,9 +18,9 @@ typedef struct Mut {
|
||||
usz ia;
|
||||
Arr* val;
|
||||
union {
|
||||
i32* ai32;
|
||||
i8* ai8; i16* ai16; i32* ai32;
|
||||
u8* ac8; u16* ac16; u32* ac32;
|
||||
f64* af64;
|
||||
u32* ac32;
|
||||
B* aB;
|
||||
};
|
||||
} Mut;
|
||||
@ -33,9 +33,13 @@ static void mut_init(Mut* m, u8 n) {
|
||||
usz sz;
|
||||
// hack around inlining of the allocator too many times
|
||||
switch(n) { default: UD;
|
||||
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_f64: ty = t_f64arr; sz = TYARR_SZ(F64,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_B:;
|
||||
HArr_p t = m_harrUp(ia);
|
||||
m->val = (Arr*)t.c;
|
||||
@ -45,9 +49,9 @@ static void mut_init(Mut* m, u8 n) {
|
||||
Arr* a = m_arr(sz, ty, ia);
|
||||
m->val = a;
|
||||
switch(n) { default: UD; // gcc generates horrible code for this (which should just be two instructions), but that's what gcc does
|
||||
case el_i32: m->ai32 = ((I32Arr*)a)->a; break;
|
||||
case el_i8: m->ai8 = ((I8Arr*)a)->a; break; case el_i16: m->ai16 = ((I16Arr*)a)->a; break; case el_i32: m->ai32 = ((I32Arr*)a)->a; break;
|
||||
case el_c8: m->ac8 = ((C8Arr*)a)->a; break; case el_c16: m->ac16 = ((C16Arr*)a)->a; break; case el_c32: m->ac32 = ((C32Arr*)a)->a; break;
|
||||
case el_f64: m->af64 = ((F64Arr*)a)->a; break;
|
||||
case el_c32: m->ac32 = ((C32Arr*)a)->a; break;
|
||||
}
|
||||
}
|
||||
void mut_to(Mut* m, u8 n);
|
||||
@ -73,16 +77,9 @@ static Arr* mut_fp(Mut* m) { assert(m->type!=el_MAX);
|
||||
return m->val;
|
||||
}
|
||||
|
||||
extern u8 el_orArr[];
|
||||
static u8 el_or(u8 a, u8 b) {
|
||||
#define M(X) if(b==X) return a>X?a:X;
|
||||
switch (a) { default: UD;
|
||||
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;
|
||||
}
|
||||
#undef M
|
||||
return el_orArr[a*16 + b];
|
||||
}
|
||||
|
||||
void mut_pfree(Mut* m, usz n);
|
||||
@ -151,70 +148,15 @@ static B mut_getU(Mut* m, usz ms) {
|
||||
}
|
||||
}
|
||||
|
||||
// doesn't consume; fills m[ms…ms+l] with x
|
||||
static void mut_fill(Mut* m, usz ms, B x, usz l) {
|
||||
again:;
|
||||
u8 nty;
|
||||
switch(m->type) { default: UD;
|
||||
case el_MAX:
|
||||
nty = isF64(x)? (q_i32(x)? el_i32 : el_f64) : (isC32(x)? el_c32 : el_B);
|
||||
goto change;
|
||||
|
||||
case el_i32: {
|
||||
if (RARE(!q_i32(x))) { nty = isF64(x)? el_f64 : el_B; goto change; }
|
||||
i32* p = m->ai32+ms;
|
||||
i32 v = o2iu(x);
|
||||
for (usz i = 0; i < l; i++) p[i] = v;
|
||||
return;
|
||||
}
|
||||
case el_c32: {
|
||||
if (RARE(!isC32(x))) { nty = el_B; goto change; }
|
||||
u32* p = m->ac32+ms;
|
||||
u32 v = o2cu(x);
|
||||
for (usz i = 0; i < l; i++) p[i] = v;
|
||||
return;
|
||||
}
|
||||
case el_f64: {
|
||||
if (RARE(!isF64(x))) { nty = el_B; goto change; }
|
||||
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;
|
||||
}
|
||||
}
|
||||
change:
|
||||
mut_to(m, nty);
|
||||
goto again;
|
||||
}
|
||||
static void mut_fillG(Mut* m, usz ms, B x, usz l) { // doesn't consume x
|
||||
switch(m->type) { default: UD;
|
||||
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_c32: {
|
||||
assert(isC32(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_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;
|
||||
@ -224,110 +166,83 @@ static void mut_fillG(Mut* m, usz ms, B x, usz l) { // doesn't consume x
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// mut_copy but x is guaranteed to be a subtype of m
|
||||
static 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, format_type(xt), xs, xs+l); fflush(stdout);
|
||||
u8 xt = v(x)->type;
|
||||
switch(m->type) { default: UD;
|
||||
case el_i8: { i8* rp = m->ai8+ms; 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_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_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_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_f64: {
|
||||
f64* rp = m->af64+ms;
|
||||
switch (xt) { default: UD;
|
||||
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_B: {
|
||||
B* mpo = m->aB+ms;
|
||||
B* xp;
|
||||
if (xt==t_harr) xp = harr_ptr(x);
|
||||
else if (xt==t_hslice) xp = c(HSlice,x)->a;
|
||||
else if (xt==t_fillarr) xp = c(FillArr,x)->a;
|
||||
else {
|
||||
BS2B xget = TIi(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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) { // TODO try harder to not bump type
|
||||
assert(isArr(x));
|
||||
u8 xt = v(x)->type;
|
||||
u8 xe = TIi(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:
|
||||
switch(m->type) { default: UD;
|
||||
case el_MAX: goto change;
|
||||
|
||||
case el_i32: {
|
||||
if (RARE(xt!=t_i32arr & xt!=t_i32slice)) goto change;
|
||||
i32* xp = i32any_ptr(x);
|
||||
memcpy(m->ai32+ms, xp+xs, l*4);
|
||||
return;
|
||||
}
|
||||
case el_c32: {
|
||||
if (RARE(xt!=t_c32arr & xt!=t_c32slice)) goto change;
|
||||
u32* xp = c32any_ptr(x);
|
||||
memcpy(m->ac32+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 if (LIKELY(xt==t_i32arr|xt==t_i32slice)) {
|
||||
i32* xp = i32any_ptr(x);
|
||||
f64* rp = m->af64+ms;
|
||||
for (usz i = 0; i < l; i++) rp[i] = xp[i+xs];
|
||||
return;
|
||||
}
|
||||
else goto change;
|
||||
memcpy(m->af64+ms, xp+xs, l*8);
|
||||
return;
|
||||
}
|
||||
case el_B: {
|
||||
B* mpo = m->aB+ms;
|
||||
B* xp;
|
||||
if (xt==t_harr) xp = harr_ptr(x);
|
||||
else if (xt==t_hslice) xp = c(HSlice,x)->a;
|
||||
else if (xt==t_fillarr) xp = c(FillArr,x)->a;
|
||||
else {
|
||||
BS2B xget = TIi(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;
|
||||
}
|
||||
}
|
||||
change:
|
||||
mut_to(m, el_or(m->type, xe));
|
||||
goto again;
|
||||
}
|
||||
static void mut_copyG(Mut* m, usz ms, B x, usz xs, usz l) { // mut_copy but x is guaranteed to be a subtype of m
|
||||
assert(isArr(x));
|
||||
u8 xt = v(x)->type;
|
||||
switch(m->type) { default: UD;
|
||||
case el_i32: {
|
||||
i32* xp = i32any_ptr(x);
|
||||
memcpy(m->ai32+ms, xp+xs, l*4);
|
||||
return;
|
||||
}
|
||||
case el_c32: {
|
||||
u32* xp = c32any_ptr(x);
|
||||
memcpy(m->ac32+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 {
|
||||
assert(TIi(xt,elType)==el_i32);
|
||||
i32* xp = i32any_ptr(x);
|
||||
f64* rp = m->af64+ms;
|
||||
for (usz i = 0; i < l; i++) rp[i] = xp[i+xs];
|
||||
return;
|
||||
}
|
||||
memcpy(m->af64+ms, xp+xs, l*8);
|
||||
return;
|
||||
}
|
||||
case el_B: {
|
||||
B* mpo = m->aB+ms;
|
||||
B* xp;
|
||||
if (xt==t_harr) xp = harr_ptr(x);
|
||||
else if (xt==t_hslice) xp = c(HSlice,x)->a;
|
||||
else if (xt==t_fillarr) xp = c(FillArr,x)->a;
|
||||
else {
|
||||
BS2B xget = TIi(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;
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static B vec_join(B w, B x) { // consumes both
|
||||
usz wia = a(w)->ia;
|
||||
usz xia = a(x)->ia;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user