Make floating-point "NaN / 0" return NaN instead of raising an error.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 20 Jul 2020 23:44:41 +0000 (19:44 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 20 Jul 2020 23:44:45 +0000 (19:44 -0400)
This is more consistent with the IEEE 754 spec and our treatment of
NaNs elsewhere; in particular, the case has always acted that way in
"numeric" arithmetic.

Noted by Dean Rasheed.

Discussion: https://postgr.es/m/3421746.1594927785@sss.pgh.pa.us

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 8d4bbc51a654dfd8d9f4c481c2d1a778142beb22..e2aae8ef1773b3bc1e570d2f9529a76d2a239a4d 100644 (file)
@@ -222,7 +222,7 @@ float4_div(const float4 val1, const float4 val2)
 {
    float4      result;
 
-   if (unlikely(val2 == 0.0f))
+   if (unlikely(val2 == 0.0f) && !isnan(val1))
        float_zero_divide_error();
    result = val1 / val2;
    if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
@@ -238,7 +238,7 @@ float8_div(const float8 val1, const float8 val2)
 {
    float8      result;
 
-   if (unlikely(val2 == 0.0))
+   if (unlikely(val2 == 0.0) && !isnan(val1))
        float_zero_divide_error();
    result = val1 / val2;
    if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
index 6c89af6394fc4915e129ddaffb51c13358cca3a1..38b847a1adbdf9de4621d34dcc1eed45a3e071b1 100644 (file)
@@ -143,6 +143,12 @@ SELECT 'nan'::float4 / 'nan'::float4;
       NaN
 (1 row)
 
+SELECT 'nan'::float4 / '0'::float4;
+ ?column? 
+----------
+      NaN
+(1 row)
+
 SELECT 'nan'::numeric::float4;
  float4 
 --------
index d6c22c1752a303375f264d0d5f2814812a872ba6..310402b6ee22ef2a7fe80d9447fb1c642315baf2 100644 (file)
@@ -143,6 +143,12 @@ SELECT 'nan'::float4 / 'nan'::float4;
       NaN
 (1 row)
 
+SELECT 'nan'::float4 / '0'::float4;
+ ?column? 
+----------
+      NaN
+(1 row)
+
 SELECT 'nan'::numeric::float4;
  float4 
 --------
index c635dd7dcb67f47dbd87a38528b49e457755c6fa..2304b579d2be5e23878ef518dc52608d500af048 100644 (file)
@@ -126,6 +126,12 @@ SELECT 'nan'::float8 / 'nan'::float8;
       NaN
 (1 row)
 
+SELECT 'nan'::float8 / '0'::float8;
+ ?column? 
+----------
+      NaN
+(1 row)
+
 SELECT 'nan'::numeric::float8;
  float8 
 --------
index 393d98fb14382aac2f16e9b9684265a6d3b3ca31..1fcf823c21b135d1901d40f48461ef8eaff32110 100644 (file)
@@ -50,6 +50,7 @@ SELECT ' INFINITY    x'::float4;
 SELECT 'Infinity'::float4 + 100.0;
 SELECT 'Infinity'::float4 / 'Infinity'::float4;
 SELECT 'nan'::float4 / 'nan'::float4;
+SELECT 'nan'::float4 / '0'::float4;
 SELECT 'nan'::numeric::float4;
 
 SELECT '' AS five, * FROM FLOAT4_TBL;
index 288969aed65d0090cd420fefcaf180452d23925c..f103871cdb2ffc2c6862a379c39ee62a9c1cd72c 100644 (file)
@@ -43,6 +43,7 @@ SELECT ' INFINITY    x'::float8;
 SELECT 'Infinity'::float8 + 100.0;
 SELECT 'Infinity'::float8 / 'Infinity'::float8;
 SELECT 'nan'::float8 / 'nan'::float8;
+SELECT 'nan'::float8 / '0'::float8;
 SELECT 'nan'::numeric::float8;
 
 SELECT '' AS five, * FROM FLOAT8_TBL;