Transpose-based fold-cells implementation

This commit is contained in:
Marshall Lochbaum 2023-03-04 14:24:56 -05:00
parent ead637b135
commit 4b35acb82b
2 changed files with 37 additions and 5 deletions

View File

@ -13,6 +13,7 @@
#include "../core.h"
#include "../builtins.h"
#include "../utils/calls.h"
#if SINGELI_X86_64
#define SINGELI_FILE fold
@ -319,3 +320,36 @@ u64 usum(B x) { // doesn't consume; will error on non-integers, or elements <0,
overflow: thrM("Sum too big");
neg: thrM("Didn't expect negative integer");
}
// Arithmetic fold/insert on rows of flat rank-2 array x
B insert_c1(Md1D*, B);
B transp_c1(B, B);
B join_c2(B, B, B);
B fold_rows(Md1D* fd, B x) {
assert(isArr(x) && RNK(x)==2);
// Target block size trying to avoid power-of-two lengths, from:
// {𝕩/˜⌊´⊸= +˝˘ +˝¬∨`2|>⌊∘÷⟜2⍟(↕12) ⌊0.5+32÷˜𝕩÷⌜1+↕64} +⟜↕2⋆16
u64 block = (116053*8) >> arrTypeBitsLog(TY(x));
if (TI(x,elType)==el_bit || IA(x)/2 <= block) {
x = C1(transp, x);
return insert_c1(fd, x);
} else {
usz *sh = SH(x); usz n = sh[0]; usz m = sh[1];
usz b = (block + m - 1) / m; // Normal block length
usz b_max = b + b/4; // Last block max length
B r = bi_N;
BSS2A slice = TI(x,slice);
for (usz i=0, im=0; i<n; ) {
usz l = n-i; if (l > b_max) { incG(x); l = b; }
usz sia = l * m;
Arr* sl = slice(x, im, sia);
usz* ssh = arr_shAlloc(sl, 2);
ssh[0] = l;
ssh[1] = m;
B sr = insert_c1(fd, C1(transp, taga(sl)));
r = q_N(r) ? sr : C2(join, r, sr);
i += l; im += sia;
}
return r;
}
}

View File

@ -315,8 +315,7 @@ static NOINLINE B match_cells(bool ne, B w, B x, ur wr, ur xr, usz len) {
}
B shape_c1(B, B);
B transp_c1(B, B);
B insert_c1(Md1D* d, B x);
B fold_rows(Md1D* d, B x); // From fold.c
B cell_c1(Md1D* d, B x) { B f = d->f;
if (isAtm(x) || RNK(x)==0) {
B r = c1(f, x);
@ -358,9 +357,8 @@ B cell_c1(Md1D* d, B x) { B f = d->f;
Md1D* fd = c(Md1D,f);
u8 rtid = fd->m1->flags-1;
if (rtid==n_const) { f=fd->f; goto const_f; }
if ((rtid==n_fold || rtid==n_insert) && TI(x,elType)!=el_B && isPervasiveDy(fd->f) && RNK(x)==2 && SH(x)[1]==2) {
x = C1(transp, x);
return insert_c1(fd, x);
if ((rtid==n_fold || rtid==n_insert) && TI(x,elType)!=el_B && isPervasiveDy(fd->f) && RNK(x)==2 && SH(x)[1]<=64) {
return fold_rows(fd, x);
}
}
}