Skip to content

Commit 152c000

Browse files
committed
fix hash for floats
1 parent 71ae658 commit 152c000

File tree

1 file changed

+31
-3
lines changed

1 file changed

+31
-3
lines changed

pandas/_libs/src/klib/khash_python.h

+31-3
Original file line numberDiff line numberDiff line change
@@ -251,12 +251,40 @@ int PANDAS_INLINE pyobject_cmp(PyObject* a, PyObject* b) {
251251
}
252252

253253

254+
Py_hash_t PANDAS_INLINE _Pandas_HashDouble(double val){
255+
//Since Python3.10, nan is no longer has hash 0
256+
if (Py_IS_NAN(val)) {
257+
return 0;
258+
}
259+
#if PY_VERSION_HEX < 0x030A0000
260+
return _Py_HashDouble(val);
261+
#else
262+
return _Py_HashDouble(NULL, val);
263+
#endif
264+
}
265+
266+
267+
Py_hash_t PANDAS_INLINE hash_float(PyFloatObject* key){
268+
return _Pandas_HashDouble(PyFloat_AS_DOUBLE(key));
269+
}
270+
271+
254272
khint32_t PANDAS_INLINE kh_python_hash_func(PyObject* key){
273+
Py_hash_t hash;
255274
// For PyObject_Hash holds:
256275
// hash(0.0) == 0 == hash(-0.0)
257-
// hash(X) == 0 if X is a NaN-value
258-
// so it is OK to use it directly for doubles
259-
Py_hash_t hash = PyObject_Hash(key);
276+
// yet for different nan-object different hash-values
277+
// are possible
278+
if (PyFloat_CheckExact(key)) {
279+
// we cannot use kh_float64_hash_func
280+
// becase float(k) == k holds for any int-object k
281+
// and kh_float64_hash_func doesn't respect it
282+
hash = hash_float((PyFloatObject*)key);
283+
}
284+
else {
285+
hash = PyObject_Hash(key);
286+
}
287+
260288
if (hash == -1) {
261289
PyErr_Clear();
262290
return 0;

0 commit comments

Comments
 (0)