high-rank in-place w∾x
This commit is contained in:
parent
1c645e11d8
commit
3c2a7dbefa
@ -836,9 +836,9 @@ B join_c2(B t, B w, B x) {
|
|||||||
if (wr==1 && inplace_add(w, x)) return w;
|
if (wr==1 && inplace_add(w, x)) return w;
|
||||||
x = m_atomUnit(x);
|
x = m_atomUnit(x);
|
||||||
}
|
}
|
||||||
usz wia = a(w)->ia; usz* wsh = a(w)->sh;
|
ur xr = rnk(x);
|
||||||
usz xia = a(x)->ia; usz* xsh = a(x)->sh; ur xr = rnk(x);
|
|
||||||
B f = fill_both(w, x);
|
B f = fill_both(w, x);
|
||||||
|
|
||||||
ur c = wr>xr?wr:xr;
|
ur c = wr>xr?wr:xr;
|
||||||
if (c==0) {
|
if (c==0) {
|
||||||
HArr_p r = m_harrUv(2);
|
HArr_p r = m_harrUv(2);
|
||||||
@ -847,27 +847,47 @@ B join_c2(B t, B w, B x) {
|
|||||||
return qWithFill(r.b, f);
|
return qWithFill(r.b, f);
|
||||||
}
|
}
|
||||||
if (c-wr > 1 || c-xr > 1) thrF("∾: Argument ranks must differ by 1 or less (%i≡=𝕨, %i≡=𝕩)", wr, xr);
|
if (c-wr > 1 || c-xr > 1) thrF("∾: Argument ranks must differ by 1 or less (%i≡=𝕨, %i≡=𝕩)", wr, xr);
|
||||||
|
|
||||||
|
bool reusedW;
|
||||||
|
B r = arr_join_inline(w, x, false, &reusedW);
|
||||||
if (c==1) {
|
if (c==1) {
|
||||||
B r = vec_join_inline(w, x);
|
|
||||||
if (rnk(r)==0) srnk(r,1);
|
if (rnk(r)==0) srnk(r,1);
|
||||||
return qWithFill(r, f);
|
} else {
|
||||||
}
|
assert(c>1);
|
||||||
MAKE_MUT(r, wia+xia); mut_init(r, el_or(TI(w,elType), TI(x,elType)));
|
ur rnk0 = rnk(r);
|
||||||
MUTG_INIT(r);
|
ShArr* sh0 = shObj(r);
|
||||||
mut_copyG(r, 0, w, 0, wia);
|
usz wia;
|
||||||
mut_copyG(r, wia, x, 0, xia);
|
usz* wsh;
|
||||||
Arr* ra = mut_fp(r);
|
if (wr==1 && reusedW) {
|
||||||
usz* sh = arr_shAlloc(ra, c);
|
wia = a(w)->ia-a(x)->ia;
|
||||||
if (sh) {
|
wsh = &wia;
|
||||||
|
} else {
|
||||||
|
wsh = a(w)->sh; // when wr>1, shape object won't be disturbed by arr_join_inline
|
||||||
|
}
|
||||||
|
usz* xsh = a(x)->sh;
|
||||||
|
srnk(r, 0); // otherwise shape allocation failing may break things
|
||||||
|
usz* rsh = arr_shAlloc(a(r), c);
|
||||||
|
#if PRINT_JOIN_REUSE
|
||||||
|
printf(reusedW? "reuse:1;" : "reuse:0;");
|
||||||
|
#endif
|
||||||
for (i32 i = 1; i < c; i++) {
|
for (i32 i = 1; i < c; i++) {
|
||||||
usz s = xsh[i+xr-c];
|
usz s = xsh[i+xr-c];
|
||||||
if (wsh[i+wr-c] != s) { mut_pfree(r, wia+xia); thrF("∾: Lengths not matchable (%H ≡ ≢𝕨, %H ≡ ≢𝕩)", w, x); }
|
if (RARE(wsh[i+wr-c] != s)) {
|
||||||
sh[i] = s;
|
B msg = make_fmt("∾: Lengths not matchable (%2H ≡ ≢𝕨, %H ≡ ≢𝕩)", wr, wsh, x);
|
||||||
|
if (rnk0>1) decShObj(sh0);
|
||||||
|
mm_free((Value*)shObjS(rsh));
|
||||||
|
arr_shVec(a(r));
|
||||||
|
thr(msg);
|
||||||
|
}
|
||||||
|
rsh[i] = s;
|
||||||
}
|
}
|
||||||
sh[0] = (wr==c? wsh[0] : 1) + (xr==c? xsh[0] : 1);
|
rsh[0] = (wr==c? wsh[0] : 1) + (xr==c? xsh[0] : 1);
|
||||||
|
if (rnk0>1) decShObj(sh0);
|
||||||
}
|
}
|
||||||
decG(w); decG(x);
|
|
||||||
return qWithFill(taga(ra), f);
|
decG(x);
|
||||||
|
if (!reusedW) decG(w);
|
||||||
|
return qWithFill(r, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -248,10 +248,19 @@ NOINLINE B do_fmt(B s, char* p, va_list a) {
|
|||||||
s = appendRaw(s, bqn_repr(inc(b)));
|
s = appendRaw(s, bqn_repr(inc(b)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case '2':
|
||||||
case 'H': {
|
case 'H': {
|
||||||
B o = va_arg(a, B);
|
ur r;
|
||||||
ur r = isArr(o)? rnk(o) : 0;
|
usz* sh;
|
||||||
usz* sh = isArr(o)? a(o)->sh : NULL;
|
if (c=='2') {
|
||||||
|
if ('H' != *p++) err("Invalid format string: expected H after %2");
|
||||||
|
r = va_arg(a, int);
|
||||||
|
sh = va_arg(a, usz*);
|
||||||
|
} else {
|
||||||
|
B o = va_arg(a, B);
|
||||||
|
r = isArr(o)? rnk(o) : 0;
|
||||||
|
sh = isArr(o)? a(o)->sh : NULL;
|
||||||
|
}
|
||||||
if (r==0) AU("⟨⟩");
|
if (r==0) AU("⟨⟩");
|
||||||
else if (r==1) AFMT("⟨%s⟩", sh[0]);
|
else if (r==1) AFMT("⟨%s⟩", sh[0]);
|
||||||
else {
|
else {
|
||||||
|
|||||||
@ -26,7 +26,8 @@ typedef struct ShArr {
|
|||||||
static ShArr* shObjS(usz* x) { return RFLD(x, ShArr, a); }
|
static ShArr* shObjS(usz* x) { return RFLD(x, ShArr, a); }
|
||||||
static ShArr* shObj (B x) { return RFLD(a(x)->sh, ShArr, a); }
|
static ShArr* shObj (B x) { return RFLD(a(x)->sh, ShArr, a); }
|
||||||
static ShArr* shObjP(Value* x) { return RFLD(((Arr*)x)->sh, ShArr, a); }
|
static ShArr* shObjP(Value* x) { return RFLD(((Arr*)x)->sh, ShArr, a); }
|
||||||
static void decSh(Value* x) { if (RARE(prnk(x)>1)) tptr_dec(shObjP(x), mm_free); }
|
static void decShObj(ShArr* x) { tptr_dec(x, mm_free); }
|
||||||
|
static void decSh(Value* x) { if (RARE(prnk(x)>1)) decShObj(shObjP(x)); }
|
||||||
|
|
||||||
// some array stuff
|
// some array stuff
|
||||||
|
|
||||||
@ -51,10 +52,11 @@ static Arr* arr_shVec(Arr* x) {
|
|||||||
x->sh = &x->ia;
|
x->sh = &x->ia;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
static usz* arr_shAlloc(Arr* x, ur r) { // sets rank, allocates & returns shape (or null if r<2)
|
static usz* arr_shAlloc(Arr* x, ur r) { // sets rank, allocates & returns shape (or null if r<2); assumes x has rank≤1 (which will be the case for new allocations)
|
||||||
|
assert(prnk(x)<=1);
|
||||||
if (r>1) {
|
if (r>1) {
|
||||||
usz* sh = x->sh = m_shArr(r)->a;
|
usz* sh = x->sh = m_shArr(r)->a; // if m_shArr fails, the assumed rank≤1 guarantees the uninitialized x->sh won't break
|
||||||
sprnk(x,r); // is m_shArr OOMs, rank is gonna stay the 0 from the initial write in allocL, which is "safe"
|
sprnk(x,r);
|
||||||
return sh;
|
return sh;
|
||||||
}
|
}
|
||||||
sprnk(x,r);
|
sprnk(x,r);
|
||||||
|
|||||||
@ -54,7 +54,8 @@ NOINLINE void mut_pfree(Mut* m, usz n) { // free the first n elements
|
|||||||
|
|
||||||
|
|
||||||
B vec_join(B w, B x) {
|
B vec_join(B w, B x) {
|
||||||
return vec_join_inline(w, x);
|
bool unused;
|
||||||
|
return arr_join_inline(w, x, true, &unused);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -157,7 +157,10 @@ static void bit_cpy(u64* r, usz rs, u64* x, usz xs, usz l) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
B vec_join(B w, B x); // consumes both
|
B vec_join(B w, B x); // consumes both
|
||||||
FORCE_INLINE B vec_join_inline(B w, B x) {
|
|
||||||
|
// if `consume==true`, consumes w,x and expects both args to be vectors
|
||||||
|
// else, doesn't consume x, and decrements refcount of w iif *reusedW (won't free because the result will be w)
|
||||||
|
FORCE_INLINE B arr_join_inline(B w, B x, bool consume, bool* reusedW) {
|
||||||
usz wia = a(w)->ia;
|
usz wia = a(w)->ia;
|
||||||
usz xia = a(x)->ia;
|
usz xia = a(x)->ia;
|
||||||
usz ria = wia+xia;
|
usz ria = wia+xia;
|
||||||
@ -166,14 +169,14 @@ FORCE_INLINE B vec_join_inline(B w, B x) {
|
|||||||
u8 wt = v(w)->type;
|
u8 wt = v(w)->type;
|
||||||
// TODO f64∾i32, i32∾i8, c32∾c8 etc
|
// TODO f64∾i32, i32∾i8, c32∾c8 etc
|
||||||
switch (wt) {
|
switch (wt) {
|
||||||
case t_bitarr: if (BITARR_SZ( ria)<wsz && TI(x,elType)==el_bit) { a(w)->ia=ria; bit_cpy(bitarr_ptr(w),wia,bitarr_ptr(x),0,xia); decG(x); return FL_KEEP(w,fl_squoze); } break;
|
case t_bitarr: if (BITARR_SZ( ria)<wsz && TI(x,elType)==el_bit) { a(w)->ia=ria; bit_cpy(bitarr_ptr(w),wia,bitarr_ptr(x),0,xia); goto rw; } break;
|
||||||
case t_i8arr: if (TYARR_SZ(I8, ria)<wsz && TI(x,elType)==el_i8 ) { a(w)->ia=ria; memcpy(i8arr_ptr (w)+wia, i8any_ptr (x), xia*1); decG(x); return FL_KEEP(w,fl_squoze); } break;
|
case t_i8arr: if (TYARR_SZ(I8, ria)<wsz && TI(x,elType)==el_i8 ) { a(w)->ia=ria; memcpy(i8arr_ptr (w)+wia, i8any_ptr (x), xia*1); goto rw; } break;
|
||||||
case t_i16arr: if (TYARR_SZ(I16,ria)<wsz && TI(x,elType)==el_i16) { a(w)->ia=ria; memcpy(i16arr_ptr(w)+wia, i16any_ptr(x), xia*2); decG(x); return FL_KEEP(w,fl_squoze); } break;
|
case t_i16arr: if (TYARR_SZ(I16,ria)<wsz && TI(x,elType)==el_i16) { a(w)->ia=ria; memcpy(i16arr_ptr(w)+wia, i16any_ptr(x), xia*2); goto rw; } break;
|
||||||
case t_i32arr: if (TYARR_SZ(I32,ria)<wsz && TI(x,elType)==el_i32) { a(w)->ia=ria; memcpy(i32arr_ptr(w)+wia, i32any_ptr(x), xia*4); decG(x); return FL_KEEP(w,fl_squoze); } break;
|
case t_i32arr: if (TYARR_SZ(I32,ria)<wsz && TI(x,elType)==el_i32) { a(w)->ia=ria; memcpy(i32arr_ptr(w)+wia, i32any_ptr(x), xia*4); goto rw; } break;
|
||||||
case t_c8arr: if (TYARR_SZ(C8, ria)<wsz && TI(x,elType)==el_c8 ) { a(w)->ia=ria; memcpy(c8arr_ptr (w)+wia, c8any_ptr (x), xia*1); decG(x); return FL_KEEP(w,fl_squoze); } break;
|
case t_c8arr: if (TYARR_SZ(C8, ria)<wsz && TI(x,elType)==el_c8 ) { a(w)->ia=ria; memcpy(c8arr_ptr (w)+wia, c8any_ptr (x), xia*1); goto rw; } break;
|
||||||
case t_c16arr: if (TYARR_SZ(C16,ria)<wsz && TI(x,elType)==el_c16) { a(w)->ia=ria; memcpy(c16arr_ptr(w)+wia, c16any_ptr(x), xia*2); decG(x); return FL_KEEP(w,fl_squoze); } break;
|
case t_c16arr: if (TYARR_SZ(C16,ria)<wsz && TI(x,elType)==el_c16) { a(w)->ia=ria; memcpy(c16arr_ptr(w)+wia, c16any_ptr(x), xia*2); goto rw; } break;
|
||||||
case t_c32arr: if (TYARR_SZ(C32,ria)<wsz && TI(x,elType)==el_c32) { a(w)->ia=ria; memcpy(c32arr_ptr(w)+wia, c32any_ptr(x), xia*4); decG(x); return FL_KEEP(w,fl_squoze); } break;
|
case t_c32arr: if (TYARR_SZ(C32,ria)<wsz && TI(x,elType)==el_c32) { a(w)->ia=ria; memcpy(c32arr_ptr(w)+wia, c32any_ptr(x), xia*4); goto rw; } break;
|
||||||
case t_f64arr: if (TYARR_SZ(F64,ria)<wsz && TI(x,elType)==el_f64) { a(w)->ia=ria; memcpy(f64arr_ptr(w)+wia, f64any_ptr(x), xia*8); decG(x); return FL_KEEP(w,fl_squoze); } break;
|
case t_f64arr: if (TYARR_SZ(F64,ria)<wsz && TI(x,elType)==el_f64) { a(w)->ia=ria; memcpy(f64arr_ptr(w)+wia, f64any_ptr(x), xia*8); goto rw; } break;
|
||||||
case t_harr: if (fsizeof(HArr,a,B,ria)<wsz) {
|
case t_harr: if (fsizeof(HArr,a,B,ria)<wsz) {
|
||||||
a(w)->ia = ria;
|
a(w)->ia = ria;
|
||||||
B* rp = harr_ptr(w)+wia;
|
B* rp = harr_ptr(w)+wia;
|
||||||
@ -190,23 +193,28 @@ FORCE_INLINE B vec_join_inline(B w, B x) {
|
|||||||
case el_c16: { u16* xp=c16any_ptr(x); for (usz i=0; i<xia; i++) rp[i] = m_c32(xp[i]); } break;
|
case el_c16: { u16* xp=c16any_ptr(x); for (usz i=0; i<xia; i++) rp[i] = m_c32(xp[i]); } break;
|
||||||
case el_c32: { u32* xp=c32any_ptr(x); for (usz i=0; i<xia; i++) rp[i] = m_c32(xp[i]); } break;
|
case el_c32: { u32* xp=c32any_ptr(x); for (usz i=0; i<xia; i++) rp[i] = m_c32(xp[i]); } break;
|
||||||
case el_f64: { f64* xp=f64any_ptr(x); for (usz i=0; i<xia; i++) rp[i] = m_f64(xp[i]); } break;
|
case el_f64: { f64* xp=f64any_ptr(x); for (usz i=0; i<xia; i++) rp[i] = m_f64(xp[i]); } break;
|
||||||
default:; SGet(x)
|
default: { SGet(x) for (usz i=0; i<xia; i++) rp[i] = Get(x, i); } break;
|
||||||
for (usz i = 0; i < xia; i++) rp[i] = Get(x, i);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
decG(x);
|
goto rw;
|
||||||
return FL_KEEP(w,fl_squoze); // keeping fl_squoze as appending items can't make the smallest item smaller
|
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MAKE_MUT(r, ria); mut_init(r, el_or(TI(w,elType), TI(x,elType)));
|
MAKE_MUT(r, ria); mut_init(r, el_or(TI(w,elType), TI(x,elType)));
|
||||||
MUTG_INIT(r);
|
MUTG_INIT(r);
|
||||||
mut_copyG(r, 0, w, 0, wia);
|
mut_copyG(r, 0, w, 0, wia);
|
||||||
mut_copyG(r, wia, x, 0, xia);
|
mut_copyG(r, wia, x, 0, xia);
|
||||||
decG(w); decG(x);
|
if (consume) { decG(x); decG(w); }
|
||||||
|
*reusedW = false;
|
||||||
return mut_fv(r);
|
return mut_fv(r);
|
||||||
|
|
||||||
|
rw:
|
||||||
|
if (consume) decG(x);
|
||||||
|
*reusedW = true;
|
||||||
|
return FL_KEEP(w,fl_squoze); // keeping fl_squoze as appending items can't make the smallest item smaller
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool inplace_add(B w, B x) { // consumes x if returns true; fails if fills wouldn't be correct
|
static inline bool inplace_add(B w, B x) { // consumes x if returns true; fails if fills wouldn't be correct
|
||||||
usz wia = a(w)->ia;
|
usz wia = a(w)->ia;
|
||||||
usz ria = wia+1;
|
usz ria = wia+1;
|
||||||
|
|||||||
@ -120,7 +120,7 @@ int32_t directAccess(BQNV x) {
|
|||||||
uint32_t res = 0;
|
uint32_t res = 0;
|
||||||
if (e==elt_i32) {
|
if (e==elt_i32) {
|
||||||
size_t bound = bqn_bound(x);
|
size_t bound = bqn_bound(x);
|
||||||
int32_t* els = bqn_directI32(x);
|
const int32_t* els = bqn_directI32(x);
|
||||||
for (size_t i = 0; i < bound; i++) res = res*31 + (uint32_t)els[i];
|
for (size_t i = 0; i < bound; i++) res = res*31 + (uint32_t)els[i];
|
||||||
} else {
|
} else {
|
||||||
printf("not elt_i32!\n");
|
printf("not elt_i32!\n");
|
||||||
|
|||||||
30
test/joinReuse.bqn
Normal file
30
test/joinReuse.bqn
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
⟨V⇐Variation ⋄ LV⇐ListVariations⟩←•internal
|
||||||
|
AllEq ← !¨ (<∘⊑≡¨⊢)
|
||||||
|
|
||||||
|
# run with -DPRINT_JOIN_REUSE
|
||||||
|
# all that's important in the output is that there are at least some "reuse:1"s and "reuse:0"s for each item
|
||||||
|
|
||||||
|
{ w𝕊x:
|
||||||
|
•Out "next"
|
||||||
|
AllEq t ← {(⥊ ⋈ ≢) (𝕨 V w)∾𝕩 V x}⌜´ LV¨ 𝕨‿𝕩
|
||||||
|
•Out "" ⋄ •Show ⊑t
|
||||||
|
}´¨ ⟨
|
||||||
|
"ab"‿["01","23"]
|
||||||
|
["ab","cd"]‿"01"
|
||||||
|
["ab","cd","ef"]‿["01","23"]
|
||||||
|
[["ab","cd"]⋄["ef","gh"]⋄["ij","kl"]]‿["01","23"]
|
||||||
|
⟩
|
||||||
|
|
||||||
|
{𝕊:
|
||||||
|
|
||||||
|
{ w𝕊x:
|
||||||
|
•Out "next"
|
||||||
|
AllEq t ← {(𝕨 V w)∾𝕩 V x ⋄ •Out "Expected error, didn't get one; fail" ⋄ •Exit 1}⎊{𝕊:•CurrentError@}⌜´ LV¨ 𝕨‿𝕩
|
||||||
|
•Out "" ⋄ •Show ⊑t
|
||||||
|
}´¨ ⟨
|
||||||
|
"abc"‿["01","23"]
|
||||||
|
["ab","cd"]‿"012"
|
||||||
|
["ab","cd","ef"]‿["012","345"]
|
||||||
|
[["ab","cd"]⋄["ef","gh"]⋄["ij","kl"]]‿["012","345"]
|
||||||
|
⟩
|
||||||
|
}⍟⊢ 0=≠•args
|
||||||
Loading…
Reference in New Issue
Block a user