Singeli min/max-fold
This commit is contained in:
parent
4b9a21c75f
commit
52608ba6ce
2
makefile
2
makefile
@ -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/^/ /'
|
||||
|
||||
@ -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 };
|
||||
|
||||
41
src/singeli/src/fold.singeli
Normal file
41
src/singeli/src/fold.singeli
Normal 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}
|
||||
Loading…
Reference in New Issue
Block a user