@@ -8222,10 +8222,18 @@ frozendict_repr(PyObject *self)
82228222 return res ;
82238223}
82248224
8225- static Py_uhash_t
8226- _shuffle_bits (Py_uhash_t h )
8225+ // based on boost's old hash_combine
8226+ static inline Py_uhash_t
8227+ _combine_hashes (Py_uhash_t h1 , Py_uhash_t h2 )
82278228{
8228- return ((h ^ 89869747UL ) ^ (h << 16 )) * 3644798167UL ;
8229+ // 2^sizeof(Py_hash_t) / phi
8230+ #if SIZEOF_PY_HASH_T == 8
8231+ const Py_uhash_t GOLDEN_C = 0x9e3779b97f4a7c15ULL ;
8232+ #else
8233+ const Py_uhash_t GOLDEN_C = 0x9e3779b9UL ;
8234+ #endif
8235+ h1 ^= h2 + GOLDEN_C + (h1 << 6 ) + (h1 >> 2 );
8236+ return h1 ;
82298237}
82308238
82318239// Code copied from frozenset_hash()
@@ -8239,7 +8247,7 @@ frozendict_hash(PyObject *op)
82398247 }
82408248
82418249 PyDictObject * mp = _PyAnyDict_CAST (op );
8242- Py_uhash_t hash = 0 ;
8250+ Py_uhash_t hash = 0xfd1c74 ; // start at a different value from frozenset to avoid collision with empty frozenset
82438251
82448252 PyObject * key , * value ; // borrowed refs
82458253 Py_ssize_t pos = 0 ;
@@ -8248,13 +8256,11 @@ frozendict_hash(PyObject *op)
82488256 if (key_hash == -1 ) {
82498257 return -1 ;
82508258 }
8251- hash ^= _shuffle_bits (key_hash );
8252-
82538259 Py_hash_t value_hash = PyObject_Hash (value );
82548260 if (value_hash == -1 ) {
82558261 return -1 ;
82568262 }
8257- hash ^= _shuffle_bits ( value_hash );
8263+ hash ^= _combine_hashes ( key_hash , value_hash );
82588264 }
82598265
82608266 /* Factor in the number of active entries */
0 commit comments