diff options
author | Sergei Zimmerman <sergei.zimmerman@syntacore.com> | 2025-02-25 18:05:40 +0000 |
---|---|---|
committer | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2025-02-26 17:17:25 -0300 |
commit | 9e51ae3cd0c7f65bdeba93b7f1d780cdb21fc269 (patch) | |
tree | bad4fd6410177c1cc4859d2102ff75bac939ba8c /sysdeps | |
parent | 2fe5e2af0995a6e6ee2c761e55e7596a3220d07c (diff) | |
download | glibc-9e51ae3cd0c7f65bdeba93b7f1d780cdb21fc269.zip glibc-9e51ae3cd0c7f65bdeba93b7f1d780cdb21fc269.tar.gz glibc-9e51ae3cd0c7f65bdeba93b7f1d780cdb21fc269.tar.bz2 |
sysdeps/ieee754: Fix remainder sign of zero for FE_DOWNWARD (BZ #32711)
Single-precision remainderf() and quad-precision remainderl()
implementation derived from Sun is affected by an issue when the result
is +-0. IEEE754 requires that if remainder(x, y) = 0, its sign shall be
that of x regardless of the rounding direction.
The implementation seems to have assumed that x - x = +0 in all
rounding modes, which is not the case. When rounding direction is
roundTowardNegative the sign of an exact zero sum (or difference) is −0.
Regression tests that triggered this erroneous behavior are added to
math/libm-test-remainder.inc.
Tested for cross riscv64 and powerpc.
Original fix by: Bruce Evans <bde@FreeBSD.org> in FreeBSD's
a2ddfa5ea726c56dbf825763ad371c261b89b7c7.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Diffstat (limited to 'sysdeps')
-rw-r--r-- | sysdeps/ieee754/flt-32/e_remainderf.c | 3 | ||||
-rw-r--r-- | sysdeps/ieee754/ldbl-128/e_remainderl.c | 5 |
2 files changed, 7 insertions, 1 deletions
diff --git a/sysdeps/ieee754/flt-32/e_remainderf.c b/sysdeps/ieee754/flt-32/e_remainderf.c index 8178136..bb066b7 100644 --- a/sysdeps/ieee754/flt-32/e_remainderf.c +++ b/sysdeps/ieee754/flt-32/e_remainderf.c @@ -56,6 +56,9 @@ __ieee754_remainderf(float x, float p) } } GET_FLOAT_WORD(hx,x); + /* Make sure x is not -0. This can occur only when x = p + and rounding direction is towards negative infinity. */ + if (hx==0x80000000) hx = 0; SET_FLOAT_WORD(x,hx^sx); return x; } diff --git a/sysdeps/ieee754/ldbl-128/e_remainderl.c b/sysdeps/ieee754/ldbl-128/e_remainderl.c index 07a15c2..1e8605f 100644 --- a/sysdeps/ieee754/ldbl-128/e_remainderl.c +++ b/sysdeps/ieee754/ldbl-128/e_remainderl.c @@ -64,7 +64,10 @@ __ieee754_remainderl(_Float128 x, _Float128 p) if(x>=p_half) x -= p; } } - GET_LDOUBLE_MSW64(hx,x); + GET_LDOUBLE_WORDS64(hx,lx,x); + /* Make sure x is not -0. This can occur only when x = p + and rounding direction is towards negative infinity. */ + if ((hx==0x8000000000000000ULL)&&(lx==0)) hx = 0; SET_LDOUBLE_MSW64(x,hx^sx); return x; } |