From 8cadeef784338f635f1f2dfa6d28b799fc92a822 Mon Sep 17 00:00:00 2001 From: Emre Hasegeli Date: Thu, 2 Nov 2017 12:21:19 +0100 Subject: [PATCH 5/6] float-zero-v07 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)