From 39e96e0739f657a5b0f1838dcd8fb179bc55ebe3 Mon Sep 17 00:00:00 2001 From: Martin Fouilleul Date: Sat, 29 Apr 2023 19:25:40 +0200 Subject: [PATCH] Added xxhash64 hash function and use that instead of x64-specific aes hash, until we get an arm version --- src/ui.c | 6 ++-- src/util/hash.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++- src/util/hash.h | 4 +++ 3 files changed, 79 insertions(+), 4 deletions(-) diff --git a/src/ui.c b/src/ui.c index 9c27438..70d671f 100644 --- a/src/ui.c +++ b/src/ui.c @@ -142,7 +142,7 @@ void ui_box_pop(void) ui_tag ui_tag_make_str8(str8 string) { - ui_tag tag = {.hash = mp_hash_aes_string(string)}; + ui_tag tag = {.hash = mp_hash_xx64_string(string)}; return(tag); } @@ -176,7 +176,7 @@ ui_key ui_key_make_str8(str8 string) } ui_key key = {0}; - key.hash = mp_hash_aes_string_seed(string, seed); + key.hash = mp_hash_xx64_string_seed(string, seed); return(key); } @@ -191,7 +191,7 @@ ui_key ui_key_make_path(str8_list path) } for_list(&path.list, elt, str8_elt, listElt) { - seed = mp_hash_aes_string_seed(elt->string, seed); + seed = mp_hash_xx64_string_seed(elt->string, seed); } ui_key key = {seed}; return(key); diff --git a/src/util/hash.c b/src/util/hash.c index 7e704d8..afae8e3 100644 --- a/src/util/hash.c +++ b/src/util/hash.c @@ -6,8 +6,11 @@ * @revision: * *****************************************************************/ -#include #include"hash.h" +#include"platform.h" + +#if ARCH_X64 +#include u64 mp_hash_aes_u64(u64 x) { @@ -122,3 +125,71 @@ u64 mp_hash_aes_string_seed(str8 string, u64 seed) u64 result = _mm_extract_epi64(hash, 0); return(result); } +#endif // ARCH_X64 + +//xxhash64, copy-pasted from https://github.com/demetri/scribbles/blob/master/hashing/hash_functions.c +// Thanks Demetri + +uint64_t xxh_64 (const void *key, int len, uint64_t h) { + // primes used in mul-rot updates + uint64_t p1 = 0x9e3779b185ebca87, p2 = 0xc2b2ae3d27d4eb4f, + p3 = 0x165667b19e3779f9, p4 =0x85ebca77c2b2ae63, p5 = 0x27d4eb2f165667c5; + + // inital 32-byte (4x8) wide hash state + uint64_t s[4] = {h+p1+p2, h+p2, h, h-p1}; + + // bulk work: process all 32 byte blocks + uint64_t *k32 = (uint64_t*) key; + for (int i=0; i < (len/32); i+=4) { + uint64_t b[4] = {k32[i+0], k32[i+1], k32[i+2], k32[i+3]}; + for (int j=0;j<4;j++) b[j] = b[j]*p2+s[j]; + for (int j=0;j<4;j++) s[j] = ((b[j] << 31) | (b[j] >> 33))*p1; + } + + // mix 32-byte state down to 8-byte state, initalize to value for short keys + uint64_t s64 = (s[2] + p5); + if (len > 32) { + s64 = ((s[0] << 1) | (s[0] >> 63)) + ((s[1] << 7) | (s[1] >> 57)) + + ((s[2] << 12) | (s[2] >> 52)) + ((s[3] << 18) | (s[3] >> 46)); + for (int i=0; i<4;i++) { + uint64_t ps = (((s[i]*p2) << 31) | ((s[i]*p2) >> 33))*p1; + s64 = (s64 ^ ps)*p1 + p4; + } + } + s64 += len; + + // up to 31 bytes remain, process 0-3 8 byte blocks + uint8_t *tail = (uint8_t *) (key + (len/32)*32); + for (int i=0;i < (len & 31) / 8; i++,tail+=8) { + uint64_t b = (*((uint64_t*) tail))*p2; + b = (((b << 31)| (b >> 33))*p1) ^ s64; + s64 = ((b << 27) | (b >> 37))*p1 + p4; + } + + // up to 7 bytes remain, process 0-1 4 byte block + for (int i=0;i< (len & 7) / 4; i++, tail +=4) { + uint64_t b = s64 ^ (*(uint32_t*)tail)*p1; + s64 = ((b << 23) | (b >> 41))*p2 + p3; + } + + // up to 3 bytes remain, process 0-3 1 byte blocks + for (int i=0;i<(len & 3); i++,tail++) { + uint64_t b = s64 ^ (*tail)*p5; + s64 = ((b << 11) | (b >> 53))*p1; + } + + // finalization mix + s64 = (s64 ^ (s64 >> 33))*p2; + s64 = (s64 ^ (s64 >> 29))*p3; + return (s64 ^ (s64 >> 32)); +} + +u64 mp_hash_xx64_string_seed(str8 string, u64 seed) +{ + return(xxh_64(string.ptr, string.len, seed)); +} + +u64 mp_hash_xx64_string(str8 string) +{ + return(xxh_64(string.ptr, string.len, 0)); +} diff --git a/src/util/hash.h b/src/util/hash.h index f3a4d5b..ee90906 100644 --- a/src/util/hash.h +++ b/src/util/hash.h @@ -21,6 +21,10 @@ MP_API u64 mp_hash_aes_u64_x2(u64 x, u64 y); MP_API u64 mp_hash_aes_string(str8 string); MP_API u64 mp_hash_aes_string_seed(str8 string, u64 seed); +MP_API u64 mp_hash_xx64_string_seed(str8 string, u64 seed); +MP_API u64 mp_hash_xx64_string(str8 string); + + #ifdef __cplusplus } // extern "C" #endif