0005-float-zero-v05.patch

application/octet-stream

Filename: 0005-float-zero-v05.patch
Type: application/octet-stream
Part: 4
Message: Re: [PATCH] Improve geometric types

Patch

Format: format-patch
Series: patch v5-0005
Subject: float-zero-v05
File+
src/include/utils/float.h 20 6
From 5b859f00b0580c4a3259403a13ecf18b4f183474 Mon Sep 17 00:00:00 2001
From: Emre Hasegeli <emre@hasegeli.com>
Date: Thu, 2 Nov 2017 12:21:19 +0100
Subject: [PATCH 5/6] float-zero-v05

Check for float -0 after multiplications and divisions

Discussion: https://www.postgresql.org/message-id/CAE2gYzxF7-5djV6-cEvqQu-fNsnt%3DEqbOURx7ZDg%2BVv6ZMTWbg%40mail.gmail.com
---
 src/include/utils/float.h | 26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/src/include/utils/float.h b/src/include/utils/float.h
index 0e8483c930..e359d8a3d4 100644
--- a/src/include/utils/float.h
+++ b/src/include/utils/float.h
@@ -209,69 +209,83 @@ float8_mi(const float8 val1, const float8 val2)
 
 	result = val1 - val2;
 	check_float8_val(result, isinf(val1) || isinf(val2), true);
 
 	return result;
 }
 
 static inline float4
 float4_mul(const float4 val1, const float4 val2)
 {
+	const bool	zero_is_valid = val1 == 0.0f || val2 == 0.0f;
 	float4		result;
 
 	result = val1 * val2;
-	check_float4_val(result, isinf(val1) || isinf(val2),
-					 val1 == 0.0f || val2 == 0.0f);
+	check_float4_val(result, isinf(val1) || isinf(val2), zero_is_valid);
+
+	if (zero_is_valid && unlikely(result == -0.0f))
+		result = 0.0f;
 
 	return result;
 }
 
 static inline float8
 float8_mul(const float8 val1, const float8 val2)
 {
+	const bool	zero_is_valid = val1 == 0.0 || val2 == 0.0;
 	float8		result;
 
 	result = val1 * val2;
-	check_float8_val(result, isinf(val1) || isinf(val2),
-					 val1 == 0.0 || val2 == 0.0);
+	check_float8_val(result, isinf(val1) || isinf(val2), zero_is_valid);
+
+	if (zero_is_valid && unlikely(result == -0.0))
+		result = 0.0;
 
 	return result;
 }
 
 static inline float4
 float4_div(const float4 val1, const float4 val2)
 {
+	const bool	zero_is_valid = val1 == 0.0f;
 	float4		result;
 
 	if (val2 == 0.0f)
 		ereport(ERROR,
 				(errcode(ERRCODE_DIVISION_BY_ZERO),
 				 errmsg("division by zero")));
 
 	result = val1 / val2;
-	check_float4_val(result, isinf(val1) || isinf(val2), val1 == 0.0f);
+	check_float4_val(result, isinf(val1) || isinf(val2), zero_is_valid);
+
+	if (zero_is_valid && unlikely(result == -0.0f))
+		result = 0.0f;
 
 	return result;
 }
 
 static inline float8
 float8_div(const float8 val1, const float8 val2)
 {
+	const bool	zero_is_valid = val1 == 0.0;
 	float8		result;
 
 	if (val2 == 0.0)
 		ereport(ERROR,
 				(errcode(ERRCODE_DIVISION_BY_ZERO),
 				 errmsg("division by zero")));
 
 	result = val1 / val2;
-	check_float8_val(result, isinf(val1) || isinf(val2), val1 == 0.0);
+	check_float8_val(result, isinf(val1) || isinf(val2), zero_is_valid);
+
+	if (zero_is_valid && unlikely(result == -0.0))
+		result = 0.0;
 
 	return result;
 }
 
 /*
  * Routines for NaN-aware comparisons
  *
  * We consider all NaNs to be equal and larger than any non-NaN. This is
  * somewhat arbitrary; the important thing is to have a consistent sort
  * order.
-- 
2.14.3 (Apple Git-98)