move arr⌾(m⊸/)𝕩 over to new DirectArr thing

This commit is contained in:
dzaima 2025-05-25 21:18:41 +03:00
parent 3abd77fed8
commit 454d1b072d
4 changed files with 89 additions and 51 deletions

View File

@ -1036,34 +1036,29 @@ B slash_im(B t, B x) {
extern INIT_GLOBAL BlendArrScalarFn* blendArrScalarFns; extern INIT_GLOBAL BlendArrScalarFn* blendArrScalarFns;
#endif #endif
typedef struct { B b; void* data; } AnyArr;
AnyArr cpyElTypeArr(u8 re, B x) { // consumes x; returns new array with the given element type, with data & shape from x #define BY_MASK(F, ELTS, C) ({ \
Arr* a; u64 c = (C); \
switch (re) { default: UD; B* elts_ = (ELTS); \
case el_bit: a = cpyBitArr(x); goto tyarr; while (c) { \
case el_i8: a = cpyI8Arr(x); goto tyarr; F(elts_[CTZ(c)]); \
case el_i16: a = cpyI16Arr(x); goto tyarr; c&=c-1; \
case el_i32: a = cpyI32Arr(x); goto tyarr; } \
case el_f64: a = cpyF64Arr(x); goto tyarr; })
case el_c8: a = cpyC8Arr(x); goto tyarr;
case el_c16: a = cpyC16Arr(x); goto tyarr; static void decByMask(u64* mask, B* elts, ux ia, bool inv) {
case el_c32: a = cpyC32Arr(x); goto tyarr; u64 xor = inv? U64_MAX : 0;
case el_B: ux e = ia>>6;
a = cpyHArr(x); for (ux i=0; i<e; i++) BY_MASK(dec, elts + i*64, xor^mask[i]);
return (AnyArr){taga(a), harrv_ptr(a)}; if (ia&63) BY_MASK(dec, elts + e*64, (xor^mask[e]) & ((1ULL<<(ia&63)) - 1));
} }
tyarr: static void incByMask(u64* mask, B* elts, ux ia, bool inv) {
return (AnyArr){taga(a), tyarrv_ptr((TyArr*)a)}; u64 xor = inv? U64_MAX : 0;
} ux e = ia>>6;
AnyArr m_anyarrc(u8 re, B x) { // consumes x; returns new array with given element type; may start NOGC for (ux i=0; i<e; i++) BY_MASK(inc, elts + i*64, xor^mask[i]);
if (re==el_B) { if (ia&63) BY_MASK(inc, elts + e*64, (xor^mask[e]) & ((1ULL<<(ia&63)) - 1));
HArr_p r = m_harrUc(x);
return (AnyArr) {r.b, r.a};
}
B r;
void* rp = m_tyarrlbc(&r, elwBitLog(re), x, el2t(re));
return (AnyArr) {r, rp};
} }
#undef BY_MASK
B ne_c2(B,B,B); B ne_c2(B,B,B);
B slash_ucw(B t, B o, B w, B x) { B slash_ucw(B t, B o, B w, B x) {
@ -1089,7 +1084,6 @@ B slash_ucw(B t, B o, B w, B x) {
#if SINGELI_SIMD #if SINGELI_SIMD
if (isFun(o) && TY(o)==t_md1D) { if (isFun(o) && TY(o)==t_md1D) {
u8 xe = TI(x,elType); u8 xe = TI(x,elType);
if (xe==el_B) goto notConstEach; // TODO not
Md1D* od = c(Md1D,o); Md1D* od = c(Md1D,o);
if (PRTID(od->m1) != n_each) goto notConstEach; if (PRTID(od->m1) != n_each) goto notConstEach;
@ -1104,27 +1098,38 @@ B slash_ucw(B t, B o, B w, B x) {
} }
u8 ce = selfElType(c); u8 ce = selfElType(c);
u8 re = el_or(ce,xe); // can be el_B u8 re = el_or(ce,xe);
B r; u64 sum = U64_MAX;
if (isVal(c)) { if (isVal(c)) {
u64 sum = usum(w); sum = bit_sum(bitany_ptr(w), ia);
if (sum==0) decG(c); // TODO could return x; fills? if (sum==0) decG(c); // TODO could return x; fills?
else incByG(c, sum-1); else incByG(c, sum-1);
} }
void* rp; DirectArr r;
void* xp; void* xp;
if (re != xe) { if (re != xe) {
AnyArr a = cpyElTypeArr(re, x); assert(xe != el_B);
x = r = incG(a.b); r = toEltypeArr(x, re);
xp = rp = a.data; x = incG(r.obj);
xp = r.data;
} else { } else {
AnyArr a = m_anyarrc(re, x); if (xe==el_B) {
r = a.b; r = potentiallyReuse(x);
rp = a.data; if (r.obj.u == x.u) {
xp = r.data;
decByMask(bitany_ptr(w), xp, ia, 0);
} else {
TO_BPTR(x);
xp = arr_bptrG(x);
incByMask(bitany_ptr(w), xp, ia, 1);
}
} else {
r = potentiallyReuse(x);
xp = tyany_ptr(x); xp = tyany_ptr(x);
} }
}
u64 cv; u64 cv;
if (elInt(re)) cv = o2iG(c); if (elInt(re)) cv = o2iG(c);
@ -1134,10 +1139,10 @@ B slash_ucw(B t, B o, B w, B x) {
cv = re==el_f64? r_f64u(o2fG(c)) : r_Bu(c); cv = re==el_f64? r_f64u(o2fG(c)) : r_Bu(c);
} }
blendArrScalarFns[elwBitLog(re)](rp, xp, cv, bitany_ptr(w), IA(x)); blendArrScalarFns[elwBitLog(re)](r.data, xp, cv, bitany_ptr(w), ia);
NOGC_E; NOGC_E;
decG(w); decG(x); decG(w); decG(x);
return r; return r.obj;
} }
#endif #endif
goto notConstEach; notConstEach:; goto notConstEach; notConstEach:;

View File

@ -799,7 +799,7 @@ static NOINLINE DirectArr toFillArr(B x, B fill) {
static void* reusableArr_ptr(Arr* t, u8 el) { static void* reusableArr_ptr(Arr* t, u8 el) {
return el==el_B? (void*)(PTY(t)==t_fillarr? fillarrv_ptr(t) : harrv_ptr(t)) : tyarrv_ptr((TyArr*)t); return el==el_B? (void*)(PTY(t)==t_fillarr? fillarrv_ptr(t) : harrv_ptr(t)) : tyarrv_ptr((TyArr*)t);
} }
DirectArr toEltypeArr(B x, u8 re) { // consumes x; returns an array with eltype==re, with same shape/elements/fill as x, and its data pointer DirectArr toEltypeArr(B x, u8 re) {
assert(isArr(x)); assert(isArr(x));
if (reusable(x) && re==reuseElType[TY(x)]) { if (reusable(x) && re==reuseElType[TY(x)]) {
x = REUSE(x); x = REUSE(x);
@ -818,16 +818,38 @@ DirectArr toEltypeArr(B x, u8 re) { // consumes x; returns an array with eltype=
case el_c32: tyarr = cpyC32Arr(x); goto tyarr; case el_c32: tyarr = cpyC32Arr(x); goto tyarr;
case el_B:; case el_B:;
B fill = getFillR(x); B fill = getFillR(x);
if (noFill(fill)) { if (!noFill(fill)) return toFillArr(x, fill);
Arr* r = cpyHArr(x); Arr* r = cpyHArr(x);
return (DirectArr){taga(r), harrv_ptr(r)}; return (DirectArr){taga(r), harrv_ptr(r)};
} }
return toFillArr(x, fill);
}
tyarr: tyarr:
return (DirectArr){taga(tyarr), tyarrv_ptr((TyArr*) tyarr)}; return (DirectArr){taga(tyarr), tyarrv_ptr((TyArr*) tyarr)};
} }
static NOINLINE DirectArr m_fillarrAs(B x, B fill) {
Arr* r = arr_shCopy(m_fillarrp(IA(x)), x);
fillarr_setFill(r, fill);
return (DirectArr){taga(r), fillarrv_ptr(r)};
}
DirectArr potentiallyReuse(B x) {
assert(isArr(x));
u8 xe = TI(x,elType);
if (reusable(x) && xe == reuseElType[TY(x)]) {
x = REUSE(x);
return (DirectArr){incG(x), reusableArr_ptr(a(x), xe)};
}
if (xe==el_B) {
B fill = getFillR(x);
if (!noFill(fill)) return m_fillarrAs(x, fill);
HArr_p r = m_harrUc(x);
return (DirectArr) {r.b, r.a};
}
B r;
void* rp = m_tyarrlbc(&r, elwBitLog(xe), x, el2t(xe));
return (DirectArr) {r, rp};
}
B directGetU_bit(void* data, ux i) { return m_f64(bitp_get(data,i));} void directSet_bit(void* data, ux i, B v) { bitp_set(data, i, o2bG(v)); } B directGetU_bit(void* data, ux i) { return m_f64(bitp_get(data,i));} void directSet_bit(void* data, ux i, B v) { bitp_set(data, i, o2bG(v)); }
B directGetU_i8 (void* data, ux i) { return m_f64((( i8*)data)[i]); } void directSet_i8 (void* data, ux i, B v) { (( i8*)data)[i] = o2iG(v); } B directGetU_i8 (void* data, ux i) { return m_f64((( i8*)data)[i]); } void directSet_i8 (void* data, ux i, B v) { (( i8*)data)[i] = o2iG(v); }

View File

@ -287,13 +287,23 @@ typedef void (*DirectSetRange)(void* data, ux rs, B x, ux xs, ux l);
extern INIT_GLOBAL DirectGet directGetU[el_MAX]; extern INIT_GLOBAL DirectGet directGetU[el_MAX];
extern INIT_GLOBAL DirectSet directSet[el_MAX]; extern INIT_GLOBAL DirectSet directSet[el_MAX];
extern INIT_GLOBAL DirectSetRange directSetRange[el_MAX]; extern INIT_GLOBAL DirectSetRange directSetRange[el_MAX];
// consumes x; returns an array with eltype==re, with same shape/elements/fill as x, and its data pointer
DirectArr toEltypeArr(B x, u8 re); DirectArr toEltypeArr(B x, u8 re);
// doesn't consume; returns array with same shape & fill as x, returning x itself if possible (iif so, x.u==obj.u).
// If reused, the object is untouched besides having its refcount incremented and flags cleared.
// As such, if an el_B array is reused, all elements effectively have 1 more refcount than they should as x's elements never get freed
// Otherwise, functionality is the same as if a regular new array was made
// May start NOGC
DirectArr potentiallyReuse(B x);
#define DIRECTARR_COPY(R, RE, X) \ #define DIRECTARR_COPY(R, RE, X) \
u8 R##_elt = RE; \ u8 R##_elt = RE; \
DirectArr R = toEltypeArr(X, R##_elt); \ MAYBE_UNUSED DirectArr R = toEltypeArr(X, R##_elt); \
DirectGet R##_getU = directGetU[R##_elt]; \ MAYBE_UNUSED DirectGet R##_getU = directGetU[R##_elt]; \
DirectSet R##_set = directSet[R##_elt]; \ MAYBE_UNUSED DirectSet R##_set = directSet[R##_elt]; \
DirectSetRange R##_setRange = directSetRange[R##_elt]; MAYBE_UNUSED DirectSetRange R##_setRange = directSetRange[R##_elt];
#define DIRECTARR_RM(R, I) if (R##_elt == el_B) dec(((B*)R.data)[I]); #define DIRECTARR_RM(R, I) if (R##_elt == el_B) dec(((B*)R.data)[I]);
#define DIRECTARR_GETU(R, I) R##_getU(R.data, I) #define DIRECTARR_GETU(R, I) R##_getU(R.data, I)

View File

@ -175,6 +175,7 @@ n←500 ⋄ a←↕n ⋄ i←(-n)+↕2×n ⋄ r←⌽(2×n)⥊a ⋄ ! (⌽a) ≡
1+((10)/) 10 %% ×+ 10 1+((10)/) 10 %% ×+ 10
%USE eqvar <> {𝕨(10011/) 𝕩}_eqvar +-×÷ %% <-×> %USE eqvar <> {𝕨(10011/) 𝕩}_eqvar +-×÷ %% <-×>
%USE eqvar ["wx""WX","yz""YZ"] {𝕨(1001/) 𝕩}_eqvar (<"aA")+42 %% 42"wx","WX","bA","bB","cA","cB","yz","YZ" %USE eqvar ["wx""WX","yz""YZ"] {𝕨(1001/) 𝕩}_eqvar (<"aA")+42 %% 42"wx","WX","bA","bB","cA","cB","yz","YZ"
{m𝕩•rand.Range 2 ! (m{𝕨?"huh";'a'+𝕩}¨𝕩) "huh"¨(m/) 'a'+𝕩}¨ 100
!"Integer out of range: 3.68934881474191e19" % 1¨(a/) a100265 !"Integer out of range: 3.68934881474191e19" % 1¨(a/) a100265
!"Expected non-negative integer, got ¯10" % %USE evar 1¨(a/)_evar a¯10(50) 10010 !"Expected non-negative integer, got ¯10" % %USE evar 1¨(a/)_evar a¯10(50) 10010