hashmaps, fast ⊐
This commit is contained in:
parent
2ed797ce16
commit
b8fe149d1f
@ -38,7 +38,7 @@ B m_c32slice(B p, u32* ptr) {
|
||||
}
|
||||
|
||||
|
||||
u32* c32arr_ptr(B x) { VT(x, t_c32arr); return c(C32Arr,x)->a; }
|
||||
u32* c32arr_ptr(B x) { VTY(x, t_c32arr); return c(C32Arr,x)->a; }
|
||||
u32* c32any_ptr(B x) { assert(isArr(x)); u8 t=v(x)->type; if(t==t_c32arr) return c(C32Arr,x)->a; assert(t==t_c32slice); return c(C32Slice,x)->a; }
|
||||
|
||||
B m_str8(usz sz, char* s) {
|
||||
@ -84,8 +84,8 @@ bool eqStr(B w, u32* x) {
|
||||
B c32arr_slice (B x, usz s) {return m_c32slice(x , c(C32Arr ,x)->a+s); }
|
||||
B c32slice_slice(B x, usz s) { B r = m_c32slice(inc(c(Slice,x)->p), c(C32Slice,x)->a+s); dec(x); return r; }
|
||||
|
||||
B c32arr_get (B x, usz n) { VT(x,t_c32arr ); return m_c32(c(C32Arr ,x)->a[n]); }
|
||||
B c32slice_get(B x, usz n) { VT(x,t_c32slice); return m_c32(c(C32Slice,x)->a[n]); }
|
||||
B c32arr_get (B x, usz n) { VTY(x,t_c32arr ); return m_c32(c(C32Arr ,x)->a[n]); }
|
||||
B c32slice_get(B x, usz n) { VTY(x,t_c32slice); return m_c32(c(C32Slice,x)->a[n]); }
|
||||
void c32arr_free(Value* x) { decSh(x); }
|
||||
bool c32arr_canStore(B x) { return isC32(x); }
|
||||
|
||||
|
||||
@ -38,7 +38,7 @@ B m_f64slice(B p, f64* ptr) {
|
||||
}
|
||||
|
||||
|
||||
f64* f64arr_ptr(B x) { VT(x, t_f64arr); return c(F64Arr,x)->a; }
|
||||
f64* f64arr_ptr(B x) { VTY(x, t_f64arr); return c(F64Arr,x)->a; }
|
||||
f64* f64any_ptr(B x) { assert(isArr(x)); u8 t=v(x)->type; if(t==t_f64arr) return c(F64Arr,x)->a; assert(t==t_f64slice); return c(F64Slice,x)->a; }
|
||||
|
||||
NOINLINE B m_caf64(usz sz, f64* a) {
|
||||
@ -61,8 +61,8 @@ F64Arr* toF64Arr(B x) {
|
||||
B f64arr_slice (B x, usz s) {return m_f64slice(x , c(F64Arr ,x)->a+s); }
|
||||
B f64slice_slice(B x, usz s) { B r = m_f64slice(inc(c(Slice,x)->p), c(F64Slice,x)->a+s); dec(x); return r; }
|
||||
|
||||
B f64arr_get (B x, usz n) { VT(x,t_f64arr ); return m_f64(c(F64Arr ,x)->a[n]); }
|
||||
B f64slice_get(B x, usz n) { VT(x,t_f64slice); return m_f64(c(F64Slice,x)->a[n]); }
|
||||
B f64arr_get (B x, usz n) { VTY(x,t_f64arr ); return m_f64(c(F64Arr ,x)->a[n]); }
|
||||
B f64slice_get(B x, usz n) { VTY(x,t_f64slice); return m_f64(c(F64Slice,x)->a[n]); }
|
||||
void f64arr_free(Value* x) { decSh(x); }
|
||||
bool f64arr_canStore(B x) { return q_f64(x); }
|
||||
|
||||
|
||||
@ -73,15 +73,15 @@ B m_fillslice(B p, B* ptr) {
|
||||
return tag(r, ARR_TAG);
|
||||
}
|
||||
|
||||
B* fillarr_ptr(B x) { VT(x,t_fillarr); return c(FillArr,x)->a; }
|
||||
B* fillarr_ptr(B x) { VTY(x,t_fillarr); return c(FillArr,x)->a; }
|
||||
B fillarr_slice (B x, usz s) {return m_fillslice(x , c(FillArr ,x)->a+s); }
|
||||
B fillslice_slice(B x, usz s) { B r = m_fillslice(inc(c(Slice,x)->p), c(FillSlice,x)->a+s); dec(x); return r; }
|
||||
|
||||
|
||||
B fillarr_get (B x, usz n) { VT(x,t_fillarr ); return inc(c(FillArr ,x)->a[n]); }
|
||||
B fillslice_get (B x, usz n) { VT(x,t_fillslice); return inc(c(FillSlice,x)->a[n]); }
|
||||
B fillarr_getU (B x, usz n) { VT(x,t_fillarr ); return c(FillArr ,x)->a[n] ; }
|
||||
B fillslice_getU(B x, usz n) { VT(x,t_fillslice); return c(FillSlice,x)->a[n] ; }
|
||||
B fillarr_get (B x, usz n) { VTY(x,t_fillarr ); return inc(c(FillArr ,x)->a[n]); }
|
||||
B fillslice_get (B x, usz n) { VTY(x,t_fillslice); return inc(c(FillSlice,x)->a[n]); }
|
||||
B fillarr_getU (B x, usz n) { VTY(x,t_fillarr ); return c(FillArr ,x)->a[n] ; }
|
||||
B fillslice_getU(B x, usz n) { VTY(x,t_fillslice); return c(FillSlice,x)->a[n] ; }
|
||||
void fillarr_free(Value* x) {
|
||||
decSh(x);
|
||||
B* p = ((FillArr*)x)->a;
|
||||
|
||||
77
src/fns.c
77
src/fns.c
@ -174,29 +174,64 @@ B indexOf_c1(B t, B x) {
|
||||
if (isAtm(x)) thrM("⊐: 𝕩 cannot have rank 0");
|
||||
usz xia = a(x)->ia;
|
||||
if (xia==0) { dec(x); return inc(bi_emptyIVec); }
|
||||
if (rnk(x)==1 && TI(x).elType==el_i32) {
|
||||
i32* xp = i32any_ptr(x);
|
||||
i32 min=I32_MAX, max=I32_MIN;
|
||||
// if (rnk(x)==1 && TI(x).elType==el_i32) {
|
||||
// i32* xp = i32any_ptr(x);
|
||||
// i32 min=I32_MAX, max=I32_MIN;
|
||||
// for (usz i = 0; i < xia; i++) {
|
||||
// i32 c = xp[i];
|
||||
// if (c<min) min = c;
|
||||
// if (c>max) max = c;
|
||||
// }
|
||||
// i32 dst = 1 + max-(i64)min;
|
||||
// if ((dst<xia*5 || dst<50) && min!=I32_MIN) {
|
||||
// i32* rp; B r = m_i32arrv(&rp, xia);
|
||||
// i32 tmp[dst];
|
||||
// for (usz i = 0; i < dst; i++) tmp[i] = I32_MIN;
|
||||
// i32* tc = tmp-min;
|
||||
// i32 ctr = 0;
|
||||
// for (usz i = 0; i < xia; i++) {
|
||||
// i32 c = xp[i];
|
||||
// if (tc[c]==I32_MIN) tc[c] = ctr++;
|
||||
// rp[i] = tc[c];
|
||||
// }
|
||||
// dec(x);
|
||||
// return r;
|
||||
// }
|
||||
// }
|
||||
// if (rnk(x)==1) { // relies on equal hashes implying equal objects, which has like a 2⋆¯64 chance of being false per item
|
||||
// // u64 s = nsTime();
|
||||
// i32* rp; B r = m_i32arrv(&rp, xia);
|
||||
// u64 size = xia*2;
|
||||
// wyhashmap_t idx[size];
|
||||
// i32 val[size];
|
||||
// for (i64 i = 0; i < size; i++) { idx[i] = 0; val[i] = -1; }
|
||||
// BS2B xget = TI(x).get;
|
||||
// i32 ctr = 0;
|
||||
// for (usz i = 0; i < xia; i++) {
|
||||
// u64 hash = bqn_hash(xget(x,i), wy_secret);
|
||||
// u64 p = wyhashmap(idx, size, &hash, 8, true, wy_secret);
|
||||
// if (val[p]==-1) val[p] = ctr++;
|
||||
// rp[i] = val[p];
|
||||
// }
|
||||
// dec(x);
|
||||
// // u64 e = nsTime(); q1+= e-s;
|
||||
// return r;
|
||||
// }
|
||||
if (rnk(x)==1) {
|
||||
// u64 s = nsTime();
|
||||
i32* rp; B r = m_i32arrv(&rp, xia);
|
||||
H_b2i* map = m_b2i(64);
|
||||
BS2B xgetU = TI(x).getU;
|
||||
i32 ctr = 0;
|
||||
for (usz i = 0; i < xia; i++) {
|
||||
i32 c = xp[i];
|
||||
if (c<min) min = c;
|
||||
if (c>max) max = c;
|
||||
}
|
||||
i32 dst = 1 + max-(i64)min;
|
||||
if ((dst<xia*5 || dst<50) && min!=I32_MIN) {
|
||||
i32* rp; B r = m_i32arrv(&rp, xia);
|
||||
i32 tmp[dst];
|
||||
for (usz i = 0; i < dst; i++) tmp[i] = I32_MIN;
|
||||
i32* tc = tmp-min;
|
||||
i32 ctr = 0;
|
||||
for (usz i = 0; i < xia; i++) {
|
||||
i32 c = xp[i];
|
||||
if (tc[c]==I32_MIN) tc[c] = ctr++;
|
||||
rp[i] = tc[c];
|
||||
}
|
||||
dec(x);
|
||||
return r;
|
||||
bool had; u64 p = mk_b2i(&map, xgetU(x,i), &had);
|
||||
if (had) rp[i] = map->ent[p].val;
|
||||
else rp[i] = map->ent[p].val = ctr++;
|
||||
}
|
||||
free_b2i(map);
|
||||
dec(x);
|
||||
// u64 e = nsTime(); q1+= e-s;
|
||||
return r;
|
||||
}
|
||||
return c1(rt_indexOf, x);
|
||||
}
|
||||
|
||||
9
src/h.h
9
src/h.h
@ -39,6 +39,7 @@
|
||||
#define NOINLINE __attribute__ ((noinline))
|
||||
#define NORETURN __attribute__ ((noreturn))
|
||||
#define AUTO __auto_type
|
||||
#define LIKELY(X) __builtin_expect(X,1)
|
||||
#define RARE(X) __builtin_expect(X,0)
|
||||
|
||||
typedef u32 usz;
|
||||
@ -86,10 +87,10 @@ enum Type {
|
||||
/*19*/ t_hslice, t_i8slice, t_i32slice, t_fillslice, t_c32slice, t_f64slice,
|
||||
|
||||
/*25*/ t_comp, t_block, t_body, t_scope,
|
||||
/*29*/ t_ns, t_nsDesc, t_fldAlias,
|
||||
/*31*/ t_freed, t_harrPartial,
|
||||
/*29*/ t_ns, t_nsDesc, t_fldAlias, t_hashmap,
|
||||
/*33*/ t_freed, t_harrPartial,
|
||||
#ifdef RT_PERF
|
||||
/*33*/ t_funPerf, t_md1Perf, t_md2Perf,
|
||||
/*35*/ t_funPerf, t_md1Perf, t_md2Perf,
|
||||
#endif
|
||||
t_COUNT
|
||||
};
|
||||
@ -289,7 +290,7 @@ u64 envPrevHeight; // envStart+prevEnvHeight will give the original envCurr
|
||||
#define sprnk(X,R) (X->extra=(R))
|
||||
#define rnk(X ) prnk(v(X))
|
||||
#define srnk(X,R) sprnk(v(X),R)
|
||||
#define VT(X,T) assert(isVal(X) && v(X)->type==(T))
|
||||
#define VTY(X,T) assert(isVal(X) && v(X)->type==(T))
|
||||
|
||||
void print_vmStack();
|
||||
#ifdef DEBUG
|
||||
|
||||
18
src/harr.c
18
src/harr.c
@ -23,27 +23,27 @@ HArr_p m_harrs(usz ia, usz* ctr) { // writes just ia
|
||||
gsAdd(r);
|
||||
return harr_parts(r);
|
||||
}
|
||||
B harr_fv(HArr_p p) { VT(p.b, t_harrPartial);
|
||||
B harr_fv(HArr_p p) { VTY(p.b, t_harrPartial);
|
||||
p.c->type = t_harr;
|
||||
p.c->sh = &p.c->ia;
|
||||
srnk(p.b, 1);
|
||||
gsPop();
|
||||
return p.b;
|
||||
}
|
||||
B harr_fc(HArr_p p, B x) { VT(p.b, t_harrPartial);
|
||||
B harr_fc(HArr_p p, B x) { VTY(p.b, t_harrPartial);
|
||||
p.c->type = t_harr;
|
||||
arr_shCopy(p.b, x);
|
||||
gsPop();
|
||||
return p.b;
|
||||
}
|
||||
B harr_fcd(HArr_p p, B x) { VT(p.b, t_harrPartial);
|
||||
B harr_fcd(HArr_p p, B x) { VTY(p.b, t_harrPartial);
|
||||
p.c->type = t_harr;
|
||||
arr_shCopy(p.b, x);
|
||||
dec(x);
|
||||
gsPop();
|
||||
return p.b;
|
||||
}
|
||||
usz* harr_fa(HArr_p p, ur r) { VT(p.b, t_harrPartial);
|
||||
usz* harr_fa(HArr_p p, ur r) { VTY(p.b, t_harrPartial);
|
||||
p.c->type = t_harr;
|
||||
gsPop();
|
||||
return arr_shAllocR(p.b, r);
|
||||
@ -133,7 +133,7 @@ B toKCells(B x, ur k) {
|
||||
}
|
||||
|
||||
|
||||
B* harr_ptr(B x) { VT(x,t_harr); return c(HArr,x)->a; }
|
||||
B* harr_ptr(B x) { VTY(x,t_harr); return c(HArr,x)->a; }
|
||||
|
||||
HArr* toHArr(B x) {
|
||||
if (v(x)->type==t_harr) return c(HArr,x);
|
||||
@ -174,10 +174,10 @@ B harr_slice (B x, usz s) {return m_hslice(x , c(HArr ,x)->a+s
|
||||
B hslice_slice(B x, usz s) { B r = m_hslice(inc(c(Slice,x)->p), c(HSlice,x)->a+s); dec(x); return r; }
|
||||
|
||||
|
||||
B harr_get (B x, usz n) { VT(x,t_harr ); return inc(c(HArr ,x)->a[n]); }
|
||||
B hslice_get (B x, usz n) { VT(x,t_hslice); return inc(c(HSlice,x)->a[n]); }
|
||||
B harr_getU (B x, usz n) { VT(x,t_harr ); return c(HArr ,x)->a[n] ; }
|
||||
B hslice_getU(B x, usz n) { VT(x,t_hslice); return c(HSlice,x)->a[n] ; }
|
||||
B harr_get (B x, usz n) { VTY(x,t_harr ); return inc(c(HArr ,x)->a[n]); }
|
||||
B hslice_get (B x, usz n) { VTY(x,t_hslice); return inc(c(HSlice,x)->a[n]); }
|
||||
B harr_getU (B x, usz n) { VTY(x,t_harr ); return c(HArr ,x)->a[n] ; }
|
||||
B hslice_getU(B x, usz n) { VTY(x,t_hslice); return c(HSlice,x)->a[n] ; }
|
||||
void harr_free(Value* x) {
|
||||
decSh(x);
|
||||
B* p = ((HArr*)x)->a; // don't use harr_ptr so type isn't checked
|
||||
|
||||
42
src/hash.c
42
src/hash.c
@ -34,18 +34,18 @@ B bqn_squeeze(B x) {
|
||||
} else return x;
|
||||
}
|
||||
|
||||
u64 bqn_hash(B x, const u64 secret[4]) { // consumes (because otherwise squeezing is hard as in-place cannot be done because slices)
|
||||
u64 bqn_hash(B x, const u64 secret[4]) { // doesn't consume
|
||||
if (isAtm(x)) {
|
||||
if (q_f64(x)) return wyhash64(secret[0], x.u);
|
||||
if (isC32(x)) return wyhash64(secret[1], x.u);
|
||||
assert(isVal(x));
|
||||
dec(x);
|
||||
return wyhash64(secret[2], x.u);
|
||||
}
|
||||
inc(x);
|
||||
x = bqn_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 shHash = wyhash(a(x)->sh, rnk(x)*sizeof(usz), 0, secret);
|
||||
u64 r;
|
||||
if (xe==el_i32) {
|
||||
r = wyhash(i32any_ptr(x), xia*4, shHash, secret);
|
||||
@ -56,10 +56,42 @@ u64 bqn_hash(B x, const u64 secret[4]) { // consumes (because otherwise squeezin
|
||||
} else {
|
||||
assert(xe==el_B);
|
||||
u64 data[xia];
|
||||
BS2B xget = TI(x).get;
|
||||
for (usz i = 0; i < xia; i++) data[i] = bqn_hash(xget(x, i), secret);
|
||||
BS2B xgetU = TI(x).getU;
|
||||
for (usz i = 0; i < xia; i++) data[i] = bqn_hash(xgetU(x, i), secret);
|
||||
r = wyhash(data, xia*8, shHash, secret);
|
||||
}
|
||||
dec(x);
|
||||
return r;
|
||||
}
|
||||
|
||||
u64 wy_secret[4];
|
||||
u64 bqn_hashP(B x, const u64 secret[4]) { // bqn_hash but never zero
|
||||
u64 r = bqn_hash(x, secret);
|
||||
return LIKELY(r)?r:secret[3]; // bias towards secret[3], whatever
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define N(X) X##_b2i
|
||||
#define HT u64
|
||||
#define KT B
|
||||
#define H1(K) bqn_hashP(K, wy_secret)
|
||||
#define H2(K,h1) h1
|
||||
#define H1R(K,h2) h2
|
||||
#define EMPTY(S,K) ((S)==0)
|
||||
#define HDEF 0
|
||||
#define KEYS
|
||||
#define EQUAL(A,B) equal(A,B)
|
||||
#define VALS
|
||||
#define VT i32
|
||||
#include "hashmap.c"
|
||||
|
||||
|
||||
|
||||
void hash_init() {
|
||||
u64 bad1=0xa0761d6478bd642full; // values wyhash64 is afraid of
|
||||
u64 bad2=0xe7037ed1a0b428dbull;
|
||||
again:
|
||||
make_secret(nsTime(), wy_secret);
|
||||
for (u64 i = 0; i < 4; i++) if(wy_secret[i]==bad1 || wy_secret[i]==bad2) goto again;
|
||||
}
|
||||
|
||||
147
src/hashmap.c
Normal file
147
src/hashmap.c
Normal file
@ -0,0 +1,147 @@
|
||||
// args:
|
||||
// N(X) - X##_mapName
|
||||
// HT - stored hash type (u32 or u64)
|
||||
// KT - key type
|
||||
// H1(K) - function to compute index in hashmap, returns u64; the expensive part
|
||||
// H2(K,h1) - function to compute HT (returning just h1 (or K if applicable) is safe)
|
||||
// H1R(K,h2) - calculate H1 from H2, preferrably fast
|
||||
// EMPTY(S,K) - test whether value counts as unpopulated (ignore K if !KEYS)
|
||||
// HDEF - if defined, the value to initialize HT to (otherwise it's undefined)
|
||||
// KEYS - whether to separately store and check keys (otherwise only HT is compared)
|
||||
// EQUAL(A,B) - compare two keys
|
||||
// KDEF - if defined, the value to initialize keys to (otherwise it's undefined)
|
||||
// VALS - whether to store values corresponding to keys (otherwise this is a hashset)
|
||||
// VT - value type
|
||||
|
||||
#define Map N(H)
|
||||
#define Ent N(Ent)
|
||||
#ifdef KEYS
|
||||
#define IFKEY(...) __VA_ARGS__
|
||||
#else
|
||||
#define IFKEY(...)
|
||||
#endif
|
||||
#ifdef VALS
|
||||
#define IFVAL(...) __VA_ARGS__
|
||||
#else
|
||||
#define IFVAL(...)
|
||||
#endif
|
||||
|
||||
typedef struct Ent {
|
||||
#ifdef KEYS
|
||||
KT key;
|
||||
#endif
|
||||
HT hash;
|
||||
#ifdef VALS
|
||||
VT val;
|
||||
#endif
|
||||
} Ent;
|
||||
|
||||
typedef struct Map {
|
||||
struct Value;
|
||||
u64 pop; // count of defined entries
|
||||
u64 mask; // sz-1
|
||||
u64 sz; // count of allocated entries, a power of 2
|
||||
Ent ent[];
|
||||
} Map;
|
||||
|
||||
Map* N(m) (u64 sz) {
|
||||
assert(sz && (sz & sz-1)==0);
|
||||
Map* r = mm_allocN(fsizeof(Map,ent,Ent,sz), t_hashmap);
|
||||
#ifdef HDEF
|
||||
for (u64 i = 0; i < sz; i++) r->ent[i].hash = HDEF;
|
||||
#endif
|
||||
#ifdef KDEF
|
||||
for (u64 i = 0; i < sz; i++) r->ent[i].key = KDEF;
|
||||
#endif
|
||||
r->sz = sz;
|
||||
r->mask = sz-1;
|
||||
r->pop = 0;
|
||||
return r;
|
||||
}
|
||||
void N(free) (Map* m) {
|
||||
mm_free((Value*) m);
|
||||
}
|
||||
|
||||
|
||||
static inline u64 N(find) (Map* m, KT k, u64 h1, u64 h2, bool* had) {
|
||||
assert(m->sz > m->pop);
|
||||
*had = true;
|
||||
u64 mask = m->mask;
|
||||
u64 p = h1 & mask;
|
||||
while (true) {
|
||||
Ent e = m->ent[p];
|
||||
if (e.hash==h2 IFKEY(&& LIKELY(EQUAL(e.key, k)))) return p;
|
||||
if (EMPTY(e.hash, e.key)) { *had=false; return p; }
|
||||
if (RARE(p++==mask)) p = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline void N(qins) (Map* m, u64 h1, HT h2, KT k IFVAL(, VT v)) { // if guaranteed that k doesn't exist in the map yet and there's space for this
|
||||
u64 mask = m->mask;
|
||||
u64 p = h1 & mask;
|
||||
while (true) {
|
||||
u64 ch2 = m->ent[p].hash;
|
||||
if (EMPTY(ch2, m->ent[p].key)) {
|
||||
m->ent[p].hash = h2;
|
||||
IFKEY(m->ent[p].key = k);
|
||||
IFVAL(m->ent[p].val = v);
|
||||
m->pop++;
|
||||
return;
|
||||
}
|
||||
if (p++==mask) p = 0;
|
||||
}
|
||||
}
|
||||
void N(dbl) (Map** m) {
|
||||
Map* pm = *m;
|
||||
u64 psz = pm->sz;
|
||||
Map* nm = N(m)(psz*2);
|
||||
for (u64 i = 0; i < psz; i++) {
|
||||
Ent e = pm->ent[i];
|
||||
if(!EMPTY(e.hash, e.key)) N(qins)(nm, H1R(e.key, e.hash), e.hash, e.key IFVAL(, e.val));
|
||||
}
|
||||
mm_free((Value*)pm);
|
||||
*m = nm;
|
||||
}
|
||||
|
||||
|
||||
static inline u64 N(mk) (Map** mp, KT k, bool* had) {
|
||||
Map* m = *mp;
|
||||
if (m->pop*2 > m->sz) { N(dbl)(mp); m=*mp; }
|
||||
u64 h1 = H1(k); u64 h2 = H2(k, h1);
|
||||
u64 p = N(find)(m, k, h1, h2, had);
|
||||
if (*had) return p;
|
||||
m->ent[p].hash = h2;
|
||||
IFKEY(m->ent[p].key = k);
|
||||
m->pop++;
|
||||
return p;
|
||||
}
|
||||
#ifdef VALS
|
||||
static inline bool N(ins) (Map** mp, KT k, VT v) { // returns whether element was replaced
|
||||
bool had; u64 p = N(mk)(mp, k, &had);
|
||||
(*mp)->ent[p].val = v;
|
||||
return had;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#undef IFKEY
|
||||
#undef IFVAL
|
||||
#undef Ent
|
||||
#undef Map
|
||||
#undef N
|
||||
#undef HT
|
||||
#undef KT
|
||||
#undef H1
|
||||
#undef H2
|
||||
#undef EMPTY
|
||||
#undef HDEF
|
||||
#ifdef KEYS
|
||||
#undef KEYS
|
||||
#undef EQUAL
|
||||
#undef KDEF
|
||||
#endif
|
||||
#ifdef VALS
|
||||
#undef VALS
|
||||
#undef VT
|
||||
#endif
|
||||
@ -38,7 +38,7 @@ B m_i32slice(B p, i32* ptr) {
|
||||
}
|
||||
|
||||
|
||||
i32* i32arr_ptr(B x) { VT(x, t_i32arr); return c(I32Arr,x)->a; }
|
||||
i32* i32arr_ptr(B x) { VTY(x, t_i32arr); return c(I32Arr,x)->a; }
|
||||
i32* i32any_ptr(B x) { assert(isArr(x)); u8 t=v(x)->type; if(t==t_i32arr) return c(I32Arr,x)->a; assert(t==t_i32slice); return c(I32Slice,x)->a; }
|
||||
|
||||
NOINLINE B m_cai32(usz ia, i32* a) {
|
||||
@ -67,8 +67,8 @@ I32Arr* toI32Arr(B x) { // assumes it's possible
|
||||
B i32arr_slice (B x, usz s) {return m_i32slice(x , c(I32Arr ,x)->a+s); }
|
||||
B i32slice_slice(B x, usz s) { B r = m_i32slice(inc(c(Slice,x)->p), c(I32Slice,x)->a+s); dec(x); return r; }
|
||||
|
||||
B i32arr_get (B x, usz n) { VT(x,t_i32arr ); return m_i32(c(I32Arr ,x)->a[n]); }
|
||||
B i32slice_get(B x, usz n) { VT(x,t_i32slice); return m_i32(c(I32Slice,x)->a[n]); }
|
||||
B i32arr_get (B x, usz n) { VTY(x,t_i32arr ); return m_i32(c(I32Arr ,x)->a[n]); }
|
||||
B i32slice_get(B x, usz n) { VTY(x,t_i32slice); return m_i32(c(I32Slice,x)->a[n]); }
|
||||
void i32arr_free(Value* x) { decSh(x); }
|
||||
bool i32arr_canStore(B x) { return q_i32(x); }
|
||||
|
||||
|
||||
@ -76,6 +76,7 @@ int main(int argc, char* argv[]) {
|
||||
gc_add(srcB);
|
||||
for (i32 i = 0; i < 100; i++) { dec(bqn_exec(inc(srcB), bi_N, bi_N)); gc_maybeGC(); }
|
||||
rtPerf_print();
|
||||
CTR_FOR(CTR_PRINT)
|
||||
exit(0);
|
||||
#endif
|
||||
bqn_setComp(bqn_exec(srcB, bi_N, bi_N));
|
||||
|
||||
@ -518,7 +518,7 @@ void printAllocStats() {
|
||||
|
||||
_Thread_local B comp_currPath;
|
||||
_Thread_local B comp_currArgs;
|
||||
#define FOR_INIT(F) F(hdr) F(harr) F(fillarr) F(i32arr) F(c32arr) F(f64arr) F(fns) F(sfns) F(arith) F(grade) F(md1) F(md2) F(sysfn) F(derv) F(comp) F(rtPerf) F(ns) F(load)
|
||||
#define FOR_INIT(F) F(hdr) F(harr) F(fillarr) F(i32arr) F(c32arr) F(f64arr) F(hash) F(fns) F(sfns) F(arith) F(grade) F(md1) F(md2) F(sysfn) F(derv) F(comp) F(rtPerf) F(ns) F(load)
|
||||
#define F(X) static inline void X##_init();
|
||||
FOR_INIT(F)
|
||||
#undef F
|
||||
|
||||
@ -164,13 +164,15 @@ B cmp_c2(B t, B w, B x) {
|
||||
B hash_c2(B t, B w, B x) {
|
||||
u64 secret[4]; make_secret(o2i64(w), secret);
|
||||
u64 rv = bqn_hash(x, secret);
|
||||
dec(x);
|
||||
i32* rp; B r = m_i32arrv(&rp, 4);
|
||||
rp[0] = (u16)(rv>>48); rp[1] = (u16)(rv>>32);
|
||||
rp[2] = (u16)(rv>>16); rp[3] = (u16)(rv );
|
||||
return r;
|
||||
}
|
||||
B hash_c1(B t, B x) {
|
||||
u64 rv = bqn_hash(x, _wyp);
|
||||
u64 rv = bqn_hash(x, wy_secret);
|
||||
dec(x);
|
||||
i32* rp; B r = m_i32arrv(&rp, 4);
|
||||
rp[0] = (u16)(rv>>48); rp[1] = (u16)(rv>>32);
|
||||
rp[2] = (u16)(rv>>16); rp[3] = (u16)(rv );
|
||||
|
||||
4
src/vm.c
4
src/vm.c
@ -211,7 +211,7 @@ void v_set(Scope* pscs[], B s, B x, bool upd) { // doesn't consume
|
||||
}
|
||||
sc->vars[(u32)s.u] = inc(x);
|
||||
} else {
|
||||
VT(s, t_harr);
|
||||
VTY(s, t_harr);
|
||||
B* sp = harr_ptr(s);
|
||||
usz ia = a(s)->ia;
|
||||
if (isAtm(x) || !eqShape(s, x)) {
|
||||
@ -244,7 +244,7 @@ B v_get(Scope* pscs[], B s) { // get value representing s, replacing with bi_opt
|
||||
sc->vars[(u32)s.u] = bi_optOut;
|
||||
return r;
|
||||
} else {
|
||||
VT(s, t_harr);
|
||||
VTY(s, t_harr);
|
||||
usz ia = a(s)->ia;
|
||||
B* sp = harr_ptr(s);
|
||||
HArr_p r = m_harrUv(ia);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user