]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Fix ldbl-128ibm ceill, floorl, roundl and truncl zero-sign handling
authorAurelien Jarno <aurelien@aurel32.net>
Tue, 20 Jan 2026 17:25:08 +0000 (18:25 +0100)
committerAurelien Jarno <aurelien@aurel32.net>
Sat, 24 Jan 2026 10:38:10 +0000 (11:38 +0100)
When the result of ceill, floorl, roundl and truncl is zero, the sign of
the result must match the sign of the input. For the IBM 128-bit long
double format, the sign is determined by the high part.

Ensure the correct sign when the high part is the result of
computations, by copying the sign from the input high part to the output
high part. On POWER, this conveniently maps to the fcpsgn instruction.

In addition add test for the values provided in BZ #33623, and for the
opposite value when the result is 0.

Fixes: BZ #33623
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
math/libm-test-ceil.inc
math/libm-test-floor.inc
math/libm-test-round.inc
math/libm-test-trunc.inc
sysdeps/ieee754/ldbl-128ibm/s_ceill.c
sysdeps/ieee754/ldbl-128ibm/s_floorl.c
sysdeps/ieee754/ldbl-128ibm/s_roundl.c
sysdeps/ieee754/ldbl-128ibm/s_truncl.c

index a471b43932ff04c1597f76aa79254f70626d8f1a..48be68cf919b9781bf8870705668c4c134258020 100644 (file)
@@ -79,6 +79,9 @@ static const struct test_f_f_data ceil_test_data[] =
     TEST_f_f (ceil, -max_value, -max_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
 #if MANT_DIG >= 64
+    /* The input value can only be represented in long double.  */
+    TEST_f_f (ceil, -0x0.ffffffffffffffffp0L, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
     /* The result can only be represented in long double.  */
     TEST_f_f (ceil, 4503599627370495.5L, 4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (ceil, 4503599627370496.25L, 4503599627370497.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
index dee4afff7a35a9ae7a1ad557692d6f93c61fe4d6..bc945a6c22d67a42d3cd1ed1c278c6c37f6bbe97 100644 (file)
@@ -79,6 +79,9 @@ static const struct test_f_f_data floor_test_data[] =
     TEST_f_f (floor, -max_value, -max_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
 #if MANT_DIG >= 64
+    /* The input value can only be represented in long double.  */
+    TEST_f_f (floor, 0x0.ffffffffffffffffp0L, plus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
     /* The result can only be represented in long double.  */
     TEST_f_f (floor, 4503599627370495.5L, 4503599627370495.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (floor, 4503599627370496.25L, 4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
index 898ff3791bdf6538223b26fac7a602187b1e6601..1395c51d5d9d9ca6629e5d08f569fb923ae73a2c 100644 (file)
@@ -99,6 +99,10 @@ static const struct test_f_f_data round_test_data[] =
 #endif
 
 #if MANT_DIG >= 64
+    /* The input value can only be represented in long double.  */
+    TEST_f_f (round, 0x0.ffffffffffffffffp-1L, plus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (round, -0x0.ffffffffffffffffp-1L, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
     /* The result can only be represented in long double.  */
     TEST_f_f (round, 4503599627370495.5L, 4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (round, 4503599627370496.25L, 4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
index 7df741f3ba3b02bded73c11739d99edff8c55580..5d69cd4b5bcdb4f421fc2a601d88c1b3314172d0 100644 (file)
@@ -91,6 +91,10 @@ static const struct test_f_f_data trunc_test_data[] =
     TEST_f_f (trunc, -4294967296.625L, -4294967296.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
 #if MANT_DIG >= 64
+    /* The input value can only be represented in long double.  */
+    TEST_f_f (trunc, 0x0.ffffffffffffffffp0L, plus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_f_f (trunc, -0x0.ffffffffffffffffp0L, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
     /* The result can only be represented in long double.  */
     TEST_f_f (trunc, 4503599627370495.5L, 4503599627370495.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
     TEST_f_f (trunc, 4503599627370496.25L, 4503599627370496.0L, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
index 8038cf9fdad61f56845bd4442723d22958cdb3b7..88bc364db50c4385eb837baf6ed387a370748a13 100644 (file)
@@ -54,6 +54,9 @@ __ceill (long double x)
          xh = hi;
          xl = lo;
          ldbl_canonicalize_int (&xh, &xl);
+
+         /* Ensure we return -0 rather than +0 when appropriate.  */
+         xh = copysign (xh, hi);
        }
     }
   else
index 23f45b773f3469161349ed4787d4c66327343bd5..4a8294cc78437c1d9f61106fd05a8f02d2d57b21 100644 (file)
@@ -54,6 +54,9 @@ __floorl (long double x)
          xh = hi;
          xl = lo;
          ldbl_canonicalize_int (&xh, &xl);
+
+         /* Ensure we return -0 rather than +0 when appropriate.  */
+         xh = copysign (xh, hi);
        }
     }
   else
index e8948a0c05efd9b1b83f6ad68edcc48edad7812c..340a63c76a66ecd85852cdd2d9d631cb68657448 100644 (file)
@@ -80,6 +80,9 @@ __roundl (long double x)
          xh = hi;
          ldbl_canonicalize_int (&xh, &xl);
        }
+
+      /* Ensure we return -0 rather than +0 when appropriate.  */
+      xh = copysign(xh, hi);
     }
   else
     /* Quiet signaling NaN arguments.  */
index 7f0b77cd3fff83a2d25471895262ebcac8a3d390..21ecbd0c85fed528c73dcb85dd4a1307da66036b 100644 (file)
@@ -56,6 +56,9 @@ __truncl (long double x)
          xh = hi;
          xl = lo;
          ldbl_canonicalize_int (&xh, &xl);
+
+         /* Ensure we return -0 rather than +0 when appropriate.  */
+         xh = copysign (xh, hi);
        }
     }
   else