This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Fix acosf underflow (bug 14153)


Bug 14153 is a spurious underflow exception from acosf (2e-17); the
cause is the acosf implementation calculating a value on the order of
the cube of its argument, which underflows.  There is a test for very
small arguments, maybe to avoid underflow, and if such an argument is
encountered it returns pi/2 (computed by adding high and low parts, I
suppose to get correct results for the current rounding mode and to
raise the inexact exception).  However, this tests for values no more
than 2**-57, as if the test was unchanged from a "double" version of
the function; it suffices to test for values no more than 2**-26,
which avoids the problem with internal underflows.  (For small x, the
correct value is essentially pi/2 - x.  Compute pi/2 rounded to 25
bits - one more bit than float - which is the nearest value that is
representable as float or half way between two representable values.
Compute the difference of pi/2 and that rounded values; if |x| is
smaller than that difference then the result of rounding pi/2 - x will
be the same in any rounding mode as the result of rounding pi/2.  Now
that difference is more than 2**-26.)

I propose this patch fixing the bug that way.  Tested x86_64 and x86.

2012-05-24  Joseph Myers  <joseph@codesourcery.com>

	[BZ #14153]
	* sysdeps/ieee754/flt-32/e_acosf.c (__ieee754_acosf): Return pi/2
	for |x| <= 2**-26, not 2**-57.
	* math/libm-test.inc (acos_test): Do not allow spurious underflow
	exception.

diff --git a/math/libm-test.inc b/math/libm-test.inc
index 5946ca8..ed13f53 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -804,8 +804,7 @@ acos_test (void)
   TEST_f_f (acos, 0.5, M_PI_6l*2.0);
   TEST_f_f (acos, -0.5, M_PI_6l*4.0);
   TEST_f_f (acos, 0.75L, 0.722734247813415611178377352641333362L);
-  /* Bug 14153: spurious exception may occur.  */
-  TEST_f_f (acos, 2e-17L, 1.57079632679489659923132169163975144L, UNDERFLOW_EXCEPTION_OK_FLOAT);
+  TEST_f_f (acos, 2e-17L, 1.57079632679489659923132169163975144L);
   TEST_f_f (acos, 0.0625L, 1.50825556499840522843072005474337068L);
   TEST_f_f (acos, 0x0.ffffffp0L, 3.4526698471620358760324948263873649728491e-4L);
   TEST_f_f (acos, -0x0.ffffffp0L, 3.1412473866050770348750401337968641476999L);
diff --git a/sysdeps/ieee754/flt-32/e_acosf.c b/sysdeps/ieee754/flt-32/e_acosf.c
index c0f1d4e..6f792f6 100644
--- a/sysdeps/ieee754/flt-32/e_acosf.c
+++ b/sysdeps/ieee754/flt-32/e_acosf.c
@@ -46,7 +46,7 @@ __ieee754_acosf(float x)
 	    return (x-x)/(x-x);		/* acos(|x|>1) is NaN */
 	}
 	if(ix<0x3f000000) {	/* |x| < 0.5 */
-	    if(ix<=0x23000000) return pio2_hi+pio2_lo;/*if|x|<2**-57*/
+	    if(ix<=0x32800000) return pio2_hi+pio2_lo;/*if|x|<=2**-26*/
 	    z = x*x;
 	    p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
 	    q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));

-- 
Joseph S. Myers
joseph@codesourcery.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]