2022-08-14 16:19:40 +00:00
|
|
|
/************************************************************//**
|
|
|
|
*
|
|
|
|
* @file: hash.cpp
|
|
|
|
* @author: Martin Fouilleul
|
|
|
|
* @date: 08/08/2022
|
|
|
|
* @revision:
|
|
|
|
*
|
|
|
|
*****************************************************************/
|
|
|
|
#include"hash.h"
|
2023-07-15 07:15:12 +00:00
|
|
|
#include"platform/platform.h"
|
2023-04-29 17:25:40 +00:00
|
|
|
|
2023-08-14 08:26:11 +00:00
|
|
|
#if OC_ARCH_X64
|
2023-04-29 17:25:40 +00:00
|
|
|
#include<immintrin.h>
|
2022-08-14 16:19:40 +00:00
|
|
|
|
2023-08-14 08:26:11 +00:00
|
|
|
u64 oc_hash_aes_u64(u64 x)
|
2022-08-14 16:19:40 +00:00
|
|
|
{
|
|
|
|
u8 seed[16] = {
|
|
|
|
0xaa, 0x9b, 0xbd, 0xb8,
|
|
|
|
0xa1, 0x98, 0xac, 0x3f,
|
|
|
|
0x1f, 0x94, 0x07, 0xb3,
|
|
|
|
0x8c, 0x27, 0x93, 0x69 };
|
|
|
|
|
|
|
|
__m128i hash = _mm_set_epi64x(0L, x);
|
|
|
|
__m128i key = _mm_loadu_si128((__m128i*)seed);
|
|
|
|
hash = _mm_aesdec_si128(hash, key);
|
|
|
|
hash = _mm_aesdec_si128(hash, key);
|
|
|
|
u64 result = _mm_extract_epi64(hash, 0);
|
|
|
|
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
2023-08-14 08:26:11 +00:00
|
|
|
u64 oc_hash_aes_u64_x2(u64 x, u64 y)
|
2022-08-14 16:19:40 +00:00
|
|
|
{
|
|
|
|
u8 seed[16] = {
|
|
|
|
0xaa, 0x9b, 0xbd, 0xb8,
|
|
|
|
0xa1, 0x98, 0xac, 0x3f,
|
|
|
|
0x1f, 0x94, 0x07, 0xb3,
|
|
|
|
0x8c, 0x27, 0x93, 0x69 };
|
|
|
|
|
|
|
|
__m128i hash = _mm_set_epi64x(x, y);
|
|
|
|
__m128i key = _mm_loadu_si128((__m128i*)seed);
|
|
|
|
hash = _mm_aesdec_si128(hash, key);
|
|
|
|
hash = _mm_aesdec_si128(hash, key);
|
|
|
|
u64 result = _mm_extract_epi64(hash, 0);
|
|
|
|
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
2023-08-14 08:26:11 +00:00
|
|
|
u64 oc_hash_aes_string(oc_str8 string)
|
2022-08-14 16:19:40 +00:00
|
|
|
{
|
|
|
|
u8 seed[16] = {
|
|
|
|
0xaa, 0x9b, 0xbd, 0xb8,
|
|
|
|
0xa1, 0x98, 0xac, 0x3f,
|
|
|
|
0x1f, 0x94, 0x07, 0xb3,
|
|
|
|
0x8c, 0x27, 0x93, 0x69 };
|
|
|
|
|
|
|
|
__m128i hash = _mm_loadu_si128((__m128i*)seed);
|
|
|
|
|
|
|
|
u64 chunkCount = string.len / 16;
|
|
|
|
char* at = string.ptr;
|
|
|
|
|
|
|
|
while(chunkCount--)
|
|
|
|
{
|
|
|
|
__m128i in = _mm_loadu_si128((__m128i*)at);
|
|
|
|
at += 16;
|
|
|
|
|
|
|
|
hash = _mm_xor_si128(hash, in);
|
|
|
|
hash = _mm_aesdec_si128(hash, _mm_setzero_si128());
|
|
|
|
hash = _mm_aesdec_si128(hash, _mm_setzero_si128());
|
|
|
|
hash = _mm_aesdec_si128(hash, _mm_setzero_si128());
|
|
|
|
hash = _mm_aesdec_si128(hash, _mm_setzero_si128());
|
|
|
|
}
|
|
|
|
|
|
|
|
u64 restCount = string.len % 16;
|
|
|
|
char tmp[16];
|
|
|
|
memset(tmp, 0, 16);
|
|
|
|
memmove(tmp, at, restCount);
|
|
|
|
|
|
|
|
__m128i in = _mm_loadu_si128((__m128i*)tmp);
|
|
|
|
hash = _mm_xor_si128(hash, in);
|
|
|
|
hash = _mm_aesdec_si128(hash, _mm_setzero_si128());
|
|
|
|
hash = _mm_aesdec_si128(hash, _mm_setzero_si128());
|
|
|
|
hash = _mm_aesdec_si128(hash, _mm_setzero_si128());
|
|
|
|
hash = _mm_aesdec_si128(hash, _mm_setzero_si128());
|
|
|
|
|
|
|
|
u64 result = _mm_extract_epi64(hash, 0);
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
2023-08-14 08:26:11 +00:00
|
|
|
u64 oc_hash_aes_string_seed(oc_str8 string, u64 seed)
|
2022-08-14 16:19:40 +00:00
|
|
|
{
|
|
|
|
u8 seed16[16];
|
|
|
|
memcpy(seed16, &seed, 8);
|
|
|
|
memcpy(seed16+8, &seed, 8);
|
|
|
|
|
|
|
|
__m128i hash = _mm_loadu_si64(&seed16);
|
|
|
|
|
|
|
|
u64 chunkCount = string.len / 16;
|
|
|
|
char* at = string.ptr;
|
|
|
|
|
|
|
|
while(chunkCount--)
|
|
|
|
{
|
|
|
|
__m128i in = _mm_loadu_si128((__m128i*)at);
|
|
|
|
at += 16;
|
|
|
|
|
|
|
|
hash = _mm_xor_si128(hash, in);
|
|
|
|
hash = _mm_aesdec_si128(hash, _mm_setzero_si128());
|
|
|
|
hash = _mm_aesdec_si128(hash, _mm_setzero_si128());
|
|
|
|
hash = _mm_aesdec_si128(hash, _mm_setzero_si128());
|
|
|
|
hash = _mm_aesdec_si128(hash, _mm_setzero_si128());
|
|
|
|
}
|
|
|
|
|
|
|
|
u64 restCount = string.len % 16;
|
|
|
|
char tmp[16];
|
|
|
|
memset(tmp, 0, 16);
|
|
|
|
memmove(tmp, at, restCount);
|
|
|
|
|
|
|
|
__m128i in = _mm_loadu_si128((__m128i*)tmp);
|
|
|
|
hash = _mm_xor_si128(hash, in);
|
|
|
|
hash = _mm_aesdec_si128(hash, _mm_setzero_si128());
|
|
|
|
hash = _mm_aesdec_si128(hash, _mm_setzero_si128());
|
|
|
|
hash = _mm_aesdec_si128(hash, _mm_setzero_si128());
|
|
|
|
hash = _mm_aesdec_si128(hash, _mm_setzero_si128());
|
|
|
|
|
|
|
|
u64 result = _mm_extract_epi64(hash, 0);
|
|
|
|
return(result);
|
|
|
|
}
|
2023-08-14 08:26:11 +00:00
|
|
|
#endif // OC_ARCH_X64
|
2023-04-29 17:25:40 +00:00
|
|
|
|
|
|
|
//xxhash64, copy-pasted from https://github.com/demetri/scribbles/blob/master/hashing/hash_functions.c
|
2023-08-14 08:26:11 +00:00
|
|
|
// Thanks to Demetri Spanos
|
2023-04-29 17:25:40 +00:00
|
|
|
|
|
|
|
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
|
2023-05-12 09:13:55 +00:00
|
|
|
uint8_t *tail = (uint8_t *) (((char*)key) + (len/32)*32);
|
2023-04-29 17:25:40 +00:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2023-08-14 08:26:11 +00:00
|
|
|
u64 oc_hash_xx64_string_seed(oc_str8 string, u64 seed)
|
2023-04-29 17:25:40 +00:00
|
|
|
{
|
|
|
|
return(xxh_64(string.ptr, string.len, seed));
|
|
|
|
}
|
|
|
|
|
2023-08-14 08:26:11 +00:00
|
|
|
u64 oc_hash_xx64_string(oc_str8 string)
|
2023-04-29 17:25:40 +00:00
|
|
|
{
|
|
|
|
return(xxh_64(string.ptr, string.len, 0));
|
|
|
|
}
|