diff options
author | Joseph Myers <joseph@codesourcery.com> | 2015-09-18 20:00:48 +0000 |
---|---|---|
committer | Joseph Myers <joseph@codesourcery.com> | 2015-09-18 20:00:48 +0000 |
commit | c8235dda728c4452f57c4c0d1bccc4e9a67da80c (patch) | |
tree | ae521c94b4648e089ee442cf8991963e7ffd97fe /sysdeps/ieee754 | |
parent | fe8c2b33aed067282ecac0cc3fdff1feef88548b (diff) | |
download | glibc-c8235dda728c4452f57c4c0d1bccc4e9a67da80c.tar glibc-c8235dda728c4452f57c4c0d1bccc4e9a67da80c.tar.gz glibc-c8235dda728c4452f57c4c0d1bccc4e9a67da80c.tar.bz2 glibc-c8235dda728c4452f57c4c0d1bccc4e9a67da80c.zip |
Avoid excess range overflowing results from cosh, sinh, lgamma (bug 18980).
Various i386 libm functions return values with excess range and
precision; Wilco Dijkstra's patches to make isfinite etc. expand
inline cause this pre-existing issue to result in test failures (when
e.g. a result that overflows float but not long double gets counted as
overflowing for some purposes but not others).
This patch addresses those cases arising from functions defined in C,
adding a math_narrow_eval macro that forces values to memory to
eliminate excess precision if FLT_EVAL_METHOD indicates this is
needed, and is a no-op otherwise. I'll convert existing uses of
volatile and asm for this purpose to use the new macro later, once
i386 has clean test results again (which requires fixes for .S files
as well).
Tested for x86_64 and x86. Committed.
[BZ #18980]
* sysdeps/generic/math_private.h: Include <float.h>.
(math_narrow_eval): New macro.
[FLT_EVAL_METHOD != 0] (excess_precision): Likewise.
* sysdeps/ieee754/dbl-64/e_cosh.c (__ieee754_cosh): Use
math_narrow_eval on overflowing return value.
* sysdeps/ieee754/dbl-64/e_lgamma_r.c (__ieee754_lgamma_r):
Likewise.
* sysdeps/ieee754/dbl-64/e_sinh.c (__ieee754_sinh): Likewise.
* sysdeps/ieee754/flt-32/e_coshf.c (__ieee754_coshf): Likewise.
* sysdeps/ieee754/flt-32/e_lgammaf_r.c (__ieee754_lgammaf_r):
Likewise.
* sysdeps/ieee754/flt-32/e_sinhf.c (__ieee754_sinhf): Likewise.
Diffstat (limited to 'sysdeps/ieee754')
-rw-r--r-- | sysdeps/ieee754/dbl-64/e_cosh.c | 2 | ||||
-rw-r--r-- | sysdeps/ieee754/dbl-64/e_lgamma_r.c | 2 | ||||
-rw-r--r-- | sysdeps/ieee754/dbl-64/e_sinh.c | 2 | ||||
-rw-r--r-- | sysdeps/ieee754/flt-32/e_coshf.c | 2 | ||||
-rw-r--r-- | sysdeps/ieee754/flt-32/e_lgammaf_r.c | 2 | ||||
-rw-r--r-- | sysdeps/ieee754/flt-32/e_sinhf.c | 2 |
6 files changed, 6 insertions, 6 deletions
diff --git a/sysdeps/ieee754/dbl-64/e_cosh.c b/sysdeps/ieee754/dbl-64/e_cosh.c index af3910dd6e..52a5d5007d 100644 --- a/sysdeps/ieee754/dbl-64/e_cosh.c +++ b/sysdeps/ieee754/dbl-64/e_cosh.c @@ -83,6 +83,6 @@ __ieee754_cosh (double x) return x * x; /* |x| > overflowthresold, cosh(x) overflow */ - return huge * huge; + return math_narrow_eval (huge * huge); } strong_alias (__ieee754_cosh, __cosh_finite) diff --git a/sysdeps/ieee754/dbl-64/e_lgamma_r.c b/sysdeps/ieee754/dbl-64/e_lgamma_r.c index ea8a9b42fb..da158cba33 100644 --- a/sysdeps/ieee754/dbl-64/e_lgamma_r.c +++ b/sysdeps/ieee754/dbl-64/e_lgamma_r.c @@ -296,7 +296,7 @@ __ieee754_lgamma_r(double x, int *signgamp) r = (x-half)*(t-one)+w; } else /* 2**58 <= x <= inf */ - r = x*(__ieee754_log(x)-one); + r = math_narrow_eval (x*(__ieee754_log(x)-one)); /* NADJ is set for negative arguments but not otherwise, resulting in warnings that it may be used uninitialized although in the cases where it is used it has always been diff --git a/sysdeps/ieee754/dbl-64/e_sinh.c b/sysdeps/ieee754/dbl-64/e_sinh.c index c99d28311d..291bfad0b3 100644 --- a/sysdeps/ieee754/dbl-64/e_sinh.c +++ b/sysdeps/ieee754/dbl-64/e_sinh.c @@ -89,6 +89,6 @@ __ieee754_sinh (double x) } /* |x| > overflowthresold, sinh(x) overflow */ - return x * shuge; + return math_narrow_eval (x * shuge); } strong_alias (__ieee754_sinh, __sinh_finite) diff --git a/sysdeps/ieee754/flt-32/e_coshf.c b/sysdeps/ieee754/flt-32/e_coshf.c index dedda47c09..7b223758e1 100644 --- a/sysdeps/ieee754/flt-32/e_coshf.c +++ b/sysdeps/ieee754/flt-32/e_coshf.c @@ -58,6 +58,6 @@ __ieee754_coshf (float x) if(ix>=0x7f800000) return x*x; /* |x| > overflowthresold, cosh(x) overflow */ - return huge*huge; + return math_narrow_eval (huge*huge); } strong_alias (__ieee754_coshf, __coshf_finite) diff --git a/sysdeps/ieee754/flt-32/e_lgammaf_r.c b/sysdeps/ieee754/flt-32/e_lgammaf_r.c index 424c4e7358..45a62c0dab 100644 --- a/sysdeps/ieee754/flt-32/e_lgammaf_r.c +++ b/sysdeps/ieee754/flt-32/e_lgammaf_r.c @@ -232,7 +232,7 @@ __ieee754_lgammaf_r(float x, int *signgamp) r = (x-half)*(t-one)+w; } else /* 2**26 <= x <= inf */ - r = x*(__ieee754_logf(x)-one); + r = math_narrow_eval (x*(__ieee754_logf(x)-one)); /* NADJ is set for negative arguments but not otherwise, resulting in warnings that it may be used uninitialized although in the cases where it is used it has always been diff --git a/sysdeps/ieee754/flt-32/e_sinhf.c b/sysdeps/ieee754/flt-32/e_sinhf.c index 17c2219c0b..a24fa0c4bc 100644 --- a/sysdeps/ieee754/flt-32/e_sinhf.c +++ b/sysdeps/ieee754/flt-32/e_sinhf.c @@ -59,6 +59,6 @@ __ieee754_sinhf(float x) } /* |x| > overflowthresold, sinh(x) overflow */ - return x*shuge; + return math_narrow_eval (x*shuge); } strong_alias (__ieee754_sinhf, __sinhf_finite) |