diff --git a/src/builtins/scan.c b/src/builtins/scan.c index 5e63e8c5..d0418dea 100644 --- a/src/builtins/scan.c +++ b/src/builtins/scan.c @@ -258,7 +258,24 @@ B scan_c1(Md1D* d, B x) { B f = d->f; return C2(shape, s, taga(r)); } if (xe > el_f64) goto base; - if (xr!=1 && arr_csz(x)!=1) goto base; + if (xr != 1) { usz csz = arr_csz(x); if (csz != 1) { + #if SINGELI + i8 t = -1; bool neg = 0; + if (xe==el_bit) switch (rtid) { + CASE_N_OR: t=0; break; + CASE_N_AND: t=1; break; + case n_eq: neg=1; case n_ne: t=2; break; + } + if (t != -1) { + if (neg) x = bit_negate(x); + u64* rp; B r=m_bitarrc(&rp,x); + si_scan_bool_stride[t](bitany_ptr(x), rp, ia, csz); + if (neg) r = bit_negate(r); + decG(x); return r; + } + #endif + goto base; + }} if (xe==el_bit) switch (rtid) { default: goto base; case n_add: return scan_add_bool(x, ia); // + diff --git a/src/singeli/src/scan.singeli b/src/singeli/src/scan.singeli index ac283d4f..a3460b96 100644 --- a/src/singeli/src/scan.singeli +++ b/src/singeli/src/scan.singeli @@ -620,3 +620,36 @@ export{'si_scan_rows_and', scan_rows_andor{0}} export{'si_scan_rows_or', scan_rows_andor{1}} export{'si_scan_rows_ne', scan_rows_neq} export{'si_scan_rows_ltack', scan_rows_left} + + +# Strided boolean scans +fn scan_stride_bool_assoc{op}(x:*u64, r:*u64, nl:usz, l:usz) : void = { + assert{l > 1} + def {flip,opf} = if (same{op, &}) tup{~,|} else tup{{x}=>x,op} + nw:= cdiv{nl, 64} + if (l <= 64) { + c:u64 = 0 # carry l bits, no matter the alignment + @for (r, x over nw) { + c = opf{flip{x}, c >> (64-l)} + s:= l; while (s < 64) { c = opf{c, c<>(64-q) | p<