uCBQN/src/utils/hash.h
2021-07-06 19:22:45 +03:00

70 lines
1.6 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 = 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 r;
if (xe==el_i32) {
r = wyhash(i32any_ptr(x), xia*4, 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);
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);
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"