squeeze & hash fixes
This commit is contained in:
parent
a6251ff3e7
commit
fded6996e6
@ -4,7 +4,7 @@ Build & run (tl;dr: `make; rlwrap ./BQN`):
|
|||||||
2. If wanted, customize settings in `src/h.h`
|
2. If wanted, customize settings in `src/h.h`
|
||||||
3. `make`
|
3. `make`
|
||||||
- Options: `make o3` (the default), `make debug` (more presets exist for more specific debugging)
|
- 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
|
- 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
|
- `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)
|
4. `./BQN` (or `rlwrap ./BQN` for a better REPL; see `./BQN --help` for more options)
|
||||||
|
|||||||
@ -24,7 +24,7 @@ B refc_c1(B t, B x) {
|
|||||||
}
|
}
|
||||||
B squeeze_c1(B t, B x) {
|
B squeeze_c1(B t, B x) {
|
||||||
if (!isArr(x)) return x;
|
if (!isArr(x)) return x;
|
||||||
return bqn_squeeze(x);
|
return any_squeeze(x);
|
||||||
}
|
}
|
||||||
B isPure_c1(B t, B x) {
|
B isPure_c1(B t, B x) {
|
||||||
B r = m_f64(isPureFn(x));
|
B r = m_f64(isPureFn(x));
|
||||||
|
|||||||
@ -130,48 +130,15 @@ B withFill(B x, B fill) { // consumes both
|
|||||||
}
|
}
|
||||||
usz ia = a(x)->ia;
|
usz ia = a(x)->ia;
|
||||||
if (isNum(fill)) {
|
if (isNum(fill)) {
|
||||||
B* xp = arr_bptr(x);
|
B r = num_squeeze(x);
|
||||||
if (xp==NULL) goto base;
|
if (TI(r,elType)<=el_f64) return r;
|
||||||
usz i = 0;
|
x = r;
|
||||||
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;
|
|
||||||
|
|
||||||
} else if (isC32(fill)) {
|
} else if (isC32(fill)) {
|
||||||
u32* rp; B r = m_c32arrc(&rp, x);
|
B r = chr_squeeze(x);
|
||||||
BS2B xgetU = TI(x,getU);
|
u8 re = TI(r,elType);
|
||||||
for (usz i = 0; i < ia; i++) {
|
if (re>=el_c8 && re<=el_c32) return r;
|
||||||
B c = xgetU(x, i);
|
x = r;
|
||||||
if (!isC32(c)) { dec(r); goto base; }
|
|
||||||
rp[i] = o2c(c);
|
|
||||||
}
|
}
|
||||||
dec(x);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
base:;
|
|
||||||
FillArr* r = m_arr(fsizeof(FillArr,a,B,ia), t_fillarr, ia);
|
FillArr* r = m_arr(fsizeof(FillArr,a,B,ia), t_fillarr, ia);
|
||||||
arr_shCopy((Arr*)r, x);
|
arr_shCopy((Arr*)r, x);
|
||||||
r->fill = fill;
|
r->fill = fill;
|
||||||
|
|||||||
100
src/core/stuff.c
100
src/core/stuff.c
@ -472,39 +472,83 @@ bool isPureFn(B x) { // doesn't consume
|
|||||||
} else return isNum(x) || isC32(x);
|
} 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;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++])) return x;
|
||||||
|
f64* rp; B r = m_f64arrc(&rp, x); for (usz i=0;i<ia;i++) rp[i]=o2fu(xp[i]); dec(x); return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
BS2B xgetU = TI(x,getU);
|
||||||
|
for (; i < ia; i++) {
|
||||||
|
B cr = xgetU(x,i);
|
||||||
|
if (!q_i32(cr)) goto n_i32_2;
|
||||||
|
i32 c = o2iu(cr);
|
||||||
|
or|= c<0?-c:c;
|
||||||
|
}
|
||||||
|
if (or<=I8_MAX ) { i8* rp; B r = m_i8arrc (&rp, x); for (usz i=0;i<ia;i++) rp[i]=o2iu(xgetU(x,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(xgetU(x,i)); dec(x); return r; }
|
||||||
|
else { i32* rp; B r = m_i32arrc(&rp, x); for (usz i=0;i<ia;i++) rp[i]=o2iu(xgetU(x,i)); dec(x); return r; }
|
||||||
|
n_i32_2: while (i<ia) if (!isF64(xgetU(x,i++))) return x;
|
||||||
|
f64* rp; B r = m_f64arrc(&rp, x); for (usz i=0;i<ia;i++) rp[i]=o2fu(xgetU(x,i)); dec(x); return r;
|
||||||
|
}
|
||||||
|
B chr_squeeze(B x) {
|
||||||
|
usz ia = a(x)->ia;
|
||||||
|
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;i<ia;i++) rp[i]=o2cu(xp[i]); dec(x); return r; }
|
||||||
|
else if (or<=U16_MAX) { u16* rp; B r = m_c16arrc(&rp, x); for (usz i=0;i<ia;i++) rp[i]=o2cu(xp[i]); dec(x); return r; }
|
||||||
|
else { u32* rp; B r = m_c32arrc(&rp, x); for (usz i=0;i<ia;i++) rp[i]=o2cu(xp[i]); dec(x); return r; }
|
||||||
|
}
|
||||||
|
BS2B xgetU = TI(x,getU);
|
||||||
|
for (; i < ia; i++) {
|
||||||
|
B cr = xgetU(x,i);
|
||||||
|
if (!isC32(cr)) return x;
|
||||||
|
or|= o2cu(cr);
|
||||||
|
}
|
||||||
|
if (or<=U8_MAX ) { u8* rp; B r = m_c8arrc (&rp, x); for (usz i=0;i<ia;i++) rp[i]=o2cu(xgetU(x,i)); dec(x); return r; }
|
||||||
|
else if (or<=U16_MAX) { u16* rp; B r = m_c16arrc(&rp, x); for (usz i=0;i<ia;i++) rp[i]=o2cu(xgetU(x,i)); dec(x); return r; }
|
||||||
|
else { u32* rp; B r = m_c32arrc(&rp, x); for (usz i=0;i<ia;i++) rp[i]=o2cu(xgetU(x,i)); dec(x); return r; }
|
||||||
|
}
|
||||||
|
B any_squeeze(B x) {
|
||||||
assert(isArr(x));
|
assert(isArr(x));
|
||||||
u8 xe = TI(x,elType);
|
u8 xe = TI(x,elType);
|
||||||
if (xe==el_i32 || xe==el_c32) return x;
|
assert(xe!=el_bit);
|
||||||
usz ia = a(x)->ia;
|
if (a(x)->ia==0) return x;
|
||||||
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);
|
|
||||||
BS2B xgetU = TI(x,getU);
|
BS2B xgetU = TI(x,getU);
|
||||||
B x0 = xgetU(x, 0);
|
B x0 = xgetU(x, 0);
|
||||||
if (isNum(x0)) {
|
if (isNum(x0)) return num_squeeze(x);
|
||||||
for (usz i = 0; i < ia; i++) {
|
else if (isC32(x0)) return chr_squeeze(x);
|
||||||
B c = xgetU(x, i);
|
return x;
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
}
|
B bqn_merge(B 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;
|
|
||||||
}
|
|
||||||
B bqn_merge(B x) { // consumes
|
|
||||||
assert(isArr(x));
|
assert(isArr(x));
|
||||||
usz xia = a(x)->ia;
|
usz xia = a(x)->ia;
|
||||||
ur xr = rnk(x);
|
ur xr = rnk(x);
|
||||||
|
|||||||
@ -124,7 +124,9 @@ char* format_pm1(u8 u);
|
|||||||
char* format_pm2(u8 u);
|
char* format_pm2(u8 u);
|
||||||
bool isPureFn(B x); // doesn't consume
|
bool isPureFn(B x); // doesn't consume
|
||||||
B bqn_merge(B x); // consumes
|
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_getU(B x, usz n);
|
||||||
B def_fn_uc1(B t, B o, B x);
|
B def_fn_uc1(B t, B o, B x);
|
||||||
B def_fn_ucw(B t, B o, B w, B x);
|
B def_fn_ucw(B t, B o, B w, B x);
|
||||||
|
|||||||
3
src/h.h
3
src/h.h
@ -108,6 +108,7 @@
|
|||||||
#define I32_MAX 2147483647
|
#define I32_MAX 2147483647
|
||||||
#define I64_MIN ((i64)(1ULL<<63))
|
#define I64_MIN ((i64)(1ULL<<63))
|
||||||
#define CHR_MAX 1114111
|
#define CHR_MAX 1114111
|
||||||
|
#define U8_MAX ((u8 )~(u8 )0)
|
||||||
#define U16_MAX ((u16)~(u16)0)
|
#define U16_MAX ((u16)~(u16)0)
|
||||||
#define U32_MAX ((u32)~(u32)0)
|
#define U32_MAX ((u32)~(u32)0)
|
||||||
#define NOINLINE __attribute__((noinline))
|
#define NOINLINE __attribute__((noinline))
|
||||||
@ -542,7 +543,7 @@ static inline u64 nsTime() {
|
|||||||
|
|
||||||
|
|
||||||
static u8 fillElType(B x) {
|
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;
|
if (isC32(x)) return el_c32;
|
||||||
return el_B;
|
return el_B;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,18 +12,19 @@ static u64 bqn_hash(B x, const u64 secret[4]) { // doesn't consume
|
|||||||
return wyhash64(secret[2], x.u);
|
return wyhash64(secret[2], x.u);
|
||||||
}
|
}
|
||||||
inc(x);
|
inc(x);
|
||||||
x = bqn_squeeze(x);
|
x = any_squeeze(x);
|
||||||
u64 shHash = wyhash(a(x)->sh, rnk(x)*sizeof(usz), 0, secret);
|
u64 shHash = wyhash(a(x)->sh, rnk(x)*sizeof(usz), 0, secret);
|
||||||
u8 xe = TI(x,elType);
|
u8 xe = TI(x,elType);
|
||||||
usz xia = a(x)->ia;
|
usz xia = a(x)->ia;
|
||||||
u64 r;
|
u64 r;
|
||||||
if (xe==el_i32) {
|
if (xe==el_i8 ) { r = wyhash(i8any_ptr (x), xia*1, shHash, secret); }
|
||||||
r = wyhash(i32any_ptr(x), xia*4, shHash, secret);
|
else if (xe==el_i16) { r = wyhash(i16any_ptr(x), xia*2, shHash, secret); }
|
||||||
} else if (xe==el_c32) {
|
else if (xe==el_i32) { r = wyhash(i32any_ptr(x), xia*4, shHash, secret); }
|
||||||
r = wyhash(c32any_ptr(x), xia*4, shHash, secret);
|
else if (xe==el_c8 ) { r = wyhash(c8any_ptr (x), xia*1, shHash, secret); }
|
||||||
} else if (xe==el_f64) {
|
else if (xe==el_c16) { r = wyhash(c16any_ptr(x), xia*2, shHash, secret); }
|
||||||
r = wyhash(f64any_ptr(x), xia*8, shHash, secret);
|
else if (xe==el_c32) { r = wyhash(c32any_ptr(x), xia*4, shHash, secret); }
|
||||||
} else {
|
else if (xe==el_f64) { r = wyhash(f64any_ptr(x), xia*8, shHash, secret); }
|
||||||
|
else {
|
||||||
assert(xe==el_B);
|
assert(xe==el_B);
|
||||||
TALLOC(u64, data, xia);
|
TALLOC(u64, data, xia);
|
||||||
BS2B xgetU = TI(x,getU);
|
BS2B xgetU = TI(x,getU);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user