mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-16 10:00:12 +00:00
9120a57f48
The ldbl-128ibm implementations of remainderl and remquol have logic resulting in incorrect tests for equality of the absolute values of the arguments. Equality is tested based on the integer representations of the high and low parts, with the sign bit masked off the high part - but when this changes the sign of the high part, the sign of the low part needs to be changed as well, and failure to do this means arguments are wrongly treated as equal when they are not. This patch fixes the logic to adjust signs of low parts as needed. Tested for powerpc. [BZ #19603] * sysdeps/ieee754/ldbl-128ibm/e_remainderl.c (__ieee754_remainderl): Adjust sign of integer version of low part when taking absolute value of high part. * sysdeps/ieee754/ldbl-128ibm/s_remquol.c (__remquol): Likewise. * math/libm-test.inc (remainder_test_data): Add another test. (remquo_test_data): Likewise.
78 lines
1.9 KiB
C
78 lines
1.9 KiB
C
/* e_fmodl.c -- long double version of e_fmod.c.
|
|
* Conversion to IEEE quad long double by Jakub Jelinek, jj@ultra.linux.cz.
|
|
*/
|
|
/*
|
|
* ====================================================
|
|
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
|
*
|
|
* Developed at SunPro, a Sun Microsystems, Inc. business.
|
|
* Permission to use, copy, modify, and distribute this
|
|
* software is freely granted, provided that this notice
|
|
* is preserved.
|
|
* ====================================================
|
|
*/
|
|
|
|
/* __ieee754_remainderl(x,p)
|
|
* Return :
|
|
* returns x REM p = x - [x/p]*p as if in infinite
|
|
* precise arithmetic, where [x/p] is the (infinite bit)
|
|
* integer nearest x/p (in half way case choose the even one).
|
|
* Method :
|
|
* Based on fmodl() return x-[x/p]chopped*p exactlp.
|
|
*/
|
|
|
|
#include <math.h>
|
|
#include <math_private.h>
|
|
|
|
static const long double zero = 0.0L;
|
|
|
|
|
|
long double
|
|
__ieee754_remainderl(long double x, long double p)
|
|
{
|
|
int64_t hx,hp;
|
|
u_int64_t sx,lx,lp;
|
|
long double p_half;
|
|
double xhi, xlo, phi, plo;
|
|
|
|
ldbl_unpack (x, &xhi, &xlo);
|
|
EXTRACT_WORDS64 (hx, xhi);
|
|
EXTRACT_WORDS64 (lx, xlo);
|
|
ldbl_unpack (p, &phi, &plo);
|
|
EXTRACT_WORDS64 (hp, phi);
|
|
EXTRACT_WORDS64 (lp, plo);
|
|
sx = hx&0x8000000000000000ULL;
|
|
lp ^= hp & 0x8000000000000000ULL;
|
|
hp &= 0x7fffffffffffffffLL;
|
|
lx ^= sx;
|
|
hx &= 0x7fffffffffffffffLL;
|
|
|
|
/* purge off exception values */
|
|
if(hp==0) return (x*p)/(x*p); /* p = 0 */
|
|
if((hx>=0x7ff0000000000000LL)|| /* x not finite */
|
|
(hp>0x7ff0000000000000LL)) /* p is NaN */
|
|
return (x*p)/(x*p);
|
|
|
|
|
|
if (hp<=0x7fdfffffffffffffLL) x = __ieee754_fmodl(x,p+p); /* now x < 2p */
|
|
if (((hx-hp)|(lx-lp))==0) return zero*x;
|
|
x = fabsl(x);
|
|
p = fabsl(p);
|
|
if (hp<0x0020000000000000LL) {
|
|
if(x+x>p) {
|
|
x-=p;
|
|
if(x+x>=p) x -= p;
|
|
}
|
|
} else {
|
|
p_half = 0.5L*p;
|
|
if(x>p_half) {
|
|
x-=p;
|
|
if(x>=p_half) x -= p;
|
|
}
|
|
}
|
|
if (sx)
|
|
x = -x;
|
|
return x;
|
|
}
|
|
strong_alias (__ieee754_remainderl, __remainderl_finite)
|