From 45207372f670baee9b73898e20af5cd8a78e0471 Mon Sep 17 00:00:00 2001 From: dzaima Date: Sun, 16 May 2021 18:16:09 +0300 Subject: [PATCH] =?UTF-8?q?native=20=E2=8C=BE(a=E2=8A=B8/)=20and=20?= =?UTF-8?q?=E2=8C=BE=E2=8A=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/derv.c | 9 ++++++++- src/fns.c | 12 +++++++++--- src/h.h | 25 ++++++++++++++++++------- src/load.c | 5 +++-- src/main.c | 3 ++- src/md2.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++------ src/mut.c | 31 ++++++++++++++++++++++++++++++- src/sfns.c | 43 ++++++++++++++++++++++++++++++++++++++++++- src/stuff.c | 34 ++++++++++++++++++++++++++++++++++ 9 files changed, 192 insertions(+), 22 deletions(-) diff --git a/src/derv.c b/src/derv.c index cc944d06..d189ed68 100644 --- a/src/derv.c +++ b/src/derv.c @@ -71,11 +71,18 @@ B m1_d(B m, B f ) { if(isMd1(m)) return TI(m).m1_d(m, f ); thrM("Interpret B m2_d(B m, B f, B g) { if(isMd2(m)) return TI(m).m2_d(m, f, g); thrM("Interpreting non-2-modifier as 2-modifier"); } B m2_h(B m, B g) { return m_md2H(m, g); } +B md2D_uc1(B t, B o, B x) { + B m = c(Md2D, t)->m2; + B f = c(Md2D, t)->f; + B g = c(Md2D, t)->g; + if (v(t)->flags || !isMd2(m)) return def_fn_uc1(t, o, x); // flags check to not deconstruct builtins + return TI(m).m2_uc1(m, o, f, g, x); +} static inline void derv_init() { ti[t_md1D].free = md1D_free; ti[t_md1D].visit = md1D_visit; ti[t_md1D].print = md1D_print; ti[t_md1D].decompose = md1D_decompose; - ti[t_md2D].free = md2D_free; ti[t_md2D].visit = md2D_visit; ti[t_md2D].print = md2D_print; ti[t_md2D].decompose = md2D_decompose; + ti[t_md2D].free = md2D_free; ti[t_md2D].visit = md2D_visit; ti[t_md2D].print = md2D_print; ti[t_md2D].decompose = md2D_decompose; ti[t_md2D].fn_uc1 = md2D_uc1; ti[t_md2H].free = md2H_free; ti[t_md2H].visit = md2H_visit; ti[t_md2H].print = md2H_print; ti[t_md2H].decompose = md2H_decompose; ti[t_fork].free = fork_free; ti[t_fork].visit = fork_visit; ti[t_fork].print = fork_print; ti[t_fork].decompose = fork_decompose; ti[t_atop].free = atop_free; ti[t_atop].visit = atop_visit; ti[t_atop].print = atop_print; ti[t_atop].decompose = atop_decompose; diff --git a/src/fns.c b/src/fns.c index 3442ce4e..eac8db05 100644 --- a/src/fns.c +++ b/src/fns.c @@ -3,9 +3,13 @@ typedef struct BFn { struct Fun; B ident; + BBB2B uc1; + BBBB2B ucw; } BFn; void print_funBI(B x) { printf("%s", format_pf(c(Fun,x)->extra)); } +B funBI_uc1(B t, B o, B x) { return c(BFn,t)->uc1(t, o, x); } +B funBI_ucw(B t, B o, B w, B x) { return c(BFn,t)->ucw(t, o, w, x); } B funBI_identity(B x) { return inc(c(BFn,x)->ident); } @@ -165,9 +169,9 @@ B fne_c2(B t, B w, B x) { } -#define BI_A(N) { B t=bi_##N = mm_alloc(sizeof(BFn), t_funBI, ftag(FUN_TAG)); BFn*f=c(BFn,t); f->c2=N##_c2 ; f->c1=N##_c1 ; f->extra=pf_##N; f->ident=bi_N; gc_add(t); } -#define BI_D(N) { B t=bi_##N = mm_alloc(sizeof(BFn), t_funBI, ftag(FUN_TAG)); BFn*f=c(BFn,t); f->c2=N##_c2 ; f->c1=c1_invalid; f->extra=pf_##N; f->ident=bi_N; gc_add(t); } -#define BI_M(N) { B t=bi_##N = mm_alloc(sizeof(BFn), t_funBI, ftag(FUN_TAG)); BFn*f=c(BFn,t); f->c2=c2_invalid; f->c1=N##_c1 ; f->extra=pf_##N; f->ident=bi_N; gc_add(t); } +#define BI_A(N) { B t=bi_##N = mm_alloc(sizeof(BFn), t_funBI, ftag(FUN_TAG)); BFn*f=c(BFn,t); f->c2=N##_c2 ; f->c1=N##_c1 ; f->extra=pf_##N; f->ident=bi_N; f->uc1=def_fn_uc1; f->ucw=def_fn_ucw; gc_add(t); } +#define BI_D(N) { B t=bi_##N = mm_alloc(sizeof(BFn), t_funBI, ftag(FUN_TAG)); BFn*f=c(BFn,t); f->c2=N##_c2 ; f->c1=c1_invalid; f->extra=pf_##N; f->ident=bi_N; f->uc1=def_fn_uc1; f->ucw=def_fn_ucw; gc_add(t); } +#define BI_M(N) { B t=bi_##N = mm_alloc(sizeof(BFn), t_funBI, ftag(FUN_TAG)); BFn*f=c(BFn,t); f->c2=c2_invalid; f->c1=N##_c1 ; f->extra=pf_##N; f->ident=bi_N; f->uc1=def_fn_uc1; f->ucw=def_fn_ucw; gc_add(t); } #define BI_VAR(N) B bi_##N; #define BI_FNS0(F) F(BI_VAR,BI_VAR,BI_VAR) #define BI_FNS1(F) F(BI_A,BI_M,BI_D) @@ -178,5 +182,7 @@ BI_FNS0(F); static inline void fns_init() { BI_FNS1(F) ti[t_funBI].print = print_funBI; ti[t_funBI].identity = funBI_identity; + ti[t_funBI].fn_uc1 = funBI_uc1; + ti[t_funBI].fn_ucw = funBI_ucw; } #undef F diff --git a/src/h.h b/src/h.h index ac34833c..779cc250 100644 --- a/src/h.h +++ b/src/h.h @@ -156,13 +156,13 @@ char* format_pm1(u8 u) { } enum PrimMd2 { pm2_none, - pm2_val, pm2_atop, pm2_over, pm2_before, pm2_after, pm2_cond, pm2_repeat, pm2_fillBy, pm2_catch, // md2.c + pm2_val, pm2_atop, pm2_over, pm2_before, pm2_after, pm2_cond, pm2_repeat, pm2_fillBy, pm2_catch, pm2_under, // md2.c }; char* format_pm2(u8 u) { switch(u) { default: case pf_none: return"(unknown 1-modifier)"; case pm2_val:return"⊘"; case pm2_repeat:return"⍟"; case pm2_fillBy:return"•_fillBy_"; case pm2_catch:return"⎊"; - case pm2_atop:return"∘"; case pm2_over:return"○"; case pm2_before:return"⊸"; case pm2_after:return"⟜"; case pm2_cond:return"◶"; + case pm2_atop:return"∘"; case pm2_over:return"○"; case pm2_before:return"⊸"; case pm2_after:return"⟜"; case pm2_cond:return"◶"; case pm2_under:return"⌾"; } } @@ -411,11 +411,12 @@ B* harr_ptr(B x); typedef void (*B2v)(B); typedef B (* BS2B)(B, usz); typedef B (*BSS2B)(B, usz, usz); -typedef B (* B2B)(B); -typedef B (* BB2B)(B, B); -typedef B (* BBB2B)(B, B, B); -typedef B (* BBBB2B)(B, B, B, B); -typedef B (*BBBBB2B)(B, B, B, B, B); +typedef B (* B2B)(B); +typedef B (* BB2B)(B, B); +typedef B (* BBB2B)(B, B, B); +typedef B (* BBBB2B)(B, B, B, B); +typedef B (* BBBBB2B)(B, B, B, B, B); +typedef B (*BBBBBB2B)(B, B, B, B, B, B); typedef bool (*B2b)(B); typedef struct TypeInfo { @@ -427,6 +428,13 @@ typedef struct TypeInfo { BS2B slice; // consumes; create slice from given starting position; add ia, rank, shape yourself; may not actually be a Slice object B2B identity; // return identity element of this function; doesn't consume + BBB2B fn_uc1; // t,o, x→r; r≡O⌾( T ) x; consumes x + BBBB2B fn_ucw; // t,o, w,x→r; r≡O⌾(w⊸ T ) x; consumes w,x + BBBB2B m1_uc1; // t,o,f, x→r; r≡O⌾( F _T ) x; consumes x + BBBBB2B m1_ucw; // t,o,f, w,x→r; r≡O⌾(w⊸(F _T )) x; consumes w,x + BBBBB2B m2_uc1; // t,o,f,g, x→r; r≡O⌾( F _T_ G ) x; consumes x + BBBBBB2B m2_ucw; // t,o,f,g,w,x→r; r≡O⌾(w⊸(F _T_ G)) x; consumes w,x + B2b canStore; // doesn't consume u8 elType; @@ -496,6 +504,9 @@ B c2(B f, B w, B x) { // BQN-call f dyadically; consumes w,x if (isFun(f)) return VALIDATE(c(Fun,f)->c2(f, w, x)); return c2_rare(f, w, x); } +B m1_d(B m, B f ); +B m2_d(B m, B f, B g); +B m2_h(B m, B g); typedef struct Md1 { diff --git a/src/load.c b/src/load.c index b1d8eac3..f014b119 100644 --- a/src/load.c +++ b/src/load.c @@ -64,7 +64,7 @@ static inline void load_init() { /* ⊣⊢⥊∾≍↑↓↕«» */ bi_ltack, bi_rtack , bi_shape, bi_join , bi_couple, bi_take , bi_drop , bi_ud , bi_shifta, bi_shiftb, /* ⌽⍉/⍋⍒⊏⊑⊐⊒∊ */ bi_N , bi_N , bi_slash, bi_gradeUp, bi_N , bi_select, bi_pick , bi_N , bi_N , bi_N, /* ⍷⊔!˙˜˘¨⌜⁼´ */ bi_N , bi_group , bi_asrt , bi_const , bi_swap , bi_N , bi_each , bi_tbl , bi_N , bi_fold, - /* ˝`∘○⊸⟜⌾⊘◶⎉ */ bi_N , bi_scan , bi_atop , bi_over , bi_before, bi_after , bi_N , bi_val , bi_cond , bi_N, + /* ˝`∘○⊸⟜⌾⊘◶⎉ */ bi_N , bi_scan , bi_atop , bi_over , bi_before, bi_after , bi_under, bi_val , bi_cond , bi_N, /* ⚇⍟⎊ */ bi_N , bi_repeat, bi_catch }; bool rtComplete[] = { @@ -73,7 +73,7 @@ static inline void load_init() { /* ⊣⊢⥊∾≍↑↓↕«» */ 1,1,0,1,1,1,1,1,1,1, /* ⌽⍉/⍋⍒⊏⊑⊐⊒∊ */ 0,0,1,1,0,1,1,0,0,0, /* ⍷⊔!˙˜˘¨⌜⁼´ */ 0,1,1,1,1,0,1,1,0,1, - /* ˝`∘○⊸⟜⌾⊘◶⎉ */ 0,1,1,1,1,1,0,1,0,0, + /* ˝`∘○⊸⟜⌾⊘◶⎉ */ 0,1,1,1,1,1,1,1,0,0, /* ⚇⍟⎊ */ 0,1,1 }; assert(sizeof(fruntime)/sizeof(B) == rtLen); @@ -122,6 +122,7 @@ static inline void load_init() { rt_take = rtObjGet(rtObjRaw, 25); gc_add(rt_take); rt_drop = rtObjGet(rtObjRaw, 26); gc_add(rt_drop); rt_group = rtObjGet(rtObjRaw, 41); gc_add(rt_group); + rt_under = rtObjGet(rtObjRaw, 56); gc_add(rt_under); for (usz i = 0; i < runtimeLen; i++) { #ifdef ALL_R1 diff --git a/src/main.c b/src/main.c index 25cc7f56..7ecab218 100644 --- a/src/main.c +++ b/src/main.c @@ -13,8 +13,9 @@ // #define OBJ_COUNTER // store a unique allocation number with each object for easier analysis // #define ALL_R0 // use all of r0.bqn for runtime_0 // #define ALL_R1 // use all of r1.bqn for runtime +// #define RT_SRC // whether ./genRuntimeSrc was used to generate precompiled sources #define VM_POS false // whether to store detailed execution position information for stacktraces -#define CHECK_VALID true // whether to check for valid arguments in places where that would be detrimental to performance (e.g. left argument sortedness of ⍋/⍒) +#define CHECK_VALID true // whether to check for valid arguments in places where that would be detrimental to performance (e.g. left argument sortedness of ⍋/⍒, incompatible changes in ⌾, etc) #define EACH_FILLS false // whether to try to squeeze out fills for ¨ and ⌜ #define SFNS_FILLS true // whether to insert fills for structural functions (∾, ≍, etc) #define FAKE_RUNTIME false // whether to disable the self-hosted runtime diff --git a/src/md2.c b/src/md2.c index c9d697bf..53f0eaea 100644 --- a/src/md2.c +++ b/src/md2.c @@ -1,5 +1,14 @@ #include "h.h" +typedef struct BMd2 { + struct Md1; + BBBBB2B uc1; + BBBBBB2B ucw; +} BMd2; + +void print_md2BI(B x) { printf("%s", format_pm2(c(Md1,x)->extra)); } +B md2BI_uc1(B t, B o, B f, B g, B x) { return c(BMd2,t)->uc1(t, o, f, g, x); } +B md2BI_ucw(B t, B o, B f, B g, B w, B x) { return c(BMd2,t)->ucw(t, o, f, g, w, x); } B val_c1(B d, B x) { return c1(c(Md2D,d)->f, x); } @@ -118,15 +127,46 @@ B cond_c2(B d, B w, B x) { B g=c(Md2D,d)->g; return c2(TI(g).getU(g, fr), w, x); } -#define ba(NAME) bi_##NAME = mm_alloc(sizeof(Md2), t_md2BI, ftag(MD2_TAG)); c(Md2,bi_##NAME)->c2 = NAME##_c2; c(Md2,bi_##NAME)->c1 = NAME##_c1; c(Md2,bi_##NAME)->extra=pm2_##NAME; gc_add(bi_##NAME); -#define bd(NAME) bi_##NAME = mm_alloc(sizeof(Md2), t_md2BI, ftag(MD2_TAG)); c(Md2,bi_##NAME)->c2 = NAME##_c2; c(Md2,bi_##NAME)->c1 = c1_invalid; c(Md1,bi_##NAME)->extra=pm2_##NAME; gc_add(bi_##NAME); -#define bm(NAME) bi_##NAME = mm_alloc(sizeof(Md2), t_md2BI, ftag(MD2_TAG)); c(Md2,bi_##NAME)->c2 = c2_invalid;c(Md2,bi_##NAME)->c1 = NAME##_c1; c(Md1,bi_##NAME)->extra=pm2_##NAME; gc_add(bi_##NAME); +B rt_under, bi_before; +B under_c1(B d, B x) { B f=c(Md2D,d)->f; B g=c(Md2D,d)->g; + if (!isVal(g)) { // ugh idk + B fn = m2_d(inc(rt_under), inc(f), inc(g)); + B r = c1(fn, x); + dec(fn); + return r; + } + return TI(g).fn_uc1(g, f, x); +} +B under_c2(B d, B w, B x) { B f=c(Md2D,d)->f; B g=c(Md2D,d)->g; + if (!isVal(g)) { + B fn = m2_d(inc(rt_under), inc(f), inc(g)); + B r = c2(fn, w, x); + dec(fn); + return r; + } + B f2 = m2_d(inc(bi_before), c1(g, w), inc(f)); + B r = TI(g).fn_uc1(g, f2, x); + dec(f2); + return r; +} -void print_md2BI(B x) { printf("%s", format_pm2(c(Md1,x)->extra)); } +B before_uc1(B t, B o, B f, B g, B x) { + if (!isFun(g)) return def_m2_uc1(t, o, f, g, x); + return TI(g).fn_ucw(g, o, inc(f), x); +} -B bi_val, bi_repeat, bi_atop, bi_over, bi_before, bi_after, bi_cond, bi_fillBy, bi_catch; -static inline void md2_init() { ba(val) ba(repeat) ba(atop) ba(over) ba(before) ba(after) ba(cond) ba(fillBy) ba(catch) + +#define ba(N) { B t=bi_##N=mm_alloc(sizeof(BMd2), t_md2BI, ftag(MD2_TAG)); BMd2*m=c(BMd2,t); m->c2 = N##_c2 ; m->c1 = N##_c1; m->extra=pm2_##N; m->uc1=def_m2_uc1; m->ucw=def_m2_ucw; gc_add(t); } +#define bd(N) { B t=bi_##N=mm_alloc(sizeof(BMd2), t_md2BI, ftag(MD2_TAG)); BMd2*m=c(BMd2,t); m->c2 = N##_c2 ; m->c1 = c1_invalid; m->extra=pm2_##N; m->uc1=def_m2_uc1; m->ucw=def_m2_ucw; gc_add(t); } +#define bm(N) { B t=bi_##N=mm_alloc(sizeof(BMd2), t_md2BI, ftag(MD2_TAG)); BMd2*m=c(BMd2,t); m->c2 = c2_invalid; m->c1 = N##_c1; m->extra=pm2_##N; m->uc1=def_m2_uc1; m->ucw=def_m2_ucw; gc_add(t); } + +B bi_val, bi_repeat, bi_atop, bi_over, bi_before, bi_after, bi_cond, bi_fillBy, bi_under, bi_catch; +static inline void md2_init() { ba(val) ba(repeat) ba(atop) ba(over) ba(before) ba(after) ba(cond) ba(fillBy) ba(under) ba(catch) ti[t_md2BI].print = print_md2BI; + ti[t_md2BI].m2_uc1 = md2BI_uc1; + ti[t_md2BI].m2_ucw = md2BI_ucw; + c(BMd2,bi_before)->uc1 = before_uc1; + } #undef ba diff --git a/src/mut.c b/src/mut.c index caa92ff1..5de7331a 100644 --- a/src/mut.c +++ b/src/mut.c @@ -78,11 +78,40 @@ u8 el_or(u8 a, u8 b) { #undef M } -void mut_pfree(Mut* m, usz n) { // free the first n elements +void mut_pfree(Mut* m, usz n) { // free the first n-1 elements if (m->type==el_B) harr_pfree(tag(m->val,ARR_TAG), n); else mm_free((Value*) m->val); } +void mut_set(Mut* m, usz ms, B x) { // consumes; sets m[ms] to x + again: + #define AGAIN(T) { mut_to(m, T); goto again; } + switch(m->type) { + case el_MAX: AGAIN(isF64(x)? (q_i32(x)? el_i32 : el_f64) : (isC32(x)? el_c32 : el_B)); + + case el_i32: { + if (!q_i32(x)) AGAIN(isF64(x)? el_f64 : el_B); + m->ai32[ms] = o2iu(x); + return; + } + case el_c32: { + if (!isC32(x)) AGAIN(el_B); + m->ac32[ms] = o2cu(x); + return; + } + case el_f64: { + if (!isF64(x)) AGAIN(el_B); + m->af64[ms] = o2fu(x); + return; + } + case el_B: { + m->aB[ms] = x; + return; + } + } + #undef AGAIN +} + // doesn't consume; fills m[ms…ms+l] with x void mut_fill(Mut* m, usz ms, B x, usz l) { again: diff --git a/src/sfns.c b/src/sfns.c index 37b33ce3..5586ffbd 100644 --- a/src/sfns.c +++ b/src/sfns.c @@ -736,8 +736,49 @@ B group_c2(B t, B w, B x) { return c2(rt_group, w, x); } +B pick_uc1(B t, B o, B x) { + if (isAtm(x) || a(x)->ia==0) return def_fn_uc1(t, o, x); + usz ia = a(x)->ia; + B x0 = TI(x).get(x, 0); + B item = c1(o, x0); + MAKE_MUT(r, ia); mut_to(r, el_or(TI(x).elType, selfElType(item))); + mut_set(r, 0, item); + mut_copy(r, 1, x, 1, ia-1); + return mut_fcd(r, x); +} + +B slash_ucw(B t, B o, B w, B x) { + if (isAtm(w) || rnk(w)!=1 || rnk(x)!=1 || a(w)->ia!=a(x)->ia) return def_fn_ucw(t, o, w, x); + usz ia = a(x)->ia; + BS2B wgetU = TI(w).getU; + for (usz i = 0; i < ia; i++) { B cw=wgetU(w,i); if (!q_i32(cw)) return def_fn_ucw(t, o, w, x); } + B arg = slash_c2(t, inc(w), inc(x)); + usz argIA = a(arg)->ia; + B rep = c1(o, arg); + if (isAtm(rep) || rnk(rep)!=1 || a(rep)->ia != argIA) thrM("𝔽⌾(a⊸/)𝕩: Result of 𝔽 must have the same shape as a/𝕩"); + MAKE_MUT(r, ia); mut_to(r, el_or(TI(x).elType, TI(rep).elType)); + BS2B xget = TI(x).get; + BS2B rgetU = TI(rep).getU; + BS2B rget = TI(rep).get; + usz repI = 0; + for (usz i = 0; i < ia; i++) { + i32 cw = o2iu(wgetU(w, i)); + if (cw) { + B cr = rget(rep,repI); + if (CHECK_VALID) for (i32 j = 1; j < cw; j++) if (!equal(rgetU(rep,repI+j), cr)) { mut_pfree(r,i); thrM("𝔽⌾(a⊸/): Incompatible result elements"); } + mut_set(r, i, cr); + repI+= cw; + } else mut_set(r, i, xget(x,i)); + } + dec(w); dec(rep); + return mut_fcd(r, x); +} + #define F(A,M,D) A(shape) A(pick) A(pair) A(select) A(slash) A(join) A(couple) A(shiftb) A(shifta) A(take) A(drop) A(group) BI_FNS0(F); -static inline void sfns_init() { BI_FNS1(F) } +static inline void sfns_init() { BI_FNS1(F) + c(BFn,bi_pick)->uc1 = pick_uc1; + c(BFn,bi_slash)->ucw = slash_ucw; +} #undef F diff --git a/src/stuff.c b/src/stuff.c index 84cb186b..7105b776 100644 --- a/src/stuff.c +++ b/src/stuff.c @@ -29,6 +29,29 @@ B def_m2_d(B m, B f, B g) { thrM("cannot derive this"); } B def_slice(B x, usz s) { thrM("cannot slice non-array!"); } bool def_canStore(B x) { return false; } +B rt_under, bi_before; +B rtUnder_c1(B f, B g, B x) { // consumes x + B fn = m2_d(inc(rt_under), inc(f), inc(g)); + B r = c1(fn, x); + dec(fn); + return r; +} +B rtUnder_cw(B f, B g, B w, B x) { // consumes w,x + B fn = m2_d(inc(rt_under), inc(f), m2_d(inc(bi_before), w, inc(g))); + B r = c1(fn, x); + dec(fn); + return r; +} + + +B bi_before; +B def_fn_uc1(B t, B o, B x) { return rtUnder_c1(o, t, x); } +B def_fn_ucw(B t, B o, B w, B x) { return rtUnder_cw(o, t, w, x); } +B def_m1_uc1(B t, B o, B f, B x) { B t2 = m1_d(inc(t),inc(f) ); B r = rtUnder_c1(o, t2, x); dec(t2); return r; } +B def_m1_ucw(B t, B o, B f, B w, B x) { B t2 = m1_d(inc(t),inc(f) ); B r = rtUnder_cw(o, t2, w, x); dec(t2); return r; } +B def_m2_uc1(B t, B o, B f, B g, B x) { B t2 = m2_d(inc(t),inc(f),inc(g)); B r = rtUnder_c1(o, t2, x); dec(t2); return r; } +B def_m2_ucw(B t, B o, B f, B g, B w, B x) { B t2 = m2_d(inc(t),inc(f),inc(g)); B r = rtUnder_cw(o, t2, w, x); dec(t2); return r; } + void arr_print(B x) { // should accept refc=0 arguments for debugging purposes ur r = rnk(x); @@ -208,6 +231,11 @@ u8 fillElType(B x) { if (isC32(x)) return el_c32; return el_B; } +u8 selfElType(B x) { + if (isF64(x)) return q_i32(x)? el_i32 : el_f64; + if (isC32(x)) return el_c32; + return el_B; +} @@ -261,6 +289,12 @@ static inline void hdr_init() { ti[i].decompose = def_decompose; ti[i].slice = def_slice; ti[i].canStore = def_canStore; + ti[i].fn_uc1 = def_fn_uc1; + ti[i].fn_ucw = def_fn_ucw; + ti[i].m1_uc1 = def_m1_uc1; + ti[i].m1_ucw = def_m1_ucw; + ti[i].m2_uc1 = def_m2_uc1; + ti[i].m2_ucw = def_m2_ucw; } ti[t_empty].free = empty_free; ti[t_freed].free = def_free;