Singeli min/max-fold

This commit is contained in:
Marshall Lochbaum 2022-11-21 11:47:50 -05:00
parent 4b9a21c75f
commit 52608ba6ce
3 changed files with 56 additions and 2 deletions

View File

@ -271,7 +271,7 @@ endif
@${MAKE} i_singeli=0 singeli=0 force_build_dir=build/obj/presingeli REPLXX=0 f= lf= postmsg="singeli sources:" i_t=presingeli i_f='-O1 -DPRE_SINGELI' FFI=0 OUTPUT=build/obj/presingeli/BQN c
build_singeli: ${addprefix src/singeli/gen/, cmp.c dyarith.c copy.c equal.c squeeze.c scan.c neq.c slash.c constrep.c bits.c}
build_singeli: ${addprefix src/singeli/gen/, cmp.c dyarith.c copy.c equal.c squeeze.c fold.c scan.c neq.c slash.c constrep.c bits.c}
@echo $(postmsg)
src/singeli/gen/%.c: src/singeli/src/%.singeli preSingeliBin
@echo $< | cut -c 17- | sed 's/^/ /'

View File

@ -1,6 +1,13 @@
#include "../core.h"
#include "../builtins.h"
#if SINGELI
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
#include "../singeli/gen/fold.c"
#pragma GCC diagnostic pop
#endif
static bool fold_ne(u64* x, u64 am) {
u64 r = 0;
for (u64 i = 0; i < (am>>6); i++) r^= x[i];
@ -55,7 +62,13 @@ static f64 (*const sum_fns[])(void*, usz, f64) = { sum_i8, sum_i16, sum_i32, sum
#define DEF_MIN_MAX(T) \
static f64 min_##T(void* xv, usz ia) { MIN_MAX(T,<) } \
static f64 max_##T(void* xv, usz ia) { MIN_MAX(T,>) }
DEF_MIN_MAX(i8) DEF_MIN_MAX(i16) DEF_MIN_MAX(i32) DEF_MIN_MAX(f64)
DEF_MIN_MAX(i8) DEF_MIN_MAX(i16) DEF_MIN_MAX(i32)
#if SINGELI
static f64 min_f64(void* xv, usz ia) { return avx2_fold_min_f64(xv,ia); }
static f64 max_f64(void* xv, usz ia) { return avx2_fold_max_f64(xv,ia); }
#else
DEF_MIN_MAX(f64)
#endif
#undef DEF_MIN_MAX
#undef MIN_MAX
static f64 (*const min_fns[])(void*, usz) = { min_i8, min_i16, min_i32, min_f64 };

View File

@ -0,0 +1,41 @@
include './base'
include './sse3'
include './avx'
include './avx2'
include './mask'
fold_idem{T==f64, op}(x:*T, len:u64) : T = {
def step = 256/width{T}
def V = [step]T
xv:= *V ~~ x
r:V = broadcast{[4]f64, 0}
if (len < step) {
# Can't overlap like the long case
assert{len > 0}
r = load{xv}
if (len > 1) {
if (len > 2) r = op{r, shuf{[4]u64, r, 4b2222}}
r = op{r, shuf{[4]u64, r, 4b1111}}
}
} else {
# Pairwise combination to shorten dependency chains
def pairwise{p, i, k} = {
def l = k-1
op{pairwise{p, i , l},
pairwise{p, i+(1<<l), l}}
}
def pairwise{p, i, k==0} = load{p, i}
def pk = 2 # Combine 1<<pk values in a step
r = load{*V ~~ (x+len-step)}
e:= (len-1)/step
f:= e >> pk
@for (i to f) r = op{r, pairwise{xv+(i<<pk), 0, pk}}
@for (xv over i from f<<pk to e) r = op{r, xv}
r = op{r, shuf{[4]u64, r, 4b2301}}
r = op{r, shuf{[4]u64, r, 4b1032}}
}
extract{r, 0}
}
'avx2_fold_min_f64' = fold_idem{f64,min}
'avx2_fold_max_f64' = fold_idem{f64,max}