// Transpose and Reorder Axes (⍉) // Transpose // One length-2 axis: dedicated code // Boolean: pdep for height 2; pext for width 2 // SHOULD use a generic implementation if BMI2 not present // SHOULD optimize other short lengths with pdep/pext and shuffles // Boolean 𝕩: convert to integer // SHOULD have bit matrix transpose kernel // CPU sizes: native or SIMD code // Large SIMD kernels used when they fit, overlapping for odd sizes // i8: 16×16; i16: 16×8; i32: 8×8; f64: 4×4 // COULD use half-width or smaller kernels to improve odd sizes // Scalar transpose or loop used for overhang of 1 // Reorder Axes: self-hosted runtime (based on +⌜ and ⊏, not that slow) // Transpose inverse ⍉⁼ // Same as ⍉ for a rank ≤2 argument // SHOULD share data movement with ⍉ for other sizes // COULD implement fast ⍉⍟n // SHOULD convert ⍉ with rank to a Reorder Axes call #include "../core.h" #include "../utils/each.h" #include "../utils/talloc.h" #include "../builtins.h" #ifdef __BMI2__ #include #if USE_VALGRIND #define _pdep_u64 vg_pdep_u64 #endif #endif #define TRANSPOSE_LOOP( DST, SRC, W, H) PLAINLOOP for(usz y=0;y< H;y++) NOVECTORIZE for(usz x=0;x< W;x++) DST[x*H+y] = SRC[xi++] #define TRANSPOSE_BLOCK(DST, SRC, BW, BH, W, H) PLAINLOOP for(usz y=0;ya, xsh+1, xr-1); sh->a[xr-1] = h; arr_shReplace(r, xr, sh); return taga(r); } usz w = xsh[1] * shProd(xsh, 2, xr); if (w==1) goto no_reorder; Arr* r; usz xi = 0; u8 xe = TI(x,elType); bool toBit = false; if (h==2) { if (xe==el_B) { B* xp = TO_BPTR(x); B* x0 = xp; B* x1 = x0+w; HArr_p rp = m_harrUp(ia); for (usz i=0; ia; for (usz i=0; iuc1 = transp_uc1; c(BFn,bi_transp)->im = transp_im; }