about summary refs log tree commit diff
path: root/sysdeps/ieee754/ldbl-128/s_erfl.c
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2014-06-24 20:56:56 +0000
committerJoseph Myers <joseph@codesourcery.com>2014-06-24 20:56:56 +0000
commite7dd3c8c1db8c6d293abb995e033893b7328ad19 (patch)
treedcfbd9476c52dbccdedf8d691b37b7442199a756 /sysdeps/ieee754/ldbl-128/s_erfl.c
parent0ea5d373c7984a1da2d0e990c6e78e6d6c24f91b (diff)
downloadglibc-e7dd3c8c1db8c6d293abb995e033893b7328ad19.tar.gz
glibc-e7dd3c8c1db8c6d293abb995e033893b7328ad19.tar.xz
glibc-e7dd3c8c1db8c6d293abb995e033893b7328ad19.zip
Fix ldbl-128 erfl spurious underflows (bug 16287).
This patch fixes bug 16287, spurious underflows from ldbl-128 erfl
arising from it calling erfcl for arguments with absolute value at
least 1.0, although for large positive arguments erfcl correctly
underflows but erfl shouldn't.  The fix is simply to avoid calling
erfcl, and just return 1, for arguments above a cut-off large enough
that erfl correctly rounds to-nearest as 1 but not so large that erfcl
underflows.

Tested mips64.  Also tested x86_64 and x86 to confirm the new tests
(taken from the tests of erfc) don't cause any problems there; no ulps
updates needed.

	[BZ #16287]
	* sysdeps/ieee754/ldbl-128/s_erfl.c (__erfl): Return 1 without
	calling __erfcl for arguments at least 16.
	* math/auto-libm-test-in: Add more tests of erf.
	* math/auto-libm-test-out: Regenerated.
Diffstat (limited to 'sysdeps/ieee754/ldbl-128/s_erfl.c')
-rw-r--r--sysdeps/ieee754/ldbl-128/s_erfl.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/sysdeps/ieee754/ldbl-128/s_erfl.c b/sysdeps/ieee754/ldbl-128/s_erfl.c
index 35ca8c1360..9bfc9c580b 100644
--- a/sysdeps/ieee754/ldbl-128/s_erfl.c
+++ b/sysdeps/ieee754/ldbl-128/s_erfl.c
@@ -769,6 +769,8 @@ __erfl (long double x)
 
   if (ix >= 0x3fff0000) /* |x| >= 1.0 */
     {
+      if (ix >= 0x40030000 && sign > 0)
+	return one; /* x >= 16, avoid spurious underflow from erfc.  */
       y = __erfcl (x);
       return (one - y);
       /*    return (one - __erfcl (x)); */