diff --git a/src/builtins/md1.c b/src/builtins/md1.c index 8473c540..b1a2e8a7 100644 --- a/src/builtins/md1.c +++ b/src/builtins/md1.c @@ -176,14 +176,26 @@ B scan_c1(Md1D* d, B x) { B f = d->f; if (xe==el_i32) { i32* xp=i32any_ptr(x); i32* rp; B r=m_i32arrv(&rp, ia); i32 c=0; for (usz i=0; ic)c=xp[i]; rp[i]=c; } decG(x); return r; } - if (xe==el_i16) { i16* xp=i16any_ptr(x); i16* rp; B r=m_i16arrv(&rp, ia); i16 c=I16_MIN; for (usz i=0; ic)c=xp[i]; rp[i]=c; } decG(x); return r; } - if (xe==el_i32) { i32* xp=i32any_ptr(x); i32* rp; B r=m_i32arrv(&rp, ia); i32 c=I32_MIN; for (usz i=0; ic)c=xp[i]; rp[i]=c; } decG(x); return r; } + #if SINGELI + if (xe==el_i8 ) { i8* rp; B r=m_i8arrv (&rp, ia); avx2_scan_max8 (i8any_ptr (x), rp, ia); decG(x); return r; } + if (xe==el_i16) { i16* rp; B r=m_i16arrv(&rp, ia); avx2_scan_max16(i16any_ptr(x), rp, ia); decG(x); return r; } + if (xe==el_i32) { i32* rp; B r=m_i32arrv(&rp, ia); avx2_scan_max32(i32any_ptr(x), rp, ia); decG(x); return r; } + #else + if (xe==el_i8 ) { i8* xp=i8any_ptr (x); i8* rp; B r=m_i8arrv (&rp, ia); i8 c=I8_MIN ; for (usz i=0; ic)c=xp[i]; rp[i]=c; } decG(x); return r; } + if (xe==el_i16) { i16* xp=i16any_ptr(x); i16* rp; B r=m_i16arrv(&rp, ia); i16 c=I16_MIN; for (usz i=0; ic)c=xp[i]; rp[i]=c; } decG(x); return r; } + if (xe==el_i32) { i32* xp=i32any_ptr(x); i32* rp; B r=m_i32arrv(&rp, ia); i32 c=I32_MIN; for (usz i=0; ic)c=xp[i]; rp[i]=c; } decG(x); return r; } + #endif } if (rtid==n_ne) { // ≠ f64 x0 = IGetU(x,0).f; if (x0!=0 && x0!=1) goto base; diff --git a/src/singeli/src/scan.singeli b/src/singeli/src/scan.singeli index 0bb6e022..d3ca6649 100644 --- a/src/singeli/src/scan.singeli +++ b/src/singeli/src/scan.singeli @@ -4,6 +4,59 @@ include './avx' include './avx2' include './mask' +def sel8{v, t} = sel{[16]u8, v, make{[32]i8, t}} +def sel8{v, t & istup{t} & tuplen{t}==16} = sel8{v, merge{t,t}} + +def base{b,l} = { if (0==tuplen{l}) 0; else tupsel{0,l}+b*base{b,slice{l,1}} } +def shuf{T, v, n & istup{n}} = shuf{T, v, base{4,n}} + +# Associative scan ?` if a?b?a = a?b = b?a, used for ⌊⌈ +avx2_scan_idem{T, op, id}(x:*T, r:*T, len:u64) : void = { + def w = width{T} + + # Within each lane, scan using shifts by powers of 2. First k elements + # when shifting by k don't need to change, so leave them alone. + def shift{k,l} = merge{iota{k},iota{l-k}} + def c8 {k, a} = op{a, shuf{[4]u32, a, shift{k,4}}} + def c32{k, a} = (if (w<=8*k) op{a, sel8{a, shift{k,16}}}; else a) + # Fill last 4 bytes with last element, in each lane + def spread{a} = { + def b = w/8 + if (w<=16) sel8{a,merge{iota{12},(16-b)+iota{4}%b}}; else a + } + # Prefix op on entire AVX register + def pre{a} = { + b:= c8{2, c8{1, c32{2, c32{1, a}}}} + # After lanewise scan, broadcast end of lane 0 to entire lane 1 + op{b, sel{[8]i32, spread{b}, make{[8]i32, 3*(3