1
0
mirror of https://github.com/janet-lang/janet synced 2026-05-31 01:32:15 +00:00

Update hash mixing behavior - address #889

Try to have better behavior when mixing sub-hashes that are not uniform and
randomly distributed. Premultiply by a large prime before mixing to
"spread entropy" if it is concentrated in a certain subset of bits.
This commit is contained in:
Calvin Rose
2021-12-05 16:31:18 -06:00
parent 4dc281a05f
commit 545c09e202
6 changed files with 19 additions and 11 deletions
+3 -3
View File
@@ -5,9 +5,9 @@
#define JANET_VERSION_MAJOR 1
#define JANET_VERSION_MINOR 19
#define JANET_VERSION_PATCH 1
#define JANET_VERSION_EXTRA ""
#define JANET_VERSION "1.19.1"
#define JANET_VERSION_PATCH 2
#define JANET_VERSION_EXTRA "-dev"
#define JANET_VERSION "1.19.2-dev"
/* #define JANET_BUILD "local" */
+9 -6
View File
@@ -224,13 +224,16 @@ int32_t janet_string_calchash(const uint8_t *str, int32_t len) {
#endif
uint32_t janet_hash_mix(uint32_t input, uint32_t more) {
return input ^ ((more * 2119589369u) + 0x9e3779b9 + (input << 6) + (input >> 2));
}
/* Computes hash of an array of values */
int32_t janet_array_calchash(const Janet *array, int32_t len) {
const Janet *end = array + len;
uint32_t hash = 0;
uint32_t hash = 33;
while (array < end) {
uint32_t elem = janet_hash(*array++);
hash ^= elem + 0x9e3779b9 + (hash << 6) + (hash >> 2);
hash = janet_hash_mix(hash, janet_hash(*array++));
}
return (int32_t) hash;
}
@@ -238,10 +241,10 @@ int32_t janet_array_calchash(const Janet *array, int32_t len) {
/* Computes hash of an array of values */
int32_t janet_kv_calchash(const JanetKV *kvs, int32_t len) {
const JanetKV *end = kvs + len;
uint32_t hash = 0;
uint32_t hash = 33;
while (kvs < end) {
hash ^= janet_hash(kvs->key) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
hash ^= janet_hash(kvs->value) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
hash = janet_hash_mix(hash, janet_hash(kvs->key));
hash = janet_hash_mix(hash, janet_hash(kvs->value));
kvs++;
}
return (int32_t) hash;
+1
View File
@@ -56,6 +56,7 @@
} while (0)
/* Utils */
uint32_t janet_hash_mix(uint32_t input, uint32_t more);
#define janet_maphash(cap, hash) ((uint32_t)(hash) & (cap - 1))
int janet_valid_utf8(const uint8_t *str, int32_t len);
int janet_is_symbol_char(uint8_t c);