◐ Shell
clean mode source ↗

gh-111545: Add Py_HashDouble() function by vstinner · Pull Request #113115 · python/cpython

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If prefer to have a deterministic behavior and always return the same hash value (0) if value is NaN. There are legit use cases to treat NaN as hash value 0.

With the following change, only check for, Py_HashDouble() hangs (fail to exit the loop) if value is NaN.

diff --git a/Python/pyhash.c b/Python/pyhash.c
index f64edde4043..23aa2dac7cc 100644
--- a/Python/pyhash.c
+++ b/Python/pyhash.c
@@ -90,14 +90,8 @@ Py_HashDouble(double v)
     double m;
     Py_uhash_t x, y;
 
-    if (!Py_IS_FINITE(v)) {
-        if (Py_IS_INFINITY(v)) {
-            return (v > 0 ? _PyHASH_INF : -_PyHASH_INF);
-        }
-        else {
-            assert(Py_IS_NAN(v));
-            return 0;
-        }
+    if (Py_IS_INFINITY(v)) {
+        return (v > 0 ? _PyHASH_INF : -_PyHASH_INF);
     }
 
     m = frexp(v, &e);

With the following change, Py_HashDouble() returns -_PyHASH_INF if value is NaN, since NaN > 0 is false:

diff --git a/Python/pyhash.c b/Python/pyhash.c
index f64edde4043..a853d6dad99 100644
--- a/Python/pyhash.c
+++ b/Python/pyhash.c
@@ -91,13 +91,8 @@ Py_HashDouble(double v)
     Py_uhash_t x, y;
 
     if (!Py_IS_FINITE(v)) {
-        if (Py_IS_INFINITY(v)) {
-            return (v > 0 ? _PyHASH_INF : -_PyHASH_INF);
-        }
-        else {
-            assert(Py_IS_NAN(v));
-            return 0;
-        }
+        // v can be NaN
+        return (v > 0 ? _PyHASH_INF : -_PyHASH_INF);
     }
 
     m = frexp(v, &e);