mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Fix $$str_hash to use a5hash like String.hash() (#2403)
* Fix `$$str_hash` to use `a5hash` like `String.hash()`
This commit is contained in:
@@ -208,6 +208,7 @@ static inline int char_hex_to_nibble(char c);
|
||||
INLINE char char_nibble_to_hex(int c);
|
||||
|
||||
static inline uint32_t fnv1a(const char *key, uint32_t len);
|
||||
static inline uint64_t a5hash(const char *key, uint32_t len, uint64_t seed);
|
||||
|
||||
INLINE uint32_t vec_size(const void *vec);
|
||||
static inline void vec_resize(void *vec, uint32_t new_size);
|
||||
@@ -256,6 +257,83 @@ static inline uint32_t fnv1a(const char *key, uint32_t len)
|
||||
return hash;
|
||||
}
|
||||
|
||||
// see: `int64_mult` in bigint.c - there is no need to import all these declarations just for this
|
||||
static inline void _a5mul(uint64_t u, uint64_t v, uint64_t *lo, uint64_t *hi)
|
||||
{
|
||||
uint64_t ul = u & 0xFFFFFFFF;
|
||||
uint64_t vl = v & 0xFFFFFFFF;
|
||||
uint64_t t = ul * vl;
|
||||
uint64_t w3 = t & 0xFFFFFFFF;
|
||||
uint64_t k = t >> 32;
|
||||
|
||||
u >>= 32;
|
||||
t = u * vl + k;
|
||||
k = t & 0xFFFFFFFF;
|
||||
uint64_t w1 = t >> 32;
|
||||
|
||||
v >>= 32;
|
||||
t = ul * v + k;
|
||||
|
||||
*hi = (u * v) + w1 + (t >> 32);
|
||||
*lo = (t << 32) + w3;
|
||||
}
|
||||
|
||||
static inline uint64_t a5hash(const char *key, uint32_t len, uint64_t seed)
|
||||
{
|
||||
uint64_t widened_len = (uint64_t)len;
|
||||
uint64_t seed1 = 0x243F6A8885A308D3 ^ widened_len;
|
||||
uint64_t seed2 = 0x452821E638D01377 ^ widened_len;
|
||||
uint64_t val10 = 0xAAAAAAAAAAAAAAAA;
|
||||
uint64_t val01 = 0x5555555555555555;
|
||||
uint64_t a, b;
|
||||
const char *scroll = key, *end = key + len;
|
||||
|
||||
_a5mul(seed2 ^ (seed & val10), seed1 ^ (seed & val01), &seed1, &seed2);
|
||||
|
||||
val10 ^= seed2;
|
||||
|
||||
if (len > 3)
|
||||
{
|
||||
if (len > 16)
|
||||
{
|
||||
val01 ^= seed1;
|
||||
|
||||
for (; end - scroll > 16; scroll += 16)
|
||||
{
|
||||
_a5mul(((uint64_t *)scroll)[0] ^ seed1, ((uint64_t *)scroll)[1] ^ seed2, &seed1, &seed2);
|
||||
|
||||
seed1 += val01;
|
||||
seed2 += val10;
|
||||
}
|
||||
|
||||
a = *(uint64_t *)(scroll + (end - scroll) - 16);
|
||||
b = *(uint64_t *)(scroll + (end - scroll) - 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
a = ((uint64_t)(*(uint32_t *)scroll) << 32) | *(uint32_t *)(end - 4);
|
||||
b = ((uint64_t)(*(uint32_t *)&scroll[(len >> 3) * 4]) << 32)
|
||||
| *(uint32_t *)(end - 4 - (len >> 3) * 4);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
a = len
|
||||
? (uint64_t)(
|
||||
(uint64_t)scroll[0]
|
||||
| (len > 1 ? ((uint64_t)scroll[1] << 8) : 0)
|
||||
| (len > 2 ? ((uint64_t)scroll[2] << 16) : 0)
|
||||
)
|
||||
: 0;
|
||||
b = 0;
|
||||
}
|
||||
|
||||
_a5mul(a ^ seed1, b ^ seed2, &seed1, &seed2);
|
||||
_a5mul(val01 ^ seed1, seed2, &a, &b);
|
||||
|
||||
return a ^ b;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t size;
|
||||
|
||||
Reference in New Issue
Block a user