Further portability tweaks for float4/float8 hash functions.
authorTom Lane
Sat, 4 Sep 2021 20:29:08 +0000 (16:29 -0400)
committerTom Lane
Sat, 4 Sep 2021 20:29:08 +0000 (16:29 -0400)
Attempting to make hashfloat4() look as much as possible like
hashfloat8(), I'd figured I could replace NaNs with get_float4_nan()
before widening to float8.  However, results from protosciurus
and topminnow show that on some platforms that produces a different
bit-pattern from get_float8_nan(), breaking the intent of ce773f230.
Rearrange so that we use the result of get_float8_nan() for all NaN
cases.  As before, back-patch.

src/backend/access/hash/hashfunc.c

index 68c3ebb9bba3feaa208bccd29160a1cb7fa9ca01..242333920e714f360d6e5b3f35f68c170e5e4dfd 100644 (file)
@@ -151,14 +151,6 @@ hashfloat4(PG_FUNCTION_ARGS)
    if (key == (float4) 0)
        PG_RETURN_UINT32(0);
 
-   /*
-    * Similarly, NaNs can have different bit patterns but they should all
-    * compare as equal.  For backwards-compatibility reasons we force them to
-    * have the hash value of a standard NaN.
-    */
-   if (isnan(key))
-       key = get_float4_nan();
-
    /*
     * To support cross-type hashing of float8 and float4, we want to return
     * the same hash value hashfloat8 would produce for an equal float8 value.
@@ -168,6 +160,16 @@ hashfloat4(PG_FUNCTION_ARGS)
     */
    key8 = key;
 
+   /*
+    * Similarly, NaNs can have different bit patterns but they should all
+    * compare as equal.  For backwards-compatibility reasons we force them to
+    * have the hash value of a standard float8 NaN.  (You'd think we could
+    * replace key with a float4 NaN and then widen it; but on some old
+    * platforms, that way produces a different bit pattern.)
+    */
+   if (isnan(key8))
+       key8 = get_float8_nan();
+
    return hash_any((unsigned char *) &key8, sizeof(key8));
 }
 
@@ -181,9 +183,9 @@ hashfloat4extended(PG_FUNCTION_ARGS)
    /* Same approach as hashfloat4 */
    if (key == (float4) 0)
        PG_RETURN_UINT64(seed);
-   if (isnan(key))
-       key = get_float4_nan();
    key8 = key;
+   if (isnan(key8))
+       key8 = get_float8_nan();
 
    return hash_any_extended((unsigned char *) &key8, sizeof(key8), seed);
 }