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;
#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
Arr* a;
switch (re) { default: UD;
case el_bit: a = cpyBitArr(x); goto tyarr;
case el_i8: a = cpyI8Arr(x); goto tyarr;
case el_i16: a = cpyI16Arr(x); goto tyarr;
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;
case el_c32: a = cpyC32Arr(x); goto tyarr;
case el_B:
a = cpyHArr(x);
return (AnyArr){taga(a), harrv_ptr(a)};
}
tyarr:
return (AnyArr){taga(a), tyarrv_ptr((TyArr*)a)};
#define BY_MASK(F, ELTS, C) ({ \
u64 c = (C); \
B* elts_ = (ELTS); \
while (c) { \
F(elts_[CTZ(c)]); \
c&=c-1; \
} \
})
static void decByMask(u64* mask, B* elts, ux ia, bool inv) {
u64 xor = inv? U64_MAX : 0;
ux e = ia>>6;
for (ux i=0; i<e; i++) BY_MASK(dec, elts + i*64, xor^mask[i]);
if (ia&63) BY_MASK(dec, elts + e*64, (xor^mask[e]) & ((1ULL<<(ia&63)) - 1));
}
AnyArr m_anyarrc(u8 re, B x) { // consumes x; returns new array with given element type; may start NOGC
if (re==el_B) {
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};
static void incByMask(u64* mask, B* elts, ux ia, bool inv) {
u64 xor = inv? U64_MAX : 0;
ux e = ia>>6;
for (ux i=0; i<e; i++) BY_MASK(inc, elts + i*64, xor^mask[i]);
if (ia&63) BY_MASK(inc, elts + e*64, (xor^mask[e]) & ((1ULL<<(ia&63)) - 1));
}
#undef BY_MASK
B ne_c2(B,B,B);
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 (isFun(o) && TY(o)==t_md1D) {
u8 xe = TI(x,elType);
if (xe==el_B) goto notConstEach; // TODO not
Md1D* od = c(Md1D,o);
if (PRTID(od->m1) != n_each) goto notConstEach;
@ -1104,26 +1098,37 @@ B slash_ucw(B t, B o, B w, B x) {
}
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)) {
u64 sum = usum(w);
sum = bit_sum(bitany_ptr(w), ia);
if (sum==0) decG(c); // TODO could return x; fills?
else incByG(c, sum-1);
}
void* rp;
DirectArr r;
void* xp;
if (re != xe) {
AnyArr a = cpyElTypeArr(re, x);
x = r = incG(a.b);
xp = rp = a.data;
assert(xe != el_B);
r = toEltypeArr(x, re);
x = incG(r.obj);
xp = r.data;
} else {
AnyArr a = m_anyarrc(re, x);
r = a.b;
rp = a.data;
xp = tyany_ptr(x);
if (xe==el_B) {
r = potentiallyReuse(x);
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);
}
}
u64 cv;
@ -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);
}
blendArrScalarFns[elwBitLog(re)](rp, xp, cv, bitany_ptr(w), IA(x));
blendArrScalarFns[elwBitLog(re)](r.data, xp, cv, bitany_ptr(w), ia);
NOGC_E;
decG(w); decG(x);
return r;
return r.obj;
}
#endif
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) {
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));
if (reusable(x) && re==reuseElType[TY(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_B:;
B fill = getFillR(x);
if (noFill(fill)) {
Arr* r = cpyHArr(x);
return (DirectArr){taga(r), harrv_ptr(r)};
}
return toFillArr(x, fill);
if (!noFill(fill)) return toFillArr(x, fill);
Arr* r = cpyHArr(x);
return (DirectArr){taga(r), harrv_ptr(r)};
}
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_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 DirectSet directSet[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);
// 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) \
u8 R##_elt = RE; \
DirectArr R = toEltypeArr(X, R##_elt); \
DirectGet R##_getU = directGetU[R##_elt]; \
DirectSet R##_set = directSet[R##_elt]; \
DirectSetRange R##_setRange = directSetRange[R##_elt];
u8 R##_elt = RE; \
MAYBE_UNUSED DirectArr R = toEltypeArr(X, R##_elt); \
MAYBE_UNUSED DirectGet R##_getU = directGetU[R##_elt]; \
MAYBE_UNUSED DirectSet R##_set = directSet[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_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
%USE eqvar <> {𝕨(10011/) 𝕩}_eqvar +-×÷ %% <-×>
%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
!"Expected non-negative integer, got ¯10" % %USE evar 1¨(a/)_evar a¯10(50) 10010