1
0
mirror of https://github.com/janet-lang/janet synced 2024-12-01 04:19:55 +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

View File

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

View File

@ -1,8 +1,11 @@
# Changelog # Changelog
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## Unreleased - ???
- Update hash function.
## 1.19.1 - 2021-12-04 ## 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 - Remove appveyor for CI pipeline
- Fixed a bug that prevented sending threaded abstracts over threaded channels. - Fixed a bug that prevented sending threaded abstracts over threaded channels.
- Fix bug in the `map` function with arity at least 3. - Fix bug in the `map` function with arity at least 3.

View File

@ -20,7 +20,7 @@
project('janet', 'c', project('janet', 'c',
default_options : ['c_std=c99', 'build.c_std=c99', 'b_lundef=false', 'default_library=both'], 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 # Global settings
janet_path = join_paths(get_option('prefix'), get_option('libdir'), 'janet') 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_MAJOR 1
#define JANET_VERSION_MINOR 19 #define JANET_VERSION_MINOR 19
#define JANET_VERSION_PATCH 1 #define JANET_VERSION_PATCH 2
#define JANET_VERSION_EXTRA "" #define JANET_VERSION_EXTRA "-dev"
#define JANET_VERSION "1.19.1" #define JANET_VERSION "1.19.2-dev"
/* #define JANET_BUILD "local" */ /* #define JANET_BUILD "local" */

View File

@ -224,13 +224,16 @@ int32_t janet_string_calchash(const uint8_t *str, int32_t len) {
#endif #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 */ /* Computes hash of an array of values */
int32_t janet_array_calchash(const Janet *array, int32_t len) { int32_t janet_array_calchash(const Janet *array, int32_t len) {
const Janet *end = array + len; const Janet *end = array + len;
uint32_t hash = 0; uint32_t hash = 33;
while (array < end) { while (array < end) {
uint32_t elem = janet_hash(*array++); hash = janet_hash_mix(hash, janet_hash(*array++));
hash ^= elem + 0x9e3779b9 + (hash << 6) + (hash >> 2);
} }
return (int32_t) hash; 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 */ /* Computes hash of an array of values */
int32_t janet_kv_calchash(const JanetKV *kvs, int32_t len) { int32_t janet_kv_calchash(const JanetKV *kvs, int32_t len) {
const JanetKV *end = kvs + len; const JanetKV *end = kvs + len;
uint32_t hash = 0; uint32_t hash = 33;
while (kvs < end) { while (kvs < end) {
hash ^= janet_hash(kvs->key) + 0x9e3779b9 + (hash << 6) + (hash >> 2); hash = janet_hash_mix(hash, janet_hash(kvs->key));
hash ^= janet_hash(kvs->value) + 0x9e3779b9 + (hash << 6) + (hash >> 2); hash = janet_hash_mix(hash, janet_hash(kvs->value));
kvs++; kvs++;
} }
return (int32_t) hash; return (int32_t) hash;

View File

@ -56,6 +56,7 @@
} while (0) } while (0)
/* Utils */ /* Utils */
uint32_t janet_hash_mix(uint32_t input, uint32_t more);
#define janet_maphash(cap, hash) ((uint32_t)(hash) & (cap - 1)) #define janet_maphash(cap, hash) ((uint32_t)(hash) & (cap - 1))
int janet_valid_utf8(const uint8_t *str, int32_t len); int janet_valid_utf8(const uint8_t *str, int32_t len);
int janet_is_symbol_char(uint8_t c); int janet_is_symbol_char(uint8_t c);