Remove underflow error in float division with infinite divisor.
authorTom Lane <[email protected]>
Wed, 4 Nov 2020 23:11:15 +0000 (18:11 -0500)
committerTom Lane <[email protected]>
Wed, 4 Nov 2020 23:11:15 +0000 (18:11 -0500)
float4_div and float8_div correctly produced zero for zero divided
by infinity, but threw an underflow error for nonzero finite values
divided by infinity.  This seems wrong; at the very least it's
inconsistent with the behavior recently implemented for numeric
infinities.  Remove the error and allow zero to be returned.

This patch also removes a useless isinf() test from the overflow
checks in these functions (non-Inf divided by Inf can't produce Inf).

Extracted from a larger patch; this seems significant outside the
context of geometric operators, so it deserves its own commit.

Kyotaro Horiguchi

Discussion: https://postgr.es/m/CAGf+fX70rWFOk5cd00uMfa__0yP+vtQg5ck7c2Onb-Yczp0URA@mail.gmail.com

src/include/utils/float.h
src/test/regress/expected/float4-misrounded-input.out
src/test/regress/expected/float4.out
src/test/regress/expected/float8.out
src/test/regress/sql/float4.sql
src/test/regress/sql/float8.sql

index e2aae8ef1773b3bc1e570d2f9529a76d2a239a4d..79bf8daca8094950a2cbe163353530aa9dfd423a 100644 (file)
@@ -225,9 +225,9 @@ float4_div(const float4 val1, const float4 val2)
    if (unlikely(val2 == 0.0f) && !isnan(val1))
        float_zero_divide_error();
    result = val1 / val2;
-   if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
+   if (unlikely(isinf(result)) && !isinf(val1))
        float_overflow_error();
-   if (unlikely(result == 0.0f) && val1 != 0.0f)
+   if (unlikely(result == 0.0f) && val1 != 0.0f && !isinf(val2))
        float_underflow_error();
 
    return result;
@@ -241,9 +241,9 @@ float8_div(const float8 val1, const float8 val2)
    if (unlikely(val2 == 0.0) && !isnan(val1))
        float_zero_divide_error();
    result = val1 / val2;
-   if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
+   if (unlikely(isinf(result)) && !isinf(val1))
        float_overflow_error();
-   if (unlikely(result == 0.0) && val1 != 0.0)
+   if (unlikely(result == 0.0) && val1 != 0.0 && !isinf(val2))
        float_underflow_error();
 
    return result;
index 38b847a1adbdf9de4621d34dcc1eed45a3e071b1..7b4964e17996bcf7da0849059d4b2ee5b2805737 100644 (file)
@@ -137,6 +137,12 @@ SELECT 'Infinity'::float4 / 'Infinity'::float4;
       NaN
 (1 row)
 
+SELECT '42'::float4 / 'Infinity'::float4;
+ ?column? 
+----------
+        0
+(1 row)
+
 SELECT 'nan'::float4 / 'nan'::float4;
  ?column? 
 ----------
index 310402b6ee22ef2a7fe80d9447fb1c642315baf2..dde8c343ce45a8841c7f1410c1c121778ba14db7 100644 (file)
@@ -137,6 +137,12 @@ SELECT 'Infinity'::float4 / 'Infinity'::float4;
       NaN
 (1 row)
 
+SELECT '42'::float4 / 'Infinity'::float4;
+ ?column? 
+----------
+        0
+(1 row)
+
 SELECT 'nan'::float4 / 'nan'::float4;
  ?column? 
 ----------
index 2304b579d2be5e23878ef518dc52608d500af048..63da733893793b35d5ace66b2d4b2ed9e31868df 100644 (file)
@@ -120,6 +120,12 @@ SELECT 'Infinity'::float8 / 'Infinity'::float8;
       NaN
 (1 row)
 
+SELECT '42'::float8 / 'Infinity'::float8;
+ ?column? 
+----------
+        0
+(1 row)
+
 SELECT 'nan'::float8 / 'nan'::float8;
  ?column? 
 ----------
index 1fcf823c21b135d1901d40f48461ef8eaff32110..14e54714826a380c41724e279e86e3818af60b2c 100644 (file)
@@ -49,6 +49,7 @@ SELECT ' INFINITY    x'::float4;
 
 SELECT 'Infinity'::float4 + 100.0;
 SELECT 'Infinity'::float4 / 'Infinity'::float4;
+SELECT '42'::float4 / 'Infinity'::float4;
 SELECT 'nan'::float4 / 'nan'::float4;
 SELECT 'nan'::float4 / '0'::float4;
 SELECT 'nan'::numeric::float4;
index f103871cdb2ffc2c6862a379c39ee62a9c1cd72c..7e81719853343bebdad75662487632e18b3187fe 100644 (file)
@@ -42,6 +42,7 @@ SELECT ' INFINITY    x'::float8;
 
 SELECT 'Infinity'::float8 + 100.0;
 SELECT 'Infinity'::float8 / 'Infinity'::float8;
+SELECT '42'::float8 / 'Infinity'::float8;
 SELECT 'nan'::float8 / 'nan'::float8;
 SELECT 'nan'::float8 / '0'::float8;
 SELECT 'nan'::numeric::float8;