From 92763fa8b2b277cc7b0111c407d180412437c7db Mon Sep 17 00:00:00 2001 From: dzaima Date: Mon, 6 Mar 2023 20:29:35 +0200 Subject: [PATCH] proper hash values for derived functions --- src/utils/hash.c | 101 +++++++++++++++++++++++++++++++++-------------- src/utils/hash.h | 4 +- 2 files changed, 73 insertions(+), 32 deletions(-) diff --git a/src/utils/hash.c b/src/utils/hash.c index fad3b3d1..9251ee73 100644 --- a/src/utils/hash.c +++ b/src/utils/hash.c @@ -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); } diff --git a/src/utils/hash.h b/src/utils/hash.h index 6846b952..25beed1b 100644 --- a/src/utils/hash.h +++ b/src/utils/hash.h @@ -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); }