uCBQN/src/utils/hash.h
2021-09-09 23:52:18 +03:00

71 lines
1.9 KiB
C

#pragma once
#include "wyhash.h"
#include "talloc.h"
extern u64 wy_secret[4];
static 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));
return wyhash64(secret[2], x.u);
}
inc(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_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);
SGetU(x)
for (usz i = 0; i < xia; i++) data[i] = bqn_hash(GetU(x, i), secret);
r = wyhash(data, xia*8, shHash, secret);
TFREE(data);
}
dec(x);
return r;
}
static 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 "hashmapTemplate.h"
#define N(X) X##_Sb
#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)
#include "hashmapTemplate.h"