diff --git a/src/builtins/cells.c b/src/builtins/cells.c index e261b493..3ca54511 100644 --- a/src/builtins/cells.c +++ b/src/builtins/cells.c @@ -26,7 +26,7 @@ B try_interleave_cells(B w, B x, ur xr, ur xk, usz* xsh); // from transpose.c // from select.c: B select_rows_B(B x, ux csz, ux cam, B inds); -B select_rows_typed(B x, ux csz, ux cam, void* inds, ux indn, u8 ie); +B select_rows_direct(B x, ux csz, ux cam, void* inds, ux indn, u8 ie); // X - variable name; XSH - its shape; K - number of leading axes that get iterated over; SLN - number of slices that will be made; DX - additional refcount count to add to x #define S_KSLICES(X, XSH, K, SLN, DX)\ @@ -507,7 +507,7 @@ B for_cells_c1(B f, u32 xr, u32 cr, u32 k, B x, u32 chr) { // F⎉cr x; array x, u8 xe = TI(x,elType); if (cr==1 && csz<=64 && xe!=el_bit && xe!=el_B && csz < (128*8 >> arrTypeBitsLog(TY(x)))) { incG(x); // TODO proper shape moving - Arr* r = customizeShape(select_rows_typed(x, csz, cam, reverse_inds_64+64-csz, csz, el_i8)); + Arr* r = customizeShape(select_rows_direct(x, csz, cam, reverse_inds_64+64-csz, csz, el_i8)); arr_shCopy(r, x); decG(x); return taga(r); diff --git a/src/builtins/select.c b/src/builtins/select.c index 1cff811f..7e236192 100644 --- a/src/builtins/select.c +++ b/src/builtins/select.c @@ -55,7 +55,7 @@ // Direct call to select function per cell // COULD have a more direct call that avoids overflow checking & wrapping // COULD generate full list of indices via arith -// 1-element cells: use (≠inds)/⥊x after checking ∧´0=inds +// 1-element cells: use (≠inds)/⥊x after checking ∧´inds∊0‿¯1 // Used for ⌽⎉1 // SHOULD use for atom⊸⊏⎉k, /⎉k, ⌽⎉k, ↑⎉k, ⍉⎉k, probably more @@ -579,7 +579,7 @@ B select_cells_base(B inds, B x0, ux csz, ux cam); #endif #define INDS_BUF_MAX 64 // only need 32 bytes for AVX2 & 16 for NEON, but have more for past-the-end pointers and writes -B select_rows_typed(B x, ux csz, ux cam, void* inds, ux indn, u8 ie) { // ⥊ (indn↑inds As ie)⊸⊏˘ cam‿csz⥊z; xe cannot be el_bit or el_B, unless csz==1; ie must be ≤el_i8 if csz≤128 +B select_rows_direct(B x, ux csz, ux cam, void* inds, ux indn, u8 ie) { // ⥊ (indn↑inds As ie)⊸⊏˘ cam‿csz⥊x assert(csz!=0 && cam!=0); assert(csz*cam == IA(x)); assert(ie<=el_i32); @@ -588,21 +588,22 @@ B select_rows_typed(B x, ux csz, ux cam, void* inds, ux indn, u8 ie) { // ⥊ (i bool generic_allowed = true; // whether required interpretation of x hasn't changed from its real one if (csz==1) { // TODO maybe move to select_rows_B and require csz>=2 here? i64 bounds[2]; - if (!getRange_fns[ie](inds, bounds, indn) || bounds[0]<-1 || bounds[1]>0) goto generic; + if (!getRange_fns[ie](inds, bounds, indn) || bounds[0]<-1 || bounds[1]>0) goto generic_any; return C2(slash, m_f64(indn), taga(arr_shVec(customizeShape(x)))); } - u8 xe = TI(x,elType); - assert(xe!=el_bit && xe!=el_B); assert(csz>=2); - B r; + u8 xe = TI(x,elType); u8 lb = arrTypeWidthLog(TY(x)); + u8* xp = tyany_ptr(x); + if (xe==el_bit || xe==el_B) goto generic_any; + + B r; + ux ria = indn * cam; + bool fast; (void) fast; ux xbump = csz<= (i64)csz) goto generic; + if (!getRange_fns[ie](inds, bounds, indn)) goto generic_int; + if (bounds[1] >= (i64)csz) goto generic_int; if (bounds[0] < 0) { - if (bounds[0] < -(i64)csz) goto generic; + if (bounds[0] < -(i64)csz) goto generic_int; if (csz < 128 && indn < INDS_BUF_MAX) { assert(ie == el_i8); si_wrap_inds[0](inds, inds_buf, indn, csz); @@ -738,11 +740,18 @@ B select_rows_typed(B x, ux csz, ux cam, void* inds, ux indn, u8 ie) { // ⥊ (i } #endif - generic:; - assert(generic_allowed); + generic_any:; + if (ie==el_bit) { + u64* rp; + B indo = m_bitarrv(&rp, indn); + memcpy(rp, inds, (indn+7)>>3); + assert(generic_allowed); + return select_cells_base(indo, x, csz, cam); + } + generic_int:; + assert(ie!=el_bit && generic_allowed); B indo = taga(arr_shVec(m_tyslice(inds, a(emptyIVec()), ie, indn))); - r = select_cells_base(indo, x, csz, cam); - return r; + return select_cells_base(indo, x, csz, cam); decG_ret:; decG(x); @@ -766,12 +775,9 @@ B select_rows_B(B x, ux csz, ux cam, B inds) { // consumes inds,x; ⥊ inds⊸ } void* ip = tyany_ptr(inds); - u8 xe = TI(x,elType); - if ((xe!=el_bit && xe!=el_B) || csz==1) { - B r = select_rows_typed(x, csz, cam, (u8*)ip, in, ie); - decG(inds); - return r; - } + B r = select_rows_direct(x, csz, cam, (u8*)ip, in, ie); + decG(inds); + return r; generic:; return select_cells_base(inds, x, csz, cam); diff --git a/src/core/tyarr.c b/src/core/tyarr.c index 74d73aaf..d4242c0e 100644 --- a/src/core/tyarr.c +++ b/src/core/tyarr.c @@ -31,7 +31,8 @@ u8 const arrTypeWidthLog[] = { [t_i8arr ]=0, [t_i8slice ]=0, [t_c8arr ]=0, [t_c8slice ]=0, [t_i16arr]=1, [t_i16slice]=1, [t_c16arr]=1, [t_c16slice]=1, [t_i32arr]=2, [t_i32slice]=2, [t_c32arr]=2, [t_c32slice]=2, - [t_f64arr]=3, [t_f64slice]=3 + [t_f64arr]=3, [t_f64slice]=3, + [t_harr ]=3, [t_hslice ]=3, [t_fillarr]=3,[t_fillslice]=3 }; u8 const arrTypeBitsLog[] = { [t_bitarr]=0, diff --git a/test/cases/cells.bqn b/test/cases/cells.bqn index d73ec933..5daf0472 100644 --- a/test/cases/cells.bqn +++ b/test/cases/cells.bqn @@ -90,6 +90,9 @@ 1‿2‿0‿1‿¯1⊸⊏⎉2 2‿3‿4⥊↕24 %% 2‿5‿4⥊4‿5‿6‿7‿8‿9‿10‿11‿0‿1‿2‿3‿4‿5‿6‿7‿8‿9‿10‿11‿16‿17‿18‿19‿20‿21‿22‿23‿12‿13‿14‿15‿16‿17‿18‿19‿20‿21‿22‿23 !"⊏: Indexing out-of-bounds (1∊𝕨, 1≡≠𝕩)" % %USE evar ⋄ 0‿¯1‿1‿¯1 {𝕨⊸⊏˘𝕩}_evar ≍˘↕5 !"⊏: Indexing out-of-bounds (¯2∊𝕨, 1≡≠𝕩)" % %USE evar ⋄ 0‿¯1‿¯2‿¯1 {𝕨⊸⊏˘𝕩}_evar ≍˘↕5 +!"⊏: Indexing out-of-bounds (¯129∊𝕨, 128≡≠𝕩)" % %USE evar ⋄ 10‿¯129 {𝕨⊸⊏˘𝕩}_evar 10‿128⥊1 +!"⊏: Indexing out-of-bounds (128∊𝕨, 128≡≠𝕩)" % %USE evar ⋄ 10‿128 {𝕨⊸⊏˘𝕩}_evar 10‿128⥊1 +!"⊏: Indexing out-of-bounds (1∊𝕨, 1≡≠𝕩)" % %USE evar ⋄ 1‿0‿0‿1 {𝕨⊸⊏˘𝕩}_evar 10‿1⥊1 ( %USE IS_HEAPVERIFY