Fix some regressions caused by the switch from gcc to clang. The fixes
are workarounds for various symptoms of the problem described in clang bugs 3929, 8100, 8241, 10409, and 12958. The regression tests did their job: they failed, someone brought it up on the mailing lists, and then the issue got ignored for 6 months. Oops. There may still be some regressions for functions we don't have test coverage for yet.
This commit is contained in:
parent
6e7bc5b60d
commit
7dbbb6dde3
@ -121,12 +121,6 @@ COMMON_SRCS:= ${COMMON_SRCS:N${i:R}.c}
|
||||
.endfor
|
||||
.endif
|
||||
|
||||
# Some files need certain gcc built-in functions to be disabled, since gcc's
|
||||
# model of the functions bogusly assumes -fno-trapping-math.
|
||||
XRINT_CFLAGS= -fno-builtin-rint -fno-builtin-rintf -fno-builtin-rintl
|
||||
CFLAGS+= ${XRINT_CFLAGS}
|
||||
XRINT_CFLAGS:= ${.IMPSRC:M*/s_nearbyint.c:C/^.+$/${XRINT_CFLAGS}/:C/^$//}
|
||||
|
||||
SRCS= ${COMMON_SRCS} ${ARCH_SRCS}
|
||||
|
||||
INCS+= fenv.h math.h
|
||||
|
@ -39,14 +39,11 @@ __FBSDID("$FreeBSD$");
|
||||
#define BIAS (LDBL_MAX_EXP - 1)
|
||||
#define EXPMASK (BIAS + LDBL_MAX_EXP)
|
||||
|
||||
#if 0 /* XXX Prevent gcc from erroneously constant folding this. */
|
||||
static const long double twom10000 = 0x1p-10000L;
|
||||
#else
|
||||
static volatile long double twom10000 = 0x1p-10000L;
|
||||
#endif
|
||||
static volatile long double
|
||||
huge = 0x1p10000L,
|
||||
twom10000 = 0x1p-10000L;
|
||||
|
||||
static const long double
|
||||
huge = 0x1p10000L,
|
||||
P1 = 0x1.62e42fefa39ef35793c7673007e6p-1L,
|
||||
P2 = 0x1.ebfbdff82c58ea86f16b06ec9736p-3L,
|
||||
P3 = 0x1.c6b08d704a0bf8b33a762bad3459p-5L,
|
||||
|
@ -43,12 +43,9 @@ __FBSDID("$FreeBSD$");
|
||||
#define BIAS (LDBL_MAX_EXP - 1)
|
||||
#define EXPMASK (BIAS + LDBL_MAX_EXP)
|
||||
|
||||
static const long double huge = 0x1p10000L;
|
||||
#if 0 /* XXX Prevent gcc from erroneously constant folding this. */
|
||||
static const long double twom10000 = 0x1p-10000L;
|
||||
#else
|
||||
static volatile long double twom10000 = 0x1p-10000L;
|
||||
#endif
|
||||
static volatile long double
|
||||
huge = 0x1p10000L,
|
||||
twom10000 = 0x1p-10000L;
|
||||
|
||||
static const double
|
||||
redux = 0x1.8p63 / TBLSIZE,
|
||||
|
@ -84,7 +84,6 @@ __FBSDID("$FreeBSD$");
|
||||
static const double
|
||||
one = 1.0,
|
||||
halF[2] = {0.5,-0.5,},
|
||||
huge = 1.0e+300,
|
||||
o_threshold= 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */
|
||||
u_threshold= -7.45133219101941108420e+02, /* 0xc0874910, 0xD52D3051 */
|
||||
ln2HI[2] ={ 6.93147180369123816490e-01, /* 0x3fe62e42, 0xfee00000 */
|
||||
@ -99,6 +98,7 @@ P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
|
||||
P5 = 4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */
|
||||
|
||||
static volatile double
|
||||
huge = 1.0e+300,
|
||||
twom1000= 9.33263618503218878990e-302; /* 2**-1000=0x01700000,0*/
|
||||
|
||||
double
|
||||
|
@ -24,7 +24,6 @@ __FBSDID("$FreeBSD$");
|
||||
static const float
|
||||
one = 1.0,
|
||||
halF[2] = {0.5,-0.5,},
|
||||
huge = 1.0e+30,
|
||||
o_threshold= 8.8721679688e+01, /* 0x42b17180 */
|
||||
u_threshold= -1.0397208405e+02, /* 0xc2cff1b5 */
|
||||
ln2HI[2] ={ 6.9314575195e-01, /* 0x3f317200 */
|
||||
@ -39,7 +38,9 @@ invln2 = 1.4426950216e+00, /* 0x3fb8aa3b */
|
||||
P1 = 1.6666625440e-1, /* 0xaaaa8f.0p-26 */
|
||||
P2 = -2.7667332906e-3; /* -0xb55215.0p-32 */
|
||||
|
||||
static volatile float twom100 = 7.8886090522e-31; /* 2**-100=0x0d800000 */
|
||||
static volatile float
|
||||
huge = 1.0e+30,
|
||||
twom100 = 7.8886090522e-31; /* 2**-100=0x0d800000 */
|
||||
|
||||
float
|
||||
__ieee754_expf(float x)
|
||||
|
@ -81,6 +81,7 @@ Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */
|
||||
Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */
|
||||
|
||||
static const double zero = 0.0;
|
||||
static volatile double vzero = 0.0;
|
||||
|
||||
double
|
||||
__ieee754_log(double x)
|
||||
@ -94,7 +95,7 @@ __ieee754_log(double x)
|
||||
k=0;
|
||||
if (hx < 0x00100000) { /* x < 2**-1022 */
|
||||
if (((hx&0x7fffffff)|lx)==0)
|
||||
return -two54/zero; /* log(+-0)=-inf */
|
||||
return -two54/vzero; /* log(+-0)=-inf */
|
||||
if (hx<0) return (x-x)/zero; /* log(-#) = NaN */
|
||||
k -= 54; x *= two54; /* subnormal number, scale up x */
|
||||
GET_HIGH_WORD(hx,x);
|
||||
|
@ -34,6 +34,7 @@ log10_2hi = 3.01029995663611771306e-01, /* 0x3FD34413, 0x509F6000 */
|
||||
log10_2lo = 3.69423907715893078616e-13; /* 0x3D59FEF3, 0x11F12B36 */
|
||||
|
||||
static const double zero = 0.0;
|
||||
static volatile double vzero = 0.0;
|
||||
|
||||
double
|
||||
__ieee754_log10(double x)
|
||||
@ -47,7 +48,7 @@ __ieee754_log10(double x)
|
||||
k=0;
|
||||
if (hx < 0x00100000) { /* x < 2**-1022 */
|
||||
if (((hx&0x7fffffff)|lx)==0)
|
||||
return -two54/zero; /* log(+-0)=-inf */
|
||||
return -two54/vzero; /* log(+-0)=-inf */
|
||||
if (hx<0) return (x-x)/zero; /* log(-#) = NaN */
|
||||
k -= 54; x *= two54; /* subnormal number, scale up x */
|
||||
GET_HIGH_WORD(hx,x);
|
||||
|
@ -28,6 +28,7 @@ log10_2hi = 3.0102920532e-01, /* 0x3e9a2080 */
|
||||
log10_2lo = 7.9034151668e-07; /* 0x355427db */
|
||||
|
||||
static const float zero = 0.0;
|
||||
static volatile float vzero = 0.0;
|
||||
|
||||
float
|
||||
__ieee754_log10f(float x)
|
||||
@ -40,7 +41,7 @@ __ieee754_log10f(float x)
|
||||
k=0;
|
||||
if (hx < 0x00800000) { /* x < 2**-126 */
|
||||
if ((hx&0x7fffffff)==0)
|
||||
return -two25/zero; /* log(+-0)=-inf */
|
||||
return -two25/vzero; /* log(+-0)=-inf */
|
||||
if (hx<0) return (x-x)/zero; /* log(-#) = NaN */
|
||||
k -= 25; x *= two25; /* subnormal number, scale up x */
|
||||
GET_FLOAT_WORD(hx,x);
|
||||
|
@ -34,6 +34,7 @@ ivln2hi = 1.44269504072144627571e+00, /* 0x3ff71547, 0x65200000 */
|
||||
ivln2lo = 1.67517131648865118353e-10; /* 0x3de705fc, 0x2eefa200 */
|
||||
|
||||
static const double zero = 0.0;
|
||||
static volatile double vzero = 0.0;
|
||||
|
||||
double
|
||||
__ieee754_log2(double x)
|
||||
@ -47,7 +48,7 @@ __ieee754_log2(double x)
|
||||
k=0;
|
||||
if (hx < 0x00100000) { /* x < 2**-1022 */
|
||||
if (((hx&0x7fffffff)|lx)==0)
|
||||
return -two54/zero; /* log(+-0)=-inf */
|
||||
return -two54/vzero; /* log(+-0)=-inf */
|
||||
if (hx<0) return (x-x)/zero; /* log(-#) = NaN */
|
||||
k -= 54; x *= two54; /* subnormal number, scale up x */
|
||||
GET_HIGH_WORD(hx,x);
|
||||
|
@ -26,6 +26,7 @@ ivln2hi = 1.4428710938e+00, /* 0x3fb8b000 */
|
||||
ivln2lo = -1.7605285393e-04; /* 0xb9389ad4 */
|
||||
|
||||
static const float zero = 0.0;
|
||||
static volatile float vzero = 0.0;
|
||||
|
||||
float
|
||||
__ieee754_log2f(float x)
|
||||
@ -38,7 +39,7 @@ __ieee754_log2f(float x)
|
||||
k=0;
|
||||
if (hx < 0x00800000) { /* x < 2**-126 */
|
||||
if ((hx&0x7fffffff)==0)
|
||||
return -two25/zero; /* log(+-0)=-inf */
|
||||
return -two25/vzero; /* log(+-0)=-inf */
|
||||
if (hx<0) return (x-x)/zero; /* log(-#) = NaN */
|
||||
k -= 25; x *= two25; /* subnormal number, scale up x */
|
||||
GET_FLOAT_WORD(hx,x);
|
||||
|
@ -30,6 +30,7 @@ Lg3 = 0x91e9ee.0p-25, /* 0.28498786688 */
|
||||
Lg4 = 0xf89e26.0p-26; /* 0.24279078841 */
|
||||
|
||||
static const float zero = 0.0;
|
||||
static volatile float vzero = 0.0;
|
||||
|
||||
float
|
||||
__ieee754_logf(float x)
|
||||
@ -42,7 +43,7 @@ __ieee754_logf(float x)
|
||||
k=0;
|
||||
if (ix < 0x00800000) { /* x < 2**-126 */
|
||||
if ((ix&0x7fffffff)==0)
|
||||
return -two25/zero; /* log(+-0)=-inf */
|
||||
return -two25/vzero; /* log(+-0)=-inf */
|
||||
if (ix<0) return (x-x)/zero; /* log(-#) = NaN */
|
||||
k -= 25; x *= two25; /* subnormal number, scale up x */
|
||||
GET_FLOAT_WORD(ix,x);
|
||||
|
@ -36,7 +36,6 @@ __FBSDID("$FreeBSD$");
|
||||
#define TBLSIZE (1 << TBLBITS)
|
||||
|
||||
static const double
|
||||
huge = 0x1p1000,
|
||||
redux = 0x1.8p52 / TBLSIZE,
|
||||
P1 = 0x1.62e42fefa39efp-1,
|
||||
P2 = 0x1.ebfbdff82c575p-3,
|
||||
@ -44,7 +43,9 @@ static const double
|
||||
P4 = 0x1.3b2ab88f70400p-7,
|
||||
P5 = 0x1.5d88003875c74p-10;
|
||||
|
||||
static volatile double twom1000 = 0x1p-1000;
|
||||
static volatile double
|
||||
huge = 0x1p1000,
|
||||
twom1000 = 0x1p-1000;
|
||||
|
||||
static const double tbl[TBLSIZE * 2] = {
|
||||
/* exp2(z + eps) eps */
|
||||
|
@ -36,14 +36,15 @@ __FBSDID("$FreeBSD$");
|
||||
#define TBLSIZE (1 << TBLBITS)
|
||||
|
||||
static const float
|
||||
huge = 0x1p100f,
|
||||
redux = 0x1.8p23f / TBLSIZE,
|
||||
P1 = 0x1.62e430p-1f,
|
||||
P2 = 0x1.ebfbe0p-3f,
|
||||
P3 = 0x1.c6b348p-5f,
|
||||
P4 = 0x1.3b2c9cp-7f;
|
||||
|
||||
static volatile float twom100 = 0x1p-100f;
|
||||
static volatile float
|
||||
huge = 0x1p100f,
|
||||
twom100 = 0x1p-100f;
|
||||
|
||||
static const double exp2ft[TBLSIZE] = {
|
||||
0x1.6a09e667f3bcdp-1,
|
||||
|
@ -115,7 +115,6 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
static const double
|
||||
one = 1.0,
|
||||
huge = 1.0e+300,
|
||||
tiny = 1.0e-300,
|
||||
o_threshold = 7.09782712893383973096e+02,/* 0x40862E42, 0xFEFA39EF */
|
||||
ln2_hi = 6.93147180369123816490e-01,/* 0x3fe62e42, 0xfee00000 */
|
||||
@ -128,6 +127,8 @@ Q3 = -7.93650757867487942473e-05, /* BF14CE19 9EAADBB7 */
|
||||
Q4 = 4.00821782732936239552e-06, /* 3ED0CFCA 86E65239 */
|
||||
Q5 = -2.01099218183624371326e-07; /* BE8AFDB7 6E09C32D */
|
||||
|
||||
static volatile double huge = 1.0e+300;
|
||||
|
||||
double
|
||||
expm1(double x)
|
||||
{
|
||||
|
@ -23,7 +23,6 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
static const float
|
||||
one = 1.0,
|
||||
huge = 1.0e+30,
|
||||
tiny = 1.0e-30,
|
||||
o_threshold = 8.8721679688e+01,/* 0x42b17180 */
|
||||
ln2_hi = 6.9313812256e-01,/* 0x3f317180 */
|
||||
@ -37,6 +36,8 @@ invln2 = 1.4426950216e+00,/* 0x3fb8aa3b */
|
||||
Q1 = -3.3333212137e-2, /* -0x888868.0p-28 */
|
||||
Q2 = 1.5807170421e-3; /* 0xcf3010.0p-33 */
|
||||
|
||||
static volatile float huge = 1.0e+30;
|
||||
|
||||
float
|
||||
expm1f(float x)
|
||||
{
|
||||
|
@ -238,6 +238,8 @@ fma(double x, double y, double z)
|
||||
zs = copysign(DBL_MIN, zs);
|
||||
|
||||
fesetround(FE_TONEAREST);
|
||||
/* work around clang bug 8100 */
|
||||
volatile double vxs = xs;
|
||||
|
||||
/*
|
||||
* Basic approach for round-to-nearest:
|
||||
@ -247,7 +249,7 @@ fma(double x, double y, double z)
|
||||
* adj = xy.lo + r.lo (inexact; low bit is sticky)
|
||||
* result = r.hi + adj (correctly rounded)
|
||||
*/
|
||||
xy = dd_mul(xs, ys);
|
||||
xy = dd_mul(vxs, ys);
|
||||
r = dd_add(xy.hi, zs);
|
||||
|
||||
spread = ex + ey;
|
||||
@ -268,7 +270,9 @@ fma(double x, double y, double z)
|
||||
* rounding modes.
|
||||
*/
|
||||
fesetround(oround);
|
||||
adj = r.lo + xy.lo;
|
||||
/* work around clang bug 8100 */
|
||||
volatile double vrlo = r.lo;
|
||||
adj = vrlo + xy.lo;
|
||||
return (ldexp(r.hi + adj, spread));
|
||||
}
|
||||
|
||||
|
@ -226,6 +226,8 @@ fmal(long double x, long double y, long double z)
|
||||
zs = copysignl(LDBL_MIN, zs);
|
||||
|
||||
fesetround(FE_TONEAREST);
|
||||
/* work around clang bug 8100 */
|
||||
volatile long double vxs = xs;
|
||||
|
||||
/*
|
||||
* Basic approach for round-to-nearest:
|
||||
@ -235,7 +237,7 @@ fmal(long double x, long double y, long double z)
|
||||
* adj = xy.lo + r.lo (inexact; low bit is sticky)
|
||||
* result = r.hi + adj (correctly rounded)
|
||||
*/
|
||||
xy = dd_mul(xs, ys);
|
||||
xy = dd_mul(vxs, ys);
|
||||
r = dd_add(xy.hi, zs);
|
||||
|
||||
spread = ex + ey;
|
||||
@ -256,7 +258,9 @@ fmal(long double x, long double y, long double z)
|
||||
* rounding modes.
|
||||
*/
|
||||
fesetround(oround);
|
||||
adj = r.lo + xy.lo;
|
||||
/* work around clang bug 8100 */
|
||||
volatile long double vrlo = r.lo;
|
||||
adj = vrlo + xy.lo;
|
||||
return (ldexpl(r.hi + adj, spread));
|
||||
}
|
||||
|
||||
|
@ -96,6 +96,7 @@ Lp6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */
|
||||
Lp7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */
|
||||
|
||||
static const double zero = 0.0;
|
||||
static volatile double vzero = 0.0;
|
||||
|
||||
double
|
||||
log1p(double x)
|
||||
@ -109,7 +110,7 @@ log1p(double x)
|
||||
k = 1;
|
||||
if (hx < 0x3FDA827A) { /* 1+x < sqrt(2)+ */
|
||||
if(ax>=0x3ff00000) { /* x <= -1.0 */
|
||||
if(x==-1.0) return -two54/zero; /* log1p(-1)=+inf */
|
||||
if(x==-1.0) return -two54/vzero; /* log1p(-1)=+inf */
|
||||
else return (x-x)/(x-x); /* log1p(x<-1)=NaN */
|
||||
}
|
||||
if(ax<0x3e200000) { /* |x| < 2**-29 */
|
||||
|
@ -34,6 +34,7 @@ Lp6 = 1.5313838422e-01, /* 3E1CD04F */
|
||||
Lp7 = 1.4798198640e-01; /* 3E178897 */
|
||||
|
||||
static const float zero = 0.0;
|
||||
static volatile float vzero = 0.0;
|
||||
|
||||
float
|
||||
log1pf(float x)
|
||||
@ -47,7 +48,7 @@ log1pf(float x)
|
||||
k = 1;
|
||||
if (hx < 0x3ed413d0) { /* 1+x < sqrt(2)+ */
|
||||
if(ax>=0x3f800000) { /* x <= -1.0 */
|
||||
if(x==(float)-1.0) return -two25/zero; /* log1p(-1)=+inf */
|
||||
if(x==(float)-1.0) return -two25/vzero; /* log1p(-1)=+inf */
|
||||
else return (x-x)/(x-x); /* log1p(x<-1)=NaN */
|
||||
}
|
||||
if(ax<0x38000000) { /* |x| < 2**-15 */
|
||||
|
@ -36,12 +36,16 @@ __FBSDID("$FreeBSD$");
|
||||
* instead of feclearexcept()/feupdateenv() to restore the environment
|
||||
* because the only exception defined for rint() is overflow, and
|
||||
* rounding can't overflow as long as emax >= p.
|
||||
*
|
||||
* The volatile keyword is needed below because clang incorrectly assumes
|
||||
* that rint won't raise any floating-point exceptions. Declaring ret volatile
|
||||
* is sufficient to trick the compiler into doing the right thing.
|
||||
*/
|
||||
#define DECL(type, fn, rint) \
|
||||
type \
|
||||
fn(type x) \
|
||||
{ \
|
||||
type ret; \
|
||||
volatile type ret; \
|
||||
fenv_t env; \
|
||||
\
|
||||
fegetenv(&env); \
|
||||
|
@ -76,6 +76,12 @@ __FBSDID("$FreeBSD$");
|
||||
test((func), (x), (y), (z), (rz), (exceptmask), (excepts)); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* This is needed because clang constant-folds fma in ways that are incorrect
|
||||
* in rounding modes other than FE_TONEAREST.
|
||||
*/
|
||||
volatile double one = 1.0;
|
||||
|
||||
/*
|
||||
* Determine whether x and y are equal, with two special rules:
|
||||
* +0.0 != -0.0
|
||||
@ -108,9 +114,9 @@ test_zeroes(void)
|
||||
testall(-0.0, 0.0, -0.0, -0.0, ALL_STD_EXCEPT, 0);
|
||||
testall(0.0, -0.0, -0.0, -0.0, ALL_STD_EXCEPT, 0);
|
||||
|
||||
testall(-1.0, 1.0, 1.0, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0);
|
||||
testall(1.0, -1.0, 1.0, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0);
|
||||
testall(-1.0, -1.0, -1.0, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0);
|
||||
testall(-one, one, one, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0);
|
||||
testall(one, -one, one, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0);
|
||||
testall(-one, -one, -one, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0);
|
||||
|
||||
switch (fegetround()) {
|
||||
case FE_TONEAREST:
|
||||
@ -190,53 +196,53 @@ test_small_z(void)
|
||||
|
||||
/* x*y positive, z positive */
|
||||
if (fegetround() == FE_UPWARD) {
|
||||
test(fmaf, 1.0, 1.0, 0x1.0p-100, 1.0 + FLT_EPSILON,
|
||||
test(fmaf, one, one, 0x1.0p-100, 1.0 + FLT_EPSILON,
|
||||
ALL_STD_EXCEPT, FE_INEXACT);
|
||||
test(fma, 1.0, 1.0, 0x1.0p-200, 1.0 + DBL_EPSILON,
|
||||
test(fma, one, one, 0x1.0p-200, 1.0 + DBL_EPSILON,
|
||||
ALL_STD_EXCEPT, FE_INEXACT);
|
||||
test(fmal, 1.0, 1.0, 0x1.0p-200, 1.0 + LDBL_EPSILON,
|
||||
test(fmal, one, one, 0x1.0p-200, 1.0 + LDBL_EPSILON,
|
||||
ALL_STD_EXCEPT, FE_INEXACT);
|
||||
} else {
|
||||
testall(0x1.0p100, 1.0, 0x1.0p-100, 0x1.0p100,
|
||||
testall(0x1.0p100, one, 0x1.0p-100, 0x1.0p100,
|
||||
ALL_STD_EXCEPT, FE_INEXACT);
|
||||
}
|
||||
|
||||
/* x*y negative, z negative */
|
||||
if (fegetround() == FE_DOWNWARD) {
|
||||
test(fmaf, -1.0, 1.0, -0x1.0p-100, -(1.0 + FLT_EPSILON),
|
||||
test(fmaf, -one, one, -0x1.0p-100, -(1.0 + FLT_EPSILON),
|
||||
ALL_STD_EXCEPT, FE_INEXACT);
|
||||
test(fma, -1.0, 1.0, -0x1.0p-200, -(1.0 + DBL_EPSILON),
|
||||
test(fma, -one, one, -0x1.0p-200, -(1.0 + DBL_EPSILON),
|
||||
ALL_STD_EXCEPT, FE_INEXACT);
|
||||
test(fmal, -1.0, 1.0, -0x1.0p-200, -(1.0 + LDBL_EPSILON),
|
||||
test(fmal, -one, one, -0x1.0p-200, -(1.0 + LDBL_EPSILON),
|
||||
ALL_STD_EXCEPT, FE_INEXACT);
|
||||
} else {
|
||||
testall(0x1.0p100, -1.0, -0x1.0p-100, -0x1.0p100,
|
||||
testall(0x1.0p100, -one, -0x1.0p-100, -0x1.0p100,
|
||||
ALL_STD_EXCEPT, FE_INEXACT);
|
||||
}
|
||||
|
||||
/* x*y positive, z negative */
|
||||
if (fegetround() == FE_DOWNWARD || fegetround() == FE_TOWARDZERO) {
|
||||
test(fmaf, 1.0, 1.0, -0x1.0p-100, 1.0 - FLT_EPSILON / 2,
|
||||
test(fmaf, one, one, -0x1.0p-100, 1.0 - FLT_EPSILON / 2,
|
||||
ALL_STD_EXCEPT, FE_INEXACT);
|
||||
test(fma, 1.0, 1.0, -0x1.0p-200, 1.0 - DBL_EPSILON / 2,
|
||||
test(fma, one, one, -0x1.0p-200, 1.0 - DBL_EPSILON / 2,
|
||||
ALL_STD_EXCEPT, FE_INEXACT);
|
||||
test(fmal, 1.0, 1.0, -0x1.0p-200, 1.0 - LDBL_EPSILON / 2,
|
||||
test(fmal, one, one, -0x1.0p-200, 1.0 - LDBL_EPSILON / 2,
|
||||
ALL_STD_EXCEPT, FE_INEXACT);
|
||||
} else {
|
||||
testall(0x1.0p100, 1.0, -0x1.0p-100, 0x1.0p100,
|
||||
testall(0x1.0p100, one, -0x1.0p-100, 0x1.0p100,
|
||||
ALL_STD_EXCEPT, FE_INEXACT);
|
||||
}
|
||||
|
||||
/* x*y negative, z positive */
|
||||
if (fegetround() == FE_UPWARD || fegetround() == FE_TOWARDZERO) {
|
||||
test(fmaf, -1.0, 1.0, 0x1.0p-100, -1.0 + FLT_EPSILON / 2,
|
||||
test(fmaf, -one, one, 0x1.0p-100, -1.0 + FLT_EPSILON / 2,
|
||||
ALL_STD_EXCEPT, FE_INEXACT);
|
||||
test(fma, -1.0, 1.0, 0x1.0p-200, -1.0 + DBL_EPSILON / 2,
|
||||
test(fma, -one, one, 0x1.0p-200, -1.0 + DBL_EPSILON / 2,
|
||||
ALL_STD_EXCEPT, FE_INEXACT);
|
||||
test(fmal, -1.0, 1.0, 0x1.0p-200, -1.0 + LDBL_EPSILON / 2,
|
||||
test(fmal, -one, one, 0x1.0p-200, -1.0 + LDBL_EPSILON / 2,
|
||||
ALL_STD_EXCEPT, FE_INEXACT);
|
||||
} else {
|
||||
testall(-0x1.0p100, 1.0, 0x1.0p-100, -0x1.0p100,
|
||||
testall(-0x1.0p100, one, 0x1.0p-100, -0x1.0p100,
|
||||
ALL_STD_EXCEPT, FE_INEXACT);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user