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

View File

@ -50,5 +50,6 @@ jobs:
with:
draft: true
files: |
./dist/*.zip
./*.zip
./*.msi

View File

@ -1,8 +1,11 @@
# Changelog
All notable changes to this project will be documented in this file.
## Unreleased - ???
- Update hash function.
## 1.19.1 - 2021-12-04
- Add an optional `prefix` paramater to `debug/stacktrace` to allow printing prettier error messages.
- Add an optional `prefix` parameter to `debug/stacktrace` to allow printing prettier error messages.
- Remove appveyor for CI pipeline
- Fixed a bug that prevented sending threaded abstracts over threaded channels.
- Fix bug in the `map` function with arity at least 3.

View File

@ -20,7 +20,7 @@
project('janet', 'c',
default_options : ['c_std=c99', 'build.c_std=c99', 'b_lundef=false', 'default_library=both'],
version : '1.19.1')
version : '1.19.2')
# Global settings
janet_path = join_paths(get_option('prefix'), get_option('libdir'), 'janet')

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" */

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;

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);