more typed ⌾(list⊸⊏)

This commit is contained in:
dzaima 2023-12-19 17:41:17 +02:00
parent 17c575edba
commit f0c1962596
8 changed files with 150 additions and 142 deletions

View File

@ -369,7 +369,8 @@ B select_c2(B t, B w, B x) {
B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xia) { // rep⌾(w⊏⥊) x
extern u8 reuseElType[t_COUNT];
B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xia) { // rep⌾(w⊏⥊) x, assumes w is a typed (elNum) list of valid indices, only el_f64 if strictly necessary
#if CHECK_VALID
TALLOC(bool, set, xia);
bool sparse = wia < xia/64;
@ -380,126 +381,103 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xia) { // rep⌾(w⊏⥊
}
#define EQ(F) if (set[cw] && (F)) thrF("𝔽⌾(a⊸%c): Incompatible result elements", chr); set[cw] = true;
#define FREE_CHECK TFREE(set)
SLOWIF(xia>100 && wia<xia/20) SLOW2("⌾(𝕨⊸⊏)𝕩 or ⌾(𝕨⊸⊑)𝕩 because CHECK_VALID", w, x);
#else
#define SPARSE_INIT(GET)
#define EQ(F)
#define FREE_CHECK
#endif
u8 we = TI(w,elType);
#define READ_W(N,I) i64 N = (i64)wp[I]; if (RARE(N<0)) N+= (i64)xia
u8 we = TI(w,elType); assert(elNum(we));
u8 xe = TI(x,elType);
u8 re = TI(rep,elType);
SLOWIF(!reusable(x) && xia>100 && wia<xia/50) SLOW2("⌾(𝕨⊸⊏)𝕩 or ⌾(𝕨⊸⊑)𝕩 because not reusable", w, x);
if (elInt(we)) {
w = toI32Any(w);
i32* wp = i32any_ptr(w);
SPARSE_INIT(wp[i])
if (elNum(re) && elNum(xe)) {
u8 me = xe>re?xe:re;
bool reuse = reusable(x);
if (me==el_i32) {
I32Arr* xn = reuse? toI32Arr(REUSE(x)) : (I32Arr*)cpyI32Arr(x);
i32* xp = i32arrv_ptr(xn);
rep = toI32Any(rep); i32* rp = i32any_ptr(rep);
for (usz i = 0; i < wia; i++) {
i64 cw = wp[i]; if (RARE(cw<0)) cw+= (i64)xia; // we're free to assume w is valid
i32 cr = rp[i];
EQ(cr != xp[cw]);
xp[cw] = cr;
}
decG(w); decG(rep); FREE_CHECK; return taga(xn);
} else if (me==el_i8) {
I8Arr* xn = reuse? toI8Arr(REUSE(x)) : (I8Arr*)cpyI8Arr(x);
i8* xp = i8arrv_ptr(xn);
rep = toI8Any(rep); i8* rp = i8any_ptr(rep);
for (usz i = 0; i < wia; i++) {
i64 cw = wp[i]; if (RARE(cw<0)) cw+= (i64)xia;
i8 cr = rp[i];
EQ(cr != xp[cw]);
xp[cw] = cr;
}
decG(w); decG(rep); FREE_CHECK; return taga(xn);
} else if (me==el_i16) {
I16Arr* xn = reuse? toI16Arr(REUSE(x)) : (I16Arr*)cpyI16Arr(x);
i16* xp = i16arrv_ptr(xn);
rep = toI16Any(rep); i16* rp = i16any_ptr(rep);
for (usz i = 0; i < wia; i++) {
i64 cw = wp[i]; if (RARE(cw<0)) cw+= (i64)xia;
i16 cr = rp[i];
EQ(cr != xp[cw]);
xp[cw] = cr;
}
decG(w); decG(rep); FREE_CHECK; return taga(xn);
} else if (me==el_bit) {
BitArr* xn = reuse? toBitArr(REUSE(x)) : (BitArr*)cpyBitArr(x);
u64* xp = bitarrv_ptr(xn);
rep = taga(toBitArr(rep)); u64* rp = bitarr_ptr(rep);
for (usz i = 0; i < wia; i++) {
i64 cw = wp[i]; if (RARE(cw<0)) cw+= (i64)xia;
bool cr = bitp_get(rp, i);
EQ(cr != bitp_get(xp,cw));
bitp_set(xp,cw,cr);
}
decG(w); decG(rep); FREE_CHECK; return taga(xn);
} else if (me==el_f64) {
F64Arr* xn = reuse? toF64Arr(REUSE(x)) : (F64Arr*)cpyF64Arr(x);
f64* xp = f64arrv_ptr(xn);
rep = toF64Any(rep); f64* rp = f64any_ptr(rep);
for (usz i = 0; i < wia; i++) {
i64 cw = wp[i]; if (RARE(cw<0)) cw+= (i64)xia;
f64 cr = rp[i];
EQ(cr != xp[cw]);
xp[cw] = cr;
}
decG(w); decG(rep); FREE_CHECK; return taga(xn);
} else UD;
}
if (reusable(x) && xe==re) {
if (TY(x)==t_harr) {
B* xp = harr_ptr(REUSE(x));
SGet(rep)
for (usz i = 0; i < wia; i++) {
i64 cw = wp[i]; if (RARE(cw<0)) cw+= (i64)xia;
B cr = Get(rep, i);
EQ(!equal(cr,xp[cw]));
dec(xp[cw]);
xp[cw] = cr;
}
decG(w); decG(rep); FREE_CHECK;
return x;
}
}
MAKE_MUT_INIT(r, xia, el_or(xe, re));
MUTG_INIT(r);
mut_copyG(r, 0, x, 0, xia);
u8 re = el_or(xe, TI(rep,elType));
Arr* ra;
// w = taga(cpyF64Arr(w)); we = el_f64; // test the float path
if (we==el_f64) {
f64* wp = f64any_ptr(w);
SPARSE_INIT((i64)wp[i])
MAKE_MUT(r, xia);
mut_init_copy(r, x, re);
NOGC_E;
SGet(rep)
MUTG_INIT(r); SGet(rep)
for (usz i = 0; i < wia; i++) {
i64 cw = wp[i]; if (RARE(cw<0)) cw+= (i64)xia;
B cr = Get(rep, i);
EQ(!equal(mut_getU(r, cw), cr));
READ_W(cw, i);
B cn = Get(rep, i);
EQ(!equal(mut_getU(r, cw), cn));
mut_rm(r, cw);
mut_setG(r, cw, cr);
mut_setG(r, cw, cn);
}
decG(w); decG(rep); FREE_CHECK;
return mut_fcd(r, x);
ra = mut_fp(r);
goto dec_ret_ra;
}
MAKE_MUT_INIT(r, xia, el_or(xe, re));
MUTG_INIT(r);
mut_copyG(r, 0, x, 0, xia);
NOGC_E;
SGet(rep) SGetU(w)
SPARSE_INIT(o2i64G(GetU(w, i)))
for (usz i = 0; i < wia; i++) {
i64 cw = o2i64G(GetU(w, i)); if (RARE(cw<0)) cw+= (i64)xia;
B cr = Get(rep, i);
EQ(!equal(mut_getU(r, cw), cr));
mut_rm(r, cw);
mut_setG(r, cw, cr);
assert(elInt(we));
w = toI32Any(w);
i32* wp = i32any_ptr(w);
SPARSE_INIT(wp[i])
bool reuse = reusable(x) && re==reuseElType[TY(x)];
SLOWIF(!reuse && xia>100 && wia<xia/50) SLOW2("⌾(𝕨⊸⊏)𝕩 or ⌾(𝕨⊸⊑)𝕩 because not reusable", w, x);
switch (re) { default: UD;
case el_i8: rep = toI8Any(rep); ra = reuse? a(REUSE(x)) : cpyI8Arr(x); goto do_u8;
case el_c8: rep = toC8Any(rep); ra = reuse? a(REUSE(x)) : cpyC8Arr(x); goto do_u8;
case el_i16: rep = toI16Any(rep); ra = reuse? a(REUSE(x)) : cpyI16Arr(x); goto do_u16;
case el_c16: rep = toC16Any(rep); ra = reuse? a(REUSE(x)) : cpyC16Arr(x); goto do_u16;
case el_i32: rep = toI32Any(rep); ra = reuse? a(REUSE(x)) : cpyI32Arr(x); goto do_u32;
case el_c32: rep = toC32Any(rep); ra = reuse? a(REUSE(x)) : cpyC32Arr(x); goto do_u32;
case el_f64: rep = toF64Any(rep); ra = reuse? a(REUSE(x)) : cpyF64Arr(x); goto do_u64;
case el_bit: { ra = reuse? a(REUSE(x)) : cpyBitArr(x);
TyArr* na = toBitArr(rep); rep = taga(na);
u64* np = bitarrv_ptr(na);
u64* rp = (void*)((TyArr*)ra)->a;
for (usz i = 0; i < wia; i++) {
READ_W(cw, i);
bool cn = bitp_get(np, i);
EQ(cn != bitp_get(rp, cw));
bitp_set(rp, cw, cn);
}
goto dec_ret_ra;
}
case el_B: {
ra = reuse? a(REUSE(x)) : cpyHArr(x);
B* rp = harrP_parts((HArr*)ra).a;
SGet(rep)
for (usz i = 0; i < wia; i++) {
READ_W(cw, i);
B cn = Get(rep, i);
EQ(!equal(cn,rp[cw]));
dec(rp[cw]);
rp[cw] = cn;
}
goto dec_ret_ra;
}
}
decG(w); decG(rep); FREE_CHECK;
return mut_fcd(r, x);
#define IMPL(T) do { \
T* rp = (void*)((TyArr*)ra)->a; \
T* np = tyany_ptr(rep); \
for (usz i = 0; i < wia; i++) { \
READ_W(cw, i); \
T cn = np[i]; \
EQ(cn != rp[cw]); \
rp[cw] = cn; \
} \
goto dec_ret_ra; \
} while(0)
do_u8: IMPL(u8);
do_u16: IMPL(u16);
do_u32: IMPL(u32);
do_u64: IMPL(u64);
#undef IMPL
dec_ret_ra:;
decG(w); decG(rep);
FREE_CHECK;
return taga(ra);
#undef SPARSE_INIT
#undef EQ
#undef FREE_CHECK

View File

@ -382,7 +382,7 @@ static B recPick(B w, B x) { // doesn't consume
if (isAtm(c)) thrM("⊑: 𝕨 contained list with mixed-type elements");
HARR_ADD(r, i, recPick(c, x));
}
return HARR_FC(r, w);
return any_squeeze(HARR_FC(r, w));
}
}
}
@ -1322,7 +1322,7 @@ B pick_ucw(B t, B o, B w, B x) {
if (RARE(c==USZ_MAX)) { mut_pfree(r, i); goto def; }
mut_setG(r, i, m_usz(c));
}
w = mut_fcd(r, w);
w = num_squeeze(mut_fcd(r, w));
B rep = isArr(o)? incG(o) : c1(o, C2(select, incG(w), C1(shape, incG(x))));
if (isAtm(rep) || !eqShape(w, rep)) thrF("𝔽⌾(a⊸⊑)𝕩: 𝔽 must return an array with the same shape as its input (expected %H, got %H)", w, rep);
return select_replace(U'', w, x, rep, wia, xia);

View File

@ -1010,6 +1010,16 @@ B slash_ucw(B t, B o, B w, B x) {
if (wb && re!=el_B) {
u64* d = bitarr_ptr(w);
void* rp = r->a;
switch (re) { default: UD;
case el_bit:
case el_i8: x = toI8Any(x); rep = toI8Any(rep); goto bit_u8;
case el_c8: x = toC8Any(x); rep = toC8Any(rep); goto bit_u8;
case el_i16: x = toI16Any(x); rep = toI16Any(rep); goto bit_u16;
case el_c16: x = toC16Any(x); rep = toC16Any(rep); goto bit_u16;
case el_i32: x = toI32Any(x); rep = toI32Any(rep); goto bit_u32;
case el_c32: x = toC32Any(x); rep = toC32Any(rep); goto bit_u32;
case el_f64: x = toF64Any(x); rep = toF64Any(rep); goto bit_u64;
}
#define IMPL(T) do { \
T* xp = tyany_ptr(x); \
@ -1022,24 +1032,12 @@ B slash_ucw(B t, B o, B w, B x) {
goto dec_ret; \
} while(0)
#define WIDEN_GO(UT, T, B) x = to##UT##Any(x); rep = to##UT##Any(rep); goto bit_##B
switch (re) {
case el_bit:
case el_i8: x = toI8Any(x); rep = toI8Any(rep); goto bit_u8;
case el_c8: x = toC8Any(x); rep = toC8Any(rep); goto bit_u8;
case el_i16: x = toI16Any(x); rep = toI16Any(rep); goto bit_u16;
case el_c16: x = toC16Any(x); rep = toC16Any(rep); goto bit_u16;
case el_i32: x = toI32Any(x); rep = toI32Any(rep); goto bit_u32;
case el_c32: x = toC32Any(x); rep = toC32Any(rep); goto bit_u32;
case el_f64: x = toF64Any(x); rep = toF64Any(rep); goto bit_u64;
}
bit_u8: IMPL(u8);
bit_u16: IMPL(u16);
bit_u32: IMPL(u32);
bit_u64: IMPL(u64);
#undef IMPL
#undef WIDEN_GO
} else {
SGet(x) SGet(rep) MUTG_INIT(r);
if (wb) {

View File

@ -2,9 +2,9 @@
#include "mut.h"
typedef struct { Arr* arr; void* els; } MadeArr;
FORCE_INLINE MadeArr mut_make_arr(usz ia, u8 type, u8 n) {
FORCE_INLINE MadeArr mut_make_arr(usz ia, u8 type, u8 el) {
u64 sz;
switch(n) { default: UD;
switch(el) { default: UD;
case el_bit: sz = BITARR_SZ( ia); break;
case el_i8: case el_c8: sz = TYARR_SZ(I8, ia); break;
case el_i16: case el_c16: sz = TYARR_SZ(I16,ia); break;
@ -18,9 +18,9 @@ FORCE_INLINE MadeArr mut_make_arr(usz ia, u8 type, u8 n) {
return (MadeArr){a, ((TyArr*)a)->a};
}
FORCE_INLINE void mut_init(Mut* m, u8 n) {
m->fns = &mutFns[n];
MadeArr a = mut_make_arr(m->ia, m->fns->valType, n);
FORCE_INLINE void mut_init(Mut* m, u8 el) {
m->fns = &mutFns[el];
MadeArr a = mut_make_arr(m->ia, m->fns->valType, el);
m->val = a.arr;
m->a = a.els;
}
@ -39,6 +39,25 @@ NOINLINE Mut make_mut_init(ux ia, u8 el) {
}
#endif
static void* arr_ptr(Arr* t, u8 el) {
return el==el_B? (void*)((HArr*)t)->a : (void*)((TyArr*)t)->a;
}
u8 reuseElType[t_COUNT];
void mut_init_copy(Mut* m, B x, u8 el) {
assert(m->fns == &mutFns[el_MAX]);
if (reusable(x) && reuseElType[TY(x)]==el) {
m->fns = &mutFns[el];
Arr* a = m->val = a(REUSE(x));
m->a = arr_ptr(a, el);
} else {
mut_to(m, el);
mut_copy(m, 0, x, 0, IA(x));
arr_shCopy(m->val, x);
decG(x);
}
}
static Arr* (*cpyFns[])(B) = {
[el_bit] = cpyBitArr,
[el_i8] = cpyI8Arr, [el_c8] = cpyC8Arr,
@ -67,7 +86,7 @@ NOINLINE void mut_to(Mut* m, u8 n) {
#endif
Arr* t = cpyFns[n](taga(m->val));
m->val = t;
m->a = n==el_B? (void*)((HArr*)t)->a : (void*)((TyArr*)t)->a;
m->a = arr_ptr(t, n);
}
}
@ -703,15 +722,17 @@ void mutF_init(void) {
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;
for (ux i = 0; i < t_COUNT; i++) reuseElType[i] = el_MAX;
mutFns[el_bit].elType = el_bit; mutFns[el_bit].valType = t_bitarr; reuseElType[t_bitarr] = el_bit;
mutFns[el_i8 ].elType = el_i8 ; mutFns[el_i8 ].valType = t_i8arr; reuseElType[t_i8arr] = el_i8;
mutFns[el_i16].elType = el_i16; mutFns[el_i16].valType = t_i16arr; reuseElType[t_i16arr] = el_i16;
mutFns[el_i32].elType = el_i32; mutFns[el_i32].valType = t_i32arr; reuseElType[t_i32arr] = el_i32;
mutFns[el_c8 ].elType = el_c8 ; mutFns[el_c8 ].valType = t_c8arr; reuseElType[t_c8arr] = el_c8;
mutFns[el_c16].elType = el_c16; mutFns[el_c16].valType = t_c16arr; reuseElType[t_c16arr] = el_c16;
mutFns[el_c32].elType = el_c32; mutFns[el_c32].valType = t_c32arr; reuseElType[t_c32arr] = el_c32;
mutFns[el_f64].elType = el_f64; mutFns[el_f64].valType = t_f64arr; reuseElType[t_f64arr] = el_f64;
mutFns[el_B ].elType = el_B ; mutFns[el_B ].valType = t_harr; reuseElType[t_harr] = el_B;
mutFns[el_MAX].elType = el_MAX; mutFns[el_MAX].valType = t_COUNT;
for (u8 i = 0; i < el_MAX; i++) copyFns[i] = mutFns[i].m_copyG;
for (u8 i = 0; i < el_MAX; i++) fillFns[i] = mutFns[i].m_fillG;

View File

@ -43,6 +43,7 @@ void mut_to(Mut* m, u8 n);
#define MAKE_MUT_INIT(N, IA, EL) Mut N##_val = make_mut_init(IA, EL); Mut* N = &N##_val;
#endif
#define MAKE_MUT(N, IA) Mut N##_val; N##_val.fns = &mutFns[el_MAX]; N##_val.ia = (IA); Mut* N = &N##_val;
void mut_init_copy(Mut* m, B x, u8 el); // consumes x; initialize m to to a type-el array, copying in all elements of x; assumes el fits x; expects no further changes to type & to be completed with mut_fp, at which point it returns an array of the same shape as x
static B mut_fv(Mut* m) { assert(m->fns->elType!=el_MAX);
NOGC_E; assert(m->ia == m->val->ia);

View File

@ -30,7 +30,9 @@
%USE fastone a5+1e6 n{𝕊: a 1+}_fastone 4 ! (10a) (5+n)6+9
# in-place ⌾(l⊸⊏)
%USE fastone a5+1e6 n{𝕊: a 1+(133¯1)}_fastone 4 ! (5678910000001000001100000210000031000004+0n0n00000n) (5a)¯5a #%NDEBUG
%USE fastone a¨5+1e6 n{𝕊: a 1+(133¯1)}_fastone 4 ! (¨5678910000001000001100000210000031000004+0n0n00000n) (5a)¯5a #%NDEBUG
%USE fastone a5+1e6 n{𝕊: a 1+(133¯1)}_fastone 4 ! ( 5678910000001000001100000210000031000004+0n0n00000n) (5a)¯5a #%NDEBUG
%USE fastone a5+1e6@+10000 n{𝕊: a 1+(133¯1)}_fastone 4 ! (@+567891000010001100021000310004 +0n0n00000n) (5a)¯5a #%NDEBUG
# in-place ∾⟜atom & ∾⟜list
%USE fastone %USE tvar2 {𝕊v: j<(×) v {a𝕩 n{𝕊: aj}_fastone 4 !( n +𝕩)a !av¨a}_tvar2_"f" 1e6 <𝕩}¨ 1, 12, 'a'

View File

@ -1,3 +1,6 @@
%DEF var V•internal.Variation LV•internal.ListVariations CLR•internal.ClearRefs
%DEF tvar %USE var _tvar {F _𝕣 x: (CLR@) {F 𝕩 V x}¨ LV 𝕩; w F _𝕣 x: (CLR@) (LV 𝕨) {(𝕨 V w) F 𝕩 V x} LV 𝕩}
%DEF evar %USE tvar _evar {ok{} r𝕨 ok𝔽{𝕊: •CurrentError@} _tvar 𝕩 {okr? !"TEST FAIL: variation didn't error"; ("TEST FAIL: varying error messages" ! 1=)r !r}}
# ¨ & ˘
# !% ⊢⌾(⊢¨) 4 # TODO enable
# !% ⊢⌾(⊢˘) 4 # TODO enable
@ -30,16 +33,21 @@ a←10‿10‿10⥊↕1000 ⋄ ! a ≡ a⌾((↕≢a)⊸⊑) a
# ⊏
n500 an i(-n)+2×n r(2×n)a ! (a) r(i) a
!"𝔽⌾(a⊸⊏)𝕩: Indexing out-of-bounds (¯11∊a, ⟨10⟩≡≢𝕩)" % 12(5¯11) 10
!"𝔽⌾(a⊸⊏)𝕩: Indexing out-of-bounds (10∊a, ⟨10⟩≡≢𝕩)" % 12(910) 10
!"𝔽⌾(a⊸⊏)𝕩: Indexing out-of-bounds (¯11∊a, ⟨10⟩≡≢𝕩)" % %USE evar 5¯11 {01(𝕨)𝕩}_evar 10101
!"𝔽⌾(a⊸⊏)𝕩: Indexing out-of-bounds (10∊a, ⟨10⟩≡≢𝕩)" % %USE evar 910 {01(𝕨)𝕩}_evar 10101
!"𝔽⌾(a⊸⊏)𝕩: Indexing out-of-bounds (10∊a, ⟨10⟩≡≢𝕩)" % %USE evar "ab" {𝕨(910)𝕩}_evar 10"foo"
100+(124) <¨10 %% <¨ 0101102310456789
100+(124) <¨10 %% <¨ 0101102310456789
100+(124) 10 %% 0101102310456789
100+¨(124) 10 %% 0101102310456789
100+(12¯4) <¨10 %% <¨ 0101102345106789
100+(12¯4) 10 %% 0101102345106789
10+(12) 0a4, a %% 011123,0123
%USE tvar !¨ 0011 {𝕨(1245) 𝕩} _tvar 101010110 %% 100011110
!"𝔽⌾(a⊸⊏): Incompatible result elements" % 34(11) 10
!"𝔽⌾(a⊸⊏): Incompatible result elements" % 34(1¯9) 10
!"𝔽⌾(a⊸⊏): Incompatible result elements" % %USE evar 34 {𝕨(1¯9) 𝕩}_evar 10
!"𝔽⌾(a⊸⊏): Incompatible result elements" % %USE evar "ab" {𝕨(1¯9) 𝕩}_evar 'a'+10
!"𝔽⌾(a⊸⊏): Incompatible result elements" % 345(112) 10
!"𝔽⌾(a⊸⊏): Incompatible result elements" % 345(112) <¨10
!"𝔽⌾(a⊸⊏): Incompatible result elements" % 345(112) a<¨10 •internal.Keep a

View File

@ -175,7 +175,7 @@ Run ← { 𝕊 testname:
}{currLn(𝕩).ln 1𝕩}¨ toRun
{𝕊:
resdesc ({@𝕩? 0; ¬(@+10)𝕩}¨ results)/¨ resultstoRun
resdesc ({@𝕩? 0; (¬(@+10)𝕩) ¬´"TEST FAIL"𝕩}¨ results)/¨ resultstoRun
0res?
•Out "Update ", •Reprres, " entr", (1<res)"y""ies", " in ", filename, "?"
{