From c1a77a24fb26d7662acb6fb4fa1756a3bffadd6e Mon Sep 17 00:00:00 2001 From: dzaima Date: Thu, 3 Nov 2022 15:09:09 +0200 Subject: [PATCH] =?UTF-8?q?fast=20(2=E2=8B=86n)|ints?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/arithd.c | 74 ++++++++++++++++++++++++--------- src/builtins/group.c | 3 +- src/singeli/src/dyarith.singeli | 12 ++++++ test/various.bqn | 19 +++++++++ 4 files changed, 86 insertions(+), 22 deletions(-) diff --git a/src/builtins/arithd.c b/src/builtins/arithd.c index 7e65e2f0..e8992e24 100644 --- a/src/builtins/arithd.c +++ b/src/builtins/arithd.c @@ -18,12 +18,23 @@ B or_c2 (B, B, B); B log_c2(B, B, B); B floor_c2(B, B, B); +typedef void (*AndBytesFn)(u8*, u8*, u64, u64); + #if SINGELI - -#define BCALL(N, X) N(b(X)) -#define interp_f64(X) b(X).f - -#include "../singeli/c/arithdDispatch.c" + #define BCALL(N, X) N(b(X)) + #define interp_f64(X) b(X).f + #include "../singeli/c/arithdDispatch.c" + static AndBytesFn andBytes_fn = avx2_andBytes; +#else + static void base_andBytes(u8* r, u8* x, u64 repeatedMask, u64 numBytes) { + u64* x64 = (u64*)x; usz i; + for (i = 0; i < numBytes/8; i++) ((u64*)r)[i] = x64[i] & repeatedMask; + if (i*8 != numBytes) { + u64 v = x64[i]&repeatedMask; + for (usz j = 0; j < (numBytes&7); j++) r[i*8 + j] = v>>(j*8); + } + } + static AndBytesFn andBytes_fn = base_andBytes; #endif #define ARITH_SLOW(N) SLOWIF((!isArr(w) || TI(w,elType)!=el_B) && (!isArr(x) || TI(x,elType)!=el_B)) SLOW2("arithd " #N, w, x) @@ -62,7 +73,7 @@ B floor_c2(B, B, B); #define DOI16(EXPR,A,W,X,BASE) { Ri16(A) for (usz i=0; i0 && (wi32&(wi32-1))==0) { + if (wi32==1) { Arr* ra=allZeroes(IA(x)); arr_shCopy(ra, x); r = taga(ra); decG(x); return r; } + if (xe==el_bit) return x; // if n>1 (true from the above), 0‿1 ≡ (2⋆n)|0‿1 + u8 elw = elWidth(xe); + u32 mask0 = (u32)wi32; + if (mask0 > (1 << (elw*8-1))) goto bad_sa; // negative numbers in 𝕩 mess with this + u64 mask = (mask0-1)*repeatNum[xe]; + usz bytes = IA(x)*elw; + u8* rp = m_tyarrc(&r, elw, x, el2t(xe)); + andBytes_fn(rp, tyany_ptr(x), mask, bytes); + decG(x); + if (wi32==2) return taga(cpyBitArr(r)); + if (wi32<256) return taga(cpyI8Arr(r)); // these won't widen, as the code doesn't even get to here if 𝕨 > max possible in 𝕩 + if (wi32<32768) return taga(cpyI16Arr(r)); + return r; + } bad_sa:; + ) #undef GC2f @@ -290,11 +324,6 @@ B floor_c2(B, B, B); AR_I_TO_ARR(NAME) \ thrM(CHR ": Unexpected argument types"); \ } -#define AR_F_SCALAR(CHR, NAME, EXPR) B NAME##_c2(B t, B w, B x) { \ - if (isF64(w) & isF64(x)) return m_f64(EXPR); \ - AR_F_TO_ARR(NAME) \ - thrM(CHR ": Unexpected argument types"); \ -} AR_I_SCALAR("+", add, w.f+x.f, { if (isC32(w) & isF64(x)) { u64 r = (u64)(o2cG(w)+o2i64(x)); if(r>CHR_MAX)thrM("+: Invalid character"); return m_c32((u32)r); } @@ -314,6 +343,11 @@ B not_c2(B t, B w, B x) { return add_c2(m_f64(1), m_f64(1), sub_c2(t, w, x)); } +#define AR_F_SCALAR(CHR, NAME, EXPR) B NAME##_c2(B t, B w, B x) { \ + if (isF64(w) & isF64(x)) return m_f64(EXPR); \ + AR_F_TO_ARR(NAME) \ + thrM(CHR ": Unexpected argument types"); \ +} AR_F_SCALAR("÷", div , w.f/x.f) AR_F_SCALAR("⋆", pow , pow(w.f, x.f)) AR_F_SCALAR("√", root , pow(x.f, 1.0/w.f)) diff --git a/src/builtins/group.c b/src/builtins/group.c index 56ca4e67..a18f8b3a 100644 --- a/src/builtins/group.c +++ b/src/builtins/group.c @@ -100,8 +100,7 @@ B group_c2(B t, B w, B x) { u64* mp; B m = m_bitarrv(&mp, xia); u8* wp0 = tyany_ptr(w); we = TI(w,elType); - u8 wew = elWidth(we); - CMP_AA_IMM(ne, we, mp, wp0-wew, wp0, xia); + CMP_AA_IMM(ne, we, mp, wp0-elWidth(we), wp0, xia); bitp_set(mp, 0, -1!=o2fG(IGetU(w,0))); B ind = C1(slash, m); diff --git a/src/singeli/src/dyarith.singeli b/src/singeli/src/dyarith.singeli index ccb9ac61..86ad0786 100644 --- a/src/singeli/src/dyarith.singeli +++ b/src/singeli/src/dyarith.singeli @@ -187,5 +187,17 @@ arithSAf{vw, mode, F, swap, W, X, R}(r:*void, w:u64, x:*void, len:u64) : u64 = { def arithSA{mode, F, swap, W, X, R} = arithSAf{256, mode, F, swap, W, X, R} +andBytes{vw}(r: *u8, x: *u8, maskU64:u64, len:u64) : void = { + assert{vw>=64} + def bulk = vw / width{u8} + def T8 = [bulk]u8 + def T64 = [bulk/8]u64 + maskFull:= T8~~broadcast{T64, maskU64} + maskedLoop{bulk, len, {i, M} => { + storeBatch{r, i, loadBatch{x, i, T8} & maskFull, M} + }} +} + +'avx2_andBytes'=andBytes{256} 'orSAc_f64_f64_f64'=arithSA{2,bqn_or,0,f64,f64,f64} include './../gen/arDefs' \ No newline at end of file diff --git a/test/various.bqn b/test/various.bqn index 5b366332..2589234d 100644 --- a/test/various.bqn +++ b/test/various.bqn @@ -58,6 +58,25 @@ Group ← {𝕊: 1 }¨ ↕ +Mod ← {𝕊: + modOptions ← ⟨∞,¯∞,0÷0⟩ ∾ ∾⟜- 2⋆↕34 + {𝕊: + n ← R 2⋆4+R 6 + w ← R∘≠⊸⊑ modOptions + x ← -⍟(R 2) (2⋆R 34) + (↕n)-R n + got ← w|x + exp ← w|"Ah"V x + ¬exp EEQ got? + •Out "𝕨: "∾•Repr w + •Out "𝕩: "∾(•Repr x)∾" / "∾I x + •Out "exp: "∾•Repr exp + •Out "got: "∾•Repr got + •Exit 1 + ;@ + }¨ ↕𝕩 +} + +•Show "powerOfTwo | arr" ⋄ Mod 100000 •Show "∨`bitarr" ⋄ OrScanBitarr 100000 •Show "+`bitarr" ⋄ PlusScanBitarr 100000