proper hash values for derived functions

This commit is contained in:
dzaima 2023-03-06 20:29:35 +02:00
parent ab5b8f92b4
commit 92763fa8b2
2 changed files with 73 additions and 32 deletions

View File

@ -3,37 +3,78 @@
#include "hash.h"
#include "time.h"
NOINLINE u64 bqn_hashArr(B x, const u64 secret[4]) { // TODO manual separation of atom & arr probably won't be worth it when there are actually sane typed array hashing things
usz xia = IA(x);
if (xia==0) return ~secret[3]; // otherwise squeeze will care about fills
x = any_squeeze(incG(x));
u8 xr = RNK(x);
u8 xe = TI(x,elType);
u64 shHash;
if (xr<=1) shHash = wyhash64(xia, xe);
else shHash = wyhash(SH(x), xr*sizeof(usz), xe, secret);
bool isTemp = false;
void* data;
u64 bytes;
switch(xe) { default: UD;
case el_bit: bcl(x,xia); data = bitarr_ptr(x); bytes = (xia+7)>>3; break;
case el_i8: case el_c8: data = tyany_ptr(x); bytes = xia*1; break;
case el_i16: case el_c16: data = tyany_ptr(x); bytes = xia*2; break;
case el_i32: case el_c32: data = tyany_ptr(x); bytes = xia*4; break;
case el_f64: data = f64any_ptr(x); bytes = xia*8; break;
case el_B:;
data = TALLOCP(u64, xia);
isTemp = true;
SGetU(x)
for (usz i = 0; i < xia; i++) ((u64*)data)[i] = bqn_hash(GetU(x, i), secret);
bytes = xia*sizeof(B);
break;
NOINLINE u64 bqn_hashObj(B x, const u64 secret[4]) { // TODO manual separation of atom & arr probably won't be worth it when there are actually sane typed array hashing things
if (isArr(x)) {
usz xia = IA(x);
if (xia==0) return ~secret[3]; // otherwise squeeze will care about fills
x = any_squeeze(incG(x));
u8 xr = RNK(x);
u8 xe = TI(x,elType);
u64 shHash;
if (xr<=1) shHash = wyhash64(xia, xe);
else shHash = wyhash(SH(x), xr*sizeof(usz), xe, secret);
bool isTemp = false;
void* data;
u64 bytes;
switch(xe) { default: UD;
case el_bit: bcl(x,xia); data = bitarr_ptr(x); bytes = (xia+7)>>3; break;
case el_i8: case el_c8: data = tyany_ptr(x); bytes = xia*1; break;
case el_i16: case el_c16: data = tyany_ptr(x); bytes = xia*2; break;
case el_i32: case el_c32: data = tyany_ptr(x); bytes = xia*4; break;
case el_f64: data = f64any_ptr(x); bytes = xia*8; break;
case el_B:;
data = TALLOCP(u64, xia);
isTemp = true;
SGetU(x)
for (usz i = 0; i < xia; i++) ((u64*)data)[i] = bqn_hash(GetU(x, i), secret);
bytes = xia*sizeof(B);
break;
}
assert(bytes!=0);
u64 r = wyhash(data, bytes, shHash, secret);
if (isTemp) TFREE(data);
dec(x);
return r;
}
assert(bytes!=0);
u64 r = wyhash(data, bytes, shHash, secret);
if (isTemp) TFREE(data);
dec(x);
return r;
u64 hashbuf[3];
switch(TY(x)) {
case t_funBl: case t_md1Bl: case t_md2Bl:
case t_funBI: case t_md1BI: case t_md2BI:
case t_ns: case t_nfn:
return wyhash64(secret[0], x.u);
case t_md1D: {
Md1D* xv = c(Md1D,x);
hashbuf[0] = 0;
hashbuf[1] = bqn_hash(xv->f, secret);
hashbuf[2] = bqn_hash(tag(xv->m1, MD1_TAG), secret);
break;
}
case t_md2D: {
Md2D* xv = c(Md2D,x);
hashbuf[0] = bqn_hash(xv->g, secret);
hashbuf[1] = bqn_hash(xv->f, secret);
hashbuf[2] = bqn_hash(tag(xv->m2, MD1_TAG), secret);
break;
}
case t_fork: {
Fork* xv = c(Fork,x);
hashbuf[0] = bqn_hash(xv->f, secret);
hashbuf[1] = bqn_hash(xv->g, secret);
hashbuf[2] = bqn_hash(xv->h, secret);
break;
}
case t_atop: {
Atop* xv = c(Atop,x);
hashbuf[0] = 0;
hashbuf[1] = bqn_hash(xv->g, secret);
hashbuf[2] = bqn_hash(xv->h, secret);
break;
}
default: thrM("Cannot hash this object");
}
return wyhash(hashbuf, sizeof(hashbuf), TY(x), secret);
}

View File

@ -11,9 +11,9 @@ static void bcl(B x, usz ia) { // clean up bitarr tail bits to zero
}
}
u64 bqn_hashArr(B x, const u64 secret[4]);
u64 bqn_hashObj(B x, const u64 secret[4]);
static u64 bqn_hash(B x, const u64 secret[4]) { // doesn't consume
if (isArr(x)) return bqn_hashArr(x, secret);
if (isVal(x)) return bqn_hashObj(x, secret);
return wyhash64(secret[0], x.u);
}