From fded6996e682f6290263b687b53d0b59311c6f57 Mon Sep 17 00:00:00 2001 From: dzaima Date: Thu, 9 Sep 2021 16:59:47 +0300 Subject: [PATCH] squeeze & hash fixes --- README.md | 2 +- src/builtins/internal.c | 2 +- src/core/fillarr.c | 47 +++---------------- src/core/stuff.c | 100 +++++++++++++++++++++++++++++----------- src/core/stuff.h | 4 +- src/h.h | 3 +- src/utils/hash.h | 17 +++---- 7 files changed, 95 insertions(+), 80 deletions(-) diff --git a/README.md b/README.md index e523696e..3b3629b4 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Build & run (tl;dr: `make; rlwrap ./BQN`): 2. If wanted, customize settings in `src/h.h` 3. `make` - Options: `make o3` (the default), `make debug` (more presets exist for more specific debugging) - - `make CC=gcc` can be used to compile with gcc + - `make CC=gcc` can be used to compile with gcc. Otherwise, `clang` is used. - Do `make clean` or `make t=[o3|debug|…] clean` beforehand to force recompile - `make single-(o3|o3g|debug|c)` compile everything as a single translation unit and thus will compile slower, but allows specifying extra compiler arguments with `make f='…' single-…` and allows the compiler to optimize more 4. `./BQN` (or `rlwrap ./BQN` for a better REPL; see `./BQN --help` for more options) diff --git a/src/builtins/internal.c b/src/builtins/internal.c index 58cdf042..8ff39486 100644 --- a/src/builtins/internal.c +++ b/src/builtins/internal.c @@ -24,7 +24,7 @@ B refc_c1(B t, B x) { } B squeeze_c1(B t, B x) { if (!isArr(x)) return x; - return bqn_squeeze(x); + return any_squeeze(x); } B isPure_c1(B t, B x) { B r = m_f64(isPureFn(x)); diff --git a/src/core/fillarr.c b/src/core/fillarr.c index 3ce14a5d..fe46bd44 100644 --- a/src/core/fillarr.c +++ b/src/core/fillarr.c @@ -130,48 +130,15 @@ B withFill(B x, B fill) { // consumes both } usz ia = a(x)->ia; if (isNum(fill)) { - B* xp = arr_bptr(x); - if (xp==NULL) goto base; - usz i = 0; - i32 or = 0; - for (; i < ia; i++) { - if (!q_i32(xp[i])) goto n_i32; - i32 c = o2iu(xp[i]); - or|= c<0?-c:c; // using or as a heuristical max - } - if (or<=I8_MAX) { - i8* rp; B r = m_i8arrc(&rp, x); - for (usz i = 0; i < ia; i++) rp[i] = o2iu(xp[i]); - dec(x); return r; - } else if (or<=I16_MAX) { - i16* rp; B r = m_i16arrc(&rp, x); - for (usz i = 0; i < ia; i++) rp[i] = o2iu(xp[i]); - dec(x); return r; - } else { - i32* rp; B r = m_i32arrc(&rp, x); - for (usz i = 0; i < ia; i++) rp[i] = o2iu(xp[i]); - dec(x); return r; - } - - n_i32:; - while (i < ia) if (!isF64(xp[i++])) goto base; - - f64* rp; B r = m_f64arrc(&rp, x); - for (usz i = 0; i < ia; i++) rp[i] = o2f(xp[i]); - dec(x); return r; - + B r = num_squeeze(x); + if (TI(r,elType)<=el_f64) return r; + x = r; } else if (isC32(fill)) { - u32* rp; B r = m_c32arrc(&rp, x); - BS2B xgetU = TI(x,getU); - for (usz i = 0; i < ia; i++) { - B c = xgetU(x, i); - if (!isC32(c)) { dec(r); goto base; } - rp[i] = o2c(c); - } - dec(x); - return r; + B r = chr_squeeze(x); + u8 re = TI(r,elType); + if (re>=el_c8 && re<=el_c32) return r; + x = r; } - base:; FillArr* r = m_arr(fsizeof(FillArr,a,B,ia), t_fillarr, ia); arr_shCopy((Arr*)r, x); r->fill = fill; diff --git a/src/core/stuff.c b/src/core/stuff.c index 76d37fa8..3a4a372d 100644 --- a/src/core/stuff.c +++ b/src/core/stuff.c @@ -472,39 +472,83 @@ bool isPureFn(B x) { // doesn't consume } else return isNum(x) || isC32(x); } -B bqn_squeeze(B x) { // consumes +B num_squeeze(B x) { + usz ia = a(x)->ia; + u8 xe = TI(x,elType); + assert(xe!=el_bit); + + if (xe==el_i8) return x; + // TODO fast paths for xe<=el_f64 + usz i = 0; + i32 or = 0; + + B* xp = arr_bptr(x); + if (xp!=NULL) { + for (; i < ia; i++) { + if (!q_i32(xp[i])) goto n_i32; + i32 c = o2iu(xp[i]); + or|= c<0?-c:c; // using or as a heuristical max + } + if (or<=I8_MAX ) { i8* rp; B r = m_i8arrc (&rp, x); for (usz i=0;iia; + u8 xe = TI(x,elType); + if (xe==el_c8) return x; + // TODO fast paths for xe == el_c8/el_c16/el_c32 + usz i = 0; + i32 or = 0; + + B* xp = arr_bptr(x); + if (xp!=NULL) { + for (; i < ia; i++) { + if (!isC32(xp[i])) return x; + or|= o2cu(xp[i]); + } + if (or<=U8_MAX ) { u8* rp; B r = m_c8arrc (&rp, x); for (usz i=0;iia; - if (ia==0) return x; - if (xe==el_f64) { - f64* xp = f64any_ptr(x); - for (usz i = 0; i < ia; i++) if (xp[i] != (f64)(i32)xp[i]) return x; - return taga(toI32Arr(x)); - } - assert(xe==el_B); + assert(xe!=el_bit); + if (a(x)->ia==0) return x; BS2B xgetU = TI(x,getU); B x0 = xgetU(x, 0); - if (isNum(x0)) { - for (usz i = 0; i < ia; i++) { - B c = xgetU(x, i); - if (!isNum(c)) return x; - if (!q_i32(c)) { - for (i++; i < ia; i++) if (!isNum(xgetU(x, i))) return x; - return taga(toF64Arr(x)); - } - } - return taga(toI32Arr(x)); - } else if (isC32(x0)) { - for (usz i = 1; i < ia; i++) { - B c = xgetU(x, i); - if (!isC32(c)) return x; - } - return taga(toC32Arr(x)); - } else return x; + if (isNum(x0)) return num_squeeze(x); + else if (isC32(x0)) return chr_squeeze(x); + return x; } -B bqn_merge(B x) { // consumes +B bqn_merge(B x) { assert(isArr(x)); usz xia = a(x)->ia; ur xr = rnk(x); diff --git a/src/core/stuff.h b/src/core/stuff.h index f5125a20..b0f6884d 100644 --- a/src/core/stuff.h +++ b/src/core/stuff.h @@ -124,7 +124,9 @@ char* format_pm1(u8 u); char* format_pm2(u8 u); bool isPureFn(B x); // doesn't consume B bqn_merge(B x); // consumes -B bqn_squeeze(B x); // consumes +B any_squeeze(B x); // consumes; accepts any array, returns one with the smallest type (doesn't recurse!) +B num_squeeze(B x); // consumes; +B chr_squeeze(B x); // consumes B def_getU(B x, usz n); B def_fn_uc1(B t, B o, B x); B def_fn_ucw(B t, B o, B w, B x); diff --git a/src/h.h b/src/h.h index 047025e7..4a740a8e 100644 --- a/src/h.h +++ b/src/h.h @@ -108,6 +108,7 @@ #define I32_MAX 2147483647 #define I64_MIN ((i64)(1ULL<<63)) #define CHR_MAX 1114111 +#define U8_MAX ((u8 )~(u8 )0) #define U16_MAX ((u16)~(u16)0) #define U32_MAX ((u32)~(u32)0) #define NOINLINE __attribute__((noinline)) @@ -542,7 +543,7 @@ static inline u64 nsTime() { static u8 fillElType(B x) { - if (isNum(x)) return el_i32; + if (isNum(x)) return el_i32; // TODO move to 8 if (isC32(x)) return el_c32; return el_B; } diff --git a/src/utils/hash.h b/src/utils/hash.h index 8b6ba998..84d53308 100644 --- a/src/utils/hash.h +++ b/src/utils/hash.h @@ -12,18 +12,19 @@ static u64 bqn_hash(B x, const u64 secret[4]) { // doesn't consume return wyhash64(secret[2], x.u); } inc(x); - x = bqn_squeeze(x); + x = any_squeeze(x); u64 shHash = wyhash(a(x)->sh, rnk(x)*sizeof(usz), 0, secret); u8 xe = TI(x,elType); usz xia = a(x)->ia; u64 r; - if (xe==el_i32) { - r = wyhash(i32any_ptr(x), xia*4, shHash, secret); - } else if (xe==el_c32) { - r = wyhash(c32any_ptr(x), xia*4, shHash, secret); - } else if (xe==el_f64) { - r = wyhash(f64any_ptr(x), xia*8, shHash, secret); - } else { + if (xe==el_i8 ) { r = wyhash(i8any_ptr (x), xia*1, shHash, secret); } + else if (xe==el_i16) { r = wyhash(i16any_ptr(x), xia*2, shHash, secret); } + else if (xe==el_i32) { r = wyhash(i32any_ptr(x), xia*4, shHash, secret); } + else if (xe==el_c8 ) { r = wyhash(c8any_ptr (x), xia*1, shHash, secret); } + else if (xe==el_c16) { r = wyhash(c16any_ptr(x), xia*2, shHash, secret); } + else if (xe==el_c32) { r = wyhash(c32any_ptr(x), xia*4, shHash, secret); } + else if (xe==el_f64) { r = wyhash(f64any_ptr(x), xia*8, shHash, secret); } + else { assert(xe==el_B); TALLOC(u64, data, xia); BS2B xgetU = TI(x,getU);