From edc8d6fa7cd9e552fc4d33f732af0ee22764e086 Mon Sep 17 00:00:00 2001 From: Tomas Vondra Date: Thu, 26 Jul 2018 16:16:38 +0200 Subject: [PATCH 5/6] 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 @@ -216,11 +216,14 @@ float8_mi(const float8 val1, const float8 val2) 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; } @@ -228,11 +231,14 @@ float4_mul(const float4 val1, const float4 val2) 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; } @@ -240,6 +246,7 @@ float8_mul(const float8 val1, const float8 val2) 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) @@ -248,7 +255,10 @@ float4_div(const float4 val1, const float4 val2) 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; } @@ -256,6 +266,7 @@ float4_div(const float4 val1, const float4 val2) 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) @@ -264,7 +275,10 @@ float8_div(const float8 val1, const float8 val2) 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; } -- 2.13.6