unify ⌾(a⊸⊏) typed array paths, fix csz==0

This commit is contained in:
dzaima 2024-05-20 01:03:45 +03:00
parent 60a28a40ca
commit 52fb05fcd4
2 changed files with 52 additions and 42 deletions

View File

@ -372,14 +372,15 @@ B select_c2(B t, B w, B x) {
extern INIT_GLOBAL u8 reuseElType[t_COUNT];
B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xl, usz xcsz) { // rep⌾(w⊏xl‿xcsz⥊⊢) x, assumes w is a typed (elNum) list of valid indices, only el_f64 if strictly necessary
B select_replace(u32 chr, B w, B x, B rep, usz wia, usz cam, usz csz) { // consumes all; (⥊rep)⌾(⥊w⊏cam‿csz⥊⊢) x; assumes csz>0, that w is a typed (elNum) list of valid indices (squeeze already attempted on el_f64), and that rep has the proper element count
assert(csz > 0);
#if CHECK_VALID
TALLOC(bool, set, xl);
bool sparse = wia < xl/64;
if (!sparse) for (i64 i = 0; i < xl; i++) set[i] = false;
TALLOC(bool, set, cam);
bool sparse = wia < cam/64;
if (!sparse) for (i64 i = 0; i < cam; i++) set[i] = false;
#define SPARSE_INIT(WI) \
if (sparse) for (usz i = 0; i < wia; i++) { \
i64 cw = WI; if (RARE(cw<0)) cw+= (i64)xl; set[cw] = false; \
i64 cw = WI; if (RARE(cw<0)) cw+= (i64)cam; set[cw] = false; \
}
#define EQ(ITER,F) if (set[cw]) ITER if (F) thrF("𝔽⌾(a⊸%c): Incompatible result elements", chr); set[cw] = true;
#define EQ1(F) EQ(,F)
@ -391,7 +392,7 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xl, usz xcsz) { // rep
#define FREE_CHECK
#endif
#define READ_W(N,I) i64 N = (i64)wp[I]; if (RARE(N<0)) N+= (i64)xl
#define READ_W(N,I) i64 N = (i64)wp[I]; if (RARE(N<0)) N+= (i64)cam
u8 we = TI(w,elType); assert(elNum(we));
u8 xe = TI(x,elType);
u8 re = el_or(xe, TI(rep,elType));
@ -401,11 +402,11 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xl, usz xcsz) { // rep
f64* wp = f64any_ptr(w);
SPARSE_INIT((i64)wp[i])
MAKE_MUT(r, xl*xcsz);
MAKE_MUT(r, cam*csz);
mut_init_copy(r, x, re);
NOGC_E;
MUTG_INIT(r); SGet(rep)
if (xcsz==1) {
if (csz==1) {
for (usz i = 0; i < wia; i++) {
READ_W(cw, i);
B cn = Get(rep, i);
@ -416,9 +417,9 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xl, usz xcsz) { // rep
} else {
for (usz i = 0; i < wia; i++) {
READ_W(cw, i);
EQ(for (usz j = 0; j < xcsz; j++),!equal(mut_getU(r, cw*xcsz + j), Get(rep, i*xcsz + j)));
for (usz j = 0; j < xcsz; j++) mut_rm(r, cw*xcsz + j);
mut_copyG(r, cw*xcsz, rep, i*xcsz, xcsz);
EQ(for (usz j = 0; j < csz; j++), !equal(mut_getU(r, cw*csz + j), Get(rep, i*csz + j)));
for (usz j = 0; j < csz; j++) mut_rm(r, cw*csz + j);
mut_copyG(r, cw*csz, rep, i*csz, csz);
}
}
ra = mut_fp(r);
@ -430,7 +431,7 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xl, usz xcsz) { // rep
i32* wp = i32any_ptr(w);
SPARSE_INIT(wp[i])
bool reuse = reusable(x) && re==reuseElType[TY(x)];
SLOWIF(!reuse && xl>100 && wia<xl/50) SLOW2("⌾(𝕨⊸⊏)𝕩 or ⌾(𝕨⊸⊑)𝕩 because not reusable", w, x);
SLOWIF(!reuse && cam>100 && wia<cam/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;
@ -443,7 +444,7 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xl, usz xcsz) { // rep
TyArr* na = toBitArr(rep); rep = taga(na);
u64* np = bitarrv_ptr(na);
u64* rp = (void*)((TyArr*)ra)->a;
if (xcsz==1) {
if (csz==1) {
for (usz i = 0; i < wia; i++) {
READ_W(cw, i);
bool cn = bitp_get(np, i);
@ -453,8 +454,8 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xl, usz xcsz) { // rep
} else {
for (usz i = 0; i < wia; i++) {
READ_W(cw, i);
EQ(for (usz j = 0; j < xcsz; j++), bitp_get(np, i*xcsz + j) != bitp_get(rp, cw*xcsz + j));
COPY_TO(rp, el_bit, cw*xcsz, rep, i*xcsz, xcsz);
EQ(for (usz j = 0; j < csz; j++), bitp_get(np, i*csz + j) != bitp_get(rp, cw*csz + j));
COPY_TO(rp, el_bit, cw*csz, rep, i*csz, csz);
}
}
goto dec_ret_ra;
@ -463,8 +464,7 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xl, usz xcsz) { // rep
ra = reuse? a(REUSE(x)) : cpyHArr(x);
B* rp = harrP_parts((HArr*)ra).a;
SGet(rep)
if (xcsz==1)
{
if (csz==1) {
for (usz i = 0; i < wia; i++) {
READ_W(cw, i);
B cn = Get(rep, i);
@ -475,34 +475,26 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xl, usz xcsz) { // rep
} else {
for (usz i = 0; i < wia; i++) {
READ_W(cw, i);
EQ(for (usz j = 0; j < xcsz; j++), !equal(Get(rep, i*xcsz + j), rp[cw*xcsz + j]));
for (usz j = 0; j < xcsz; j++) dec(rp[cw*xcsz + j]);
COPY_TO(rp, el_B, cw*xcsz, rep, i*xcsz, xcsz);
EQ(for (usz j = 0; j < csz; j++), !equal(Get(rep, i*csz + j), rp[cw*csz + j]));
for (usz j = 0; j < csz; j++) dec(rp[cw*csz + j]);
COPY_TO(rp, el_B, cw*csz, rep, i*csz, csz);
}
}
goto dec_ret_ra;
}
}
#define IMPL(T) do { \
T* rp = (void*)((TyArr*)ra)->a; \
T* np = tyany_ptr(rep); \
if (xcsz==1) { \
for (usz i = 0; i < wia; i++) { \
READ_W(cw, i); \
T cn = np[i]; \
EQ1(cn != rp[cw]); \
rp[cw] = cn; \
} \
} else { \
EqFnObj eq = EQFN_GET(re,re); \
for (usz i = 0; i < wia; i++) { \
READ_W(cw, i); \
EQ1(!EQFN_CALL(eq, rp+cw*xcsz, np+i*xcsz, xcsz)); \
COPY_TO(rp, re, cw*xcsz, rep, i*xcsz, xcsz); \
} \
} \
goto dec_ret_ra; \
#define IMPL(T) do { \
if (csz!=1) goto do_tycell; \
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]; \
EQ1(cn != rp[cw]); \
rp[cw] = cn; \
} \
goto dec_ret_ra; \
} while(0)
do_u8: IMPL(u8);
@ -511,6 +503,18 @@ B select_replace(u32 chr, B w, B x, B rep, usz wia, usz xl, usz xcsz) { // rep
do_u64: IMPL(u64);
#undef IMPL
do_tycell:;
u8 cwidth = csz * elWidth(re);
u8* rp = (u8*) ((TyArr*)ra)->a;
u8* np = tyany_ptr(rep);
EqFnObj eq = EQFN_GET(re,re);
for (usz i = 0; i < wia; i++) {
READ_W(cw, i);
EQ1(!EQFN_CALL(eq, rp + cw*cwidth, np + i*cwidth, csz));
COPY_TO(rp, re, cw*csz, rep, i*csz, csz);
}
goto dec_ret_ra;
dec_ret_ra:;
@ -546,5 +550,7 @@ B select_ucw(B t, B o, B w, B x) {
usz rr = RNK(rep);
bool ok = !isAtm(rep) && xr+wr==rr+1 && eqShPart(SH(w),SH(rep),wr) && eqShPart(SH(x)+1,SH(rep)+wr,xr-1);
if (!ok) thrF("𝔽⌾(a⊸⊏)𝕩: 𝔽 must return an array with the same shape as its input (%H ≡ shape of a, %2H ≡ shape of ⊏𝕩, %H ≡ shape of result of 𝔽)", w, xr-1, SH(x)+1, rep);
return select_replace(U'', w, x, rep, wia, *SH(x), arr_csz(x));
usz csz = arr_csz(x);
if (csz == 0) { decG(rep); decG(w); return x; }
return select_replace(U'', w, x, rep, wia, *SH(x), csz);
}

View File

@ -1,5 +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 eqvar %USE tvar _eqvar {r 𝕨 𝔽 _tvar 𝕩 !(r)¨ r r}
%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
@ -41,7 +42,7 @@ n←500 ⋄ a←↕n ⋄ i←(-n)+↕2×n ⋄ r←⌽(2×n)⥊a ⋄ ! (⌽a) ≡
100+(12¯4) <¨10 %% <¨ 0101102345106789
100+(12¯4) 10 %% 0101102345106789
10+(12) 0a4, a %% 011123,0123
%USE tvar !¨ 0011 {𝕨(1245) 𝕩} _tvar 101010110 %% 100011110
%USE eqvar 0011 {𝕨(1245) 𝕩} _eqvar 101010110 %% 100011110
!"𝔽⌾(a⊸⊏)𝕩: 𝔽 must return an array with the same shape as its input (⟨2⟩ ≡ shape of a, ⟨⟩ ≡ shape of ⊏𝕩, ⟨3⟩ ≡ shape of result of 𝔽)" % 102030(23) 10
!"𝔽⌾(a⊸⊏)𝕩: 𝔽 must return an array with the same shape as its input (⟨2⟩ ≡ shape of a, ⟨⟩ ≡ shape of ⊏𝕩, ⟨3⟩ ≡ shape of result of 𝔽)" % 1(23) 10
!"𝔽⌾(a⊸⊏)𝕩: 𝔽 must return an array with the same shape as its input (⟨3⟩ ≡ shape of a, ⟨10⟩ ≡ shape of ⊏𝕩, 2‿10 ≡ shape of result of 𝔽)" % %USE evar 1(234)_evar 10100
@ -55,11 +56,14 @@ n←500 ⋄ a←↕n ⋄ i←(-n)+↕2×n ⋄ r←⌽(2×n)⥊a ⋄ ! (⌽a) ≡
!"𝔽⌾(a⊸⊏): Incompatible result elements" % 34(("Ah"•internal.Variation 11)) <¨10
!"𝔽⌾(a⊸⊏): Incompatible result elements" % %USE evar (2730) {𝕨((3010)) 𝕩} _evar 1001
!"𝔽⌾(a⊸⊏): Incompatible result elements" % %USE evar !¨ {{¬(314)𝕩}•internal.Keep((10<𝕩)) 𝕩} _evar 105110011
%USE tvar !¨ {¬((10<𝕩)) 𝕩} _tvar 105110011 %% 105001100
%USE eqvar {¬((10<𝕩)) 𝕩} _eqvar 105110011 %% 105001100
2020(11) 10 %% 0202+8
100+(12¯1) 5 %% 01011023104
100+(12¯1) <¨5 %% <¨ 01011023104
1+(((10010)10/10)) 10 %% 1+10
%USE eqvar 1+((2/5)) _eqvar 10 %% <5+ 10
%USE eqvar 1+((2/5)) _eqvar ˘ 10 %% ˘ <5+ 10
%USE eqvar •internal.Keep((2/5)) _eqvar 10040 %% 10040
# ⥊