From fd295d0c687eb8f2e9ec6d9bb1cedf0cc45e1dd8 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sat, 4 Sep 2021 16:29:08 -0400
Subject: [PATCH] Further portability tweaks for float4/float8 hash functions.

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 | 22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/src/backend/access/hash/hashfunc.c b/src/backend/access/hash/hashfunc.c
index 89d85f5a22..a43edfe0cc 100644
--- a/src/backend/access/hash/hashfunc.c
+++ b/src/backend/access/hash/hashfunc.c
@@ -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);
 }