Skip to content

Commit 6faf86d

Browse files
committed
fix hash for floats
1 parent de9f8c0 commit 6faf86d

File tree

1 file changed

+31
-3
lines changed

1 file changed

+31
-3
lines changed

pandas/_libs/src/klib/khash_python.h

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,12 +242,40 @@ int PANDAS_INLINE pyobject_cmp(PyObject* a, PyObject* b) {
242242
}
243243

244244

245+
Py_hash_t PANDAS_INLINE _Pandas_HashDouble(double val){
246+
//Since Python3.10, nan is no longer has hash 0
247+
if (Py_IS_NAN(val)) {
248+
return 0;
249+
}
250+
#if PY_VERSION_HEX < 0x030A0000
251+
return _Py_HashDouble(val);
252+
#else
253+
return _Py_HashDouble(NULL, val);
254+
#endif
255+
}
256+
257+
258+
Py_hash_t PANDAS_INLINE hash_float(PyFloatObject* key){
259+
return _Pandas_HashDouble(PyFloat_AS_DOUBLE(key));
260+
}
261+
262+
245263
khint32_t PANDAS_INLINE kh_python_hash_func(PyObject* key){
264+
Py_hash_t hash;
246265
// For PyObject_Hash holds:
247266
// hash(0.0) == 0 == hash(-0.0)
248-
// hash(X) == 0 if X is a NaN-value
249-
// so it is OK to use it directly for doubles
250-
Py_hash_t hash = PyObject_Hash(key);
267+
// yet for different nan-object different hash-values
268+
// are possible
269+
if (PyFloat_CheckExact(key)) {
270+
// we cannot use kh_float64_hash_func
271+
// becase float(k) == k holds for any int-object k
272+
// and kh_float64_hash_func doesn't respect it
273+
hash = hash_float((PyFloatObject*)key);
274+
}
275+
else {
276+
hash = PyObject_Hash(key);
277+
}
278+
251279
if (hash == -1) {
252280
PyErr_Clear();
253281
return 0;

0 commit comments

Comments
 (0)