monadic arith

This commit is contained in:
dzaima 2023-01-23 01:22:40 +02:00
parent 7284eb7010
commit 721dd8889b
5 changed files with 104 additions and 36 deletions

View File

@ -514,7 +514,8 @@ cachedBin‿linkerCache ← {
"src/jit/", "nvm.c" "src/jit/", "nvm.c"
"src/utils/", "ryu.c", "utf.c", "hash.c", "file.c", "mut.c", "each.c", "bits.c" "src/utils/", "ryu.c", "utf.c", "hash.c", "file.c", "mut.c", "each.c", "bits.c"
singeliMap {po.arch"aarch64"? 𝕩/˜(1¨𝕩)"cmp""bits""equal""dyarith"; 𝕩} singeliMap {po.arch"aarch64"? 𝕩/˜(1¨𝕩)"cmp""bits""equal""dyarith""monarith"; 𝕩}
"src/builtins/arithm.c""monarith",
"src/core/stuff.c""equal", "src/utils/mut.c""copy", "src/utils/bits.c""bits" "src/core/stuff.c""equal", "src/utils/mut.c""copy", "src/utils/bits.c""bits"
"src/builtins/arithd.c""dyarith", "src/builtins/cmp.c""cmp", "src/builtins/squeeze.c""squeeze" "src/builtins/arithd.c""dyarith", "src/builtins/cmp.c""cmp", "src/builtins/squeeze.c""squeeze"
"src/builtins/select.c""select", "src/builtins/fold.c""fold", "src/builtins/scan.c""scan" "src/builtins/select.c""select", "src/builtins/fold.c""fold", "src/builtins/scan.c""scan"

View File

@ -298,7 +298,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 @"${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 select.c fold.c scan.c neq.c slash.c constrep.c bits.c} build_singeli: ${addprefix src/singeli/gen/, cmp.c dyarith.c monarith.c copy.c equal.c squeeze.c select.c fold.c scan.c neq.c slash.c constrep.c bits.c}
@echo $(postmsg) @echo $(postmsg)
src/singeli/gen/%.c: src/singeli/src/%.singeli preSingeliBin src/singeli/gen/%.c: src/singeli/src/%.singeli preSingeliBin
@echo $< | cut -c 17- | sed 's/^/ /' @echo $< | cut -c 17- | sed 's/^/ /'

View File

@ -22,33 +22,6 @@ B bit_negate(B x) { // consumes
return r; return r;
} }
#define GC1i(SYMB,NAME,FEXPR,IBAD,IEXPR,SQF,TMIN,RMIN) B NAME##_c1(B t, B x) { \
if (isF64(x)) { f64 v = x.f; return m_f64(FEXPR); } \
if (RARE(!isArr(x))) thrM(SYMB ": Expected argument to be a number"); \
u8 xe = TI(x,elType); \
if (xe<=TMIN) return RMIN; \
i64 sz = IA(x); \
if (xe==el_i8) { i8 MAX=I8_MAX; i8 MIN=I8_MIN; i8* xp=i8any_ptr(x); i8* rp; B r=m_i8arrc(&rp,x); \
for (i64 i = 0; i < sz; i++) { i8 v = xp[i]; if (RARE(IBAD)) { decG(r); goto base; } rp[i] = IEXPR; } \
decG(x); (void)MIN;(void)MAX; return r; \
} \
if (xe==el_i16) { i16 MAX=I16_MAX; i16 MIN=I16_MIN; i16* xp=i16any_ptr(x); i16* rp; B r=m_i16arrc(&rp,x); \
for (i64 i = 0; i < sz; i++) { i16 v = xp[i]; if (RARE(IBAD)) { decG(r); goto base; } rp[i] = IEXPR; } \
decG(x); (void)MIN;(void)MAX; return r; \
} \
if (xe==el_i32) { i32 MAX=I32_MAX; i32 MIN=I32_MIN; i32* xp=i32any_ptr(x); i32* rp; B r=m_i32arrc(&rp,x); \
for (i64 i = 0; i < sz; i++) { i32 v = xp[i]; if (RARE(IBAD)) { decG(r); goto base; } rp[i] = IEXPR; } \
decG(x); (void)MIN;(void)MAX; return r; \
} \
if (xe==el_f64) { f64* xp = f64any_ptr(x); \
f64* rp; B r = m_f64arrc(&rp, x); \
for (i64 i = 0; i < sz; i++) { f64 v = xp[i]; rp[i] = FEXPR; } \
decG(x); return SQF? num_squeeze(r) : r; \
} \
base: SLOW1(SYMB"𝕩", x); return arith_recm(NAME##_c1, x); \
}
B add_c1(B t, B x) { B add_c1(B t, B x) {
if (isF64(x)) return x; if (isF64(x)) return x;
if (!isArr(x)) thrM("+: Argument must consist of numbers"); if (!isArr(x)) thrM("+: Argument must consist of numbers");
@ -56,13 +29,69 @@ B add_c1(B t, B x) {
dec(eachm_fn(m_f64(0), inc(x), add_c1)); dec(eachm_fn(m_f64(0), inc(x), add_c1));
return x; return x;
} }
#if SINGELI
#define SINGELI_FILE monarith
#include "../utils/includeSingeli.h"
#endif
GC1i("-", sub, -v, v== MIN, -v, 0, el_bit, bit_sel(x,m_f64(0),m_f64(-1))) // change icond to v==-v to support ¯0 (TODO that won't work for i8/i16) #define GC1i(SYMB,NAME,FEXPR,TMIN,RMIN,MAIN) B NAME##_c1(B t, B x) { \
GC1i("|", stile, fabs(v), v== MIN, v<0?-v:v,0, el_bit, x) if (isF64(x)) { f64 v = x.f; return m_f64(FEXPR); } \
GC1i("", floor, floor(v), 0, v, 1, el_i32, x) if (RARE(!isArr(x))) thrM(SYMB ": Expected argument to be a number"); \
GC1i("", ceil, ceil(v), 0, v, 1, el_i32, x) u8 xe = TI(x,elType); \
GC1i("×", mul, v==0?0:v>0?1:-1, 0,v==0?0:v>0?1:-1,1, el_bit, x) if (elNum(xe)) { \
GC1i("¬", not, 1-v, v<=-MAX, 1-v, 0, el_bit, bit_negate(x)) if (xe<=TMIN) return RMIN; \
MAIN(FEXPR) \
} \
SLOW1(SYMB"𝕩", x); return arith_recm(NAME##_c1, x); \
}
#define LOOP_BODY(INIT, EXPR, POST) { \
i64 ia = IA(x); INIT; \
void* xp = tyany_ptr(x); \
switch(xe) { default: UD; \
case el_i8: for(usz i=0; i<ia; i++) { i8 c = ((i8* )xp)[i]; EXPR(i8, c==I8_MIN) } break; \
case el_i16: for(usz i=0; i<ia; i++) { i16 c = ((i16*)xp)[i]; EXPR(i16, c==I16_MIN) } break; \
case el_i32: for(usz i=0; i<ia; i++) { i32 c = ((i32*)xp)[i]; EXPR(i32, c==I32_MIN) } break; \
case el_f64: for(usz i=0; i<ia; i++) { f64 c = ((f64*)xp)[i]; EXPR(f64, 0) } break; \
} \
decG(x); return r; POST \
}
#define SIGN_EXPR(T, C) rp[i] = c>0? 1 : c==0? 0 : -1;
#define SIGN_MAIN(FEXPR) LOOP_BODY(i8* rp; B r=m_i8arrc(&rp,x);, SIGN_EXPR,)
#if SINGELI
#define STILE_BODY(FEXPR) { usz ia = IA(x); B r; retry: \
void* rp = m_tyarrlc(&r, elWidth(xe), x, el2t(xe)); \
u64 got = simd_abs[xe-el_i8](rp, tyany_ptr(x), ia); \
if (LIKELY(got==ia)) { decG(x); return r; } \
tyarr_freeF(v(r)); \
xe++;if (xe==el_i16) x=taga(cpyI16Arr(x)); \
else if (xe==el_i32) x=taga(cpyI32Arr(x)); \
else x=taga(cpyF64Arr(x)); \
goto retry; \
}
#else
#define STILE_EXPR(T, C) if(C) goto bad; ((T*)rp)[i] = c>=0? c : -c;
#define STILE_BODY(FEXPR) LOOP_BODY(B r; void* rp = m_tyarrlc(&r, elWidth(xe), x, el2t(xe));, STILE_EXPR, bad: tyarr_freeF(v(r));)
#endif
#define FLOAT_BODY(FEXPR) { i64 ia = IA(x); \
assert(xe==el_f64); f64* xp = f64any_ptr(x); \
f64* rp; B r = m_f64arrc(&rp, x); \
for (usz i = 0; i < ia; i++) { f64 v=xp[i]; rp[i]=FEXPR; } \
decG(x); return num_squeeze(r); \
}
B sub_c2(B,B,B);
#define SUB_BODY(FEXPR) return sub_c2(t, m_f64(0), x);
#define NOT_BODY(FEXPR) x = num_squeezeChk(x); return TI(x,elType)==el_bit? bit_negate(x) : sub_c2(m_f64(0), m_f64(1), x);
GC1i("-", sub, -v, el_bit, bit_sel(x,m_f64(0),m_f64(-1)), SUB_BODY)
GC1i("|", stile, fabs(v), el_bit, x, STILE_BODY)
GC1i("", floor, floor(v), el_i32, x, FLOAT_BODY)
GC1i("", ceil, ceil(v), el_i32, x, FLOAT_BODY)
GC1i("×", mul, v==0?0:v>0?1:-1, el_bit, x, SIGN_MAIN)
GC1i("¬", not, 1-v, el_bit, bit_negate(x), NOT_BODY)
#define GC1f(N, F, MSG) B N##_c1(B t, B x) { \ #define GC1f(N, F, MSG) B N##_c1(B t, B x) { \
if (isF64(x)) { f64 xv=o2fG(x); return m_f64(F); } \ if (isF64(x)) { f64 xv=o2fG(x); return m_f64(F); } \
@ -86,6 +115,16 @@ GC1i("¬", not, 1-v, v<=-MAX, 1-v, 0, el_bit, bit_negate(x))
GC1f( div, 1/xv, "÷: Getting reciprocal of non-number") GC1f( div, 1/xv, "÷: Getting reciprocal of non-number")
GC1f(root, sqrt(xv), "√: Getting square root of non-number") GC1f(root, sqrt(xv), "√: Getting square root of non-number")
#undef GC1i
#undef LOOP_BODY
#undef SIGN_EXPR
#undef SIGN_MAIN
#undef STILE_BODY
#undef STILE_EXPR
#undef STILE_BODY
#undef FLOAT_BODY
#undef SUB_BODY
#undef NOT_BODY
#undef GC1f #undef GC1f
f64 fact(f64 x) { return tgamma(x+1); } f64 fact(f64 x) { return tgamma(x+1); }

View File

@ -164,7 +164,7 @@ def arithAAimpl{vw, mode, F, W, X, R, w, x, r, len} = {
def run = runner{match{overflow, 0}, R, F} def run = runner{match{overflow, 0}, R, F}
def unr = tern{mode==0, 2, 1} # 2x unroll non-overflowing cases; surpresses clang's default unrolling, which unrolls a lot more; 2x appears to be plenty def unr = tern{mode==0, 2, 1} # 2x unroll non-overflowing cases; suppresses clang's default unrolling, which unrolls a lot more; 2x appears to be plenty
muLoop{bulk, unr, len, {is, M} => { muLoop{bulk, unr, len, {is, M} => {
def cw = loadBatch{*W~~w, is, ty_sc{W, TY}} def cw = loadBatch{*W~~w, is, ty_sc{W, TY}}
def cx = loadBatch{*X~~x, is, ty_sc{X, TY}} def cx = loadBatch{*X~~x, is, ty_sc{X, TY}}

View File

@ -0,0 +1,28 @@
include './base'
include './f64'
include './cbqnDefs'
if (hasarch{'X86_64'}) {
include './sse3'
include './avx'
include './avx2'
} else if (hasarch{'AARCH64'}) {
include './neon'
}
include './bitops'
include './mask'
absFn{T}(r:*void, x:*void, len:u64) : u64 = {
def bulk = arch_defvw/width{T}
def VT = [bulk]T
muLoop{bulk, tern{T==f64, 2, 1}, len, {is, M} => {
def cx = loadBatch{*T~~x, is, VT}
if (T!=f64 and homAny{M{tree_fold{&, eachx{==, cx, VT**minvalue{T}}}}}) return{tupsel{0,is}*bulk}
storeBatch{*T~~r, is, each{abs, cx}, M}
}}
len
}
def tup_abs = each{{T}=>absFn{T}, tup{i8, i16, i32, f64}}
t_abs:*type{tupsel{0,tup_abs}} = tup_abs
'simd_abs' = t_abs