diff mbox

Fix ldbl-128 erfl spurious underflows (bug 16287)

Message ID Pine.LNX.4.64.1406242024001.21652@digraph.polyomino.org.uk
State Committed
Headers show

Commit Message

Joseph Myers June 24, 2014, 8:24 p.m. UTC
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.

(auto-libm-test-out diffs omitted below.)

2014-06-24  Joseph Myers  <joseph@codesourcery.com>

	[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.

Comments

Andreas Jaeger June 24, 2014, 8:44 p.m. UTC | #1
On 06/24/2014 10:24 PM, Joseph S. Myers wrote:
> 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.
> 
> (auto-libm-test-out diffs omitted below.)
> 
> 2014-06-24  Joseph Myers  <joseph@codesourcery.com>
> 
> 	[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.
> 
> diff --git a/math/auto-libm-test-in b/math/auto-libm-test-in
> index 4eaa013..79d276c 100644
> --- a/math/auto-libm-test-in
> +++ b/math/auto-libm-test-in
> @@ -803,6 +803,16 @@ erf 0x1.c5bf94p-127
>  erf 0x3.8b7fa8p-128
>  erf -0x3.8b7f12369ded8p-1024
>  erf 0x3.8b7f12369ded5518p-16384
> +erf 26.0
> +erf 28.0
> +erf 100
> +erf 106
> +erf 106.5
> +erf 106.625
> +erf 107
> +erf 108
> +erf 1000
> +erf max
>  
>  erfc 0.0
>  erfc -0
> diff --git a/sysdeps/ieee754/ldbl-128/s_erfl.c b/sysdeps/ieee754/ldbl-128/s_erfl.c
> index 35ca8c1..f44d481 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;

Could you add a comment on this, please?

Fine with this change,
Andreas

>        y = __erfcl (x);
>        return (one - y);
>        /*    return (one - __erfcl (x)); */
>
diff mbox

Patch

diff --git a/math/auto-libm-test-in b/math/auto-libm-test-in
index 4eaa013..79d276c 100644
--- a/math/auto-libm-test-in
+++ b/math/auto-libm-test-in
@@ -803,6 +803,16 @@  erf 0x1.c5bf94p-127
 erf 0x3.8b7fa8p-128
 erf -0x3.8b7f12369ded8p-1024
 erf 0x3.8b7f12369ded5518p-16384
+erf 26.0
+erf 28.0
+erf 100
+erf 106
+erf 106.5
+erf 106.625
+erf 107
+erf 108
+erf 1000
+erf max
 
 erfc 0.0
 erfc -0
diff --git a/sysdeps/ieee754/ldbl-128/s_erfl.c b/sysdeps/ieee754/ldbl-128/s_erfl.c
index 35ca8c1..f44d481 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;
       y = __erfcl (x);
       return (one - y);
       /*    return (one - __erfcl (x)); */