constexpr u32 HASH_INIT = 5381; u32 sdbm_hash (void* data, s64 size) { u32 h = HASH_INIT; for (s64 i = 0; i < size; i += 1) { h = (h << 16) + (h << 6) - h + ((u8*)data)[i]; } return (u32)h; } u64 knuth_hash (u64 x) { constexpr u64 KNUTH_GOLDEN_RATIO_64 = 11400714819323198485ULL; return (KNUTH_GOLDEN_RATIO_64 * x); } u32 knuth_hash_u32 (u64 x) { u32 h = HASH_INIT; return (u32)((knuth_hash(x) ^ h) >> 32); } constexpr u64 FNV_64_PRIME = 0x100000001b3ULL; constexpr u64 FNV_64_OFFSET_BIAS = 0xcbf29ce484222325ULL; u64 fnv1a_hash (u64 x, u64 h = FNV_64_OFFSET_BIAS) { h ^= x; return h * FNV_64_PRIME; } // Good for hashing strings. u64 fnv1a_hash_any (void* data, s64 size, u64 h = FNV_64_OFFSET_BIAS) { for (s64 i = 0; i < size; i += 1) { h = fnv1a_hash( ((u8*)data)[i], h); } return h; } u32 table_hash_function_fnv1a (void* key, s64 size) { return (u32)fnv1a_hash_any(key, size); } u32 table_hash_function_knuth (void* key, s64 size) { Assert(size == 8); return knuth_hash_u32(*(u64*)key); } u32 string_hash_function_fnv1a (void* key, s64 size) { Assert(size == sizeof(string)); string key_as_string = *((string*)key); // #TODO It should be xor folded to the desired range rather than shifted. return (u32)(fnv1a_hash_any(key_as_string.data, key_as_string.count)); } bool u64_keys_match (void* key1, void* key2) { u64 key1_u64 = *(u64*)key1; u64 key2_u64 = *(u64*)key2; return key1_u64 == key2_u64; } bool string_keys_match (void* key1, void* key2) { string key1_s = *((string*)key1); string key2_s = *((string*)key2); return strings_match(key1_s, key2_s); }