From: Joseph Myers Date: Wed, 2 Apr 2014 13:10:19 +0000 (+0000) Subject: Fix clog / clog10 sign of zero result in round-downward mode (bug 16789). X-Git-Tag: glibc-2.20~656 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6f05bafebac30a389807979f8efbb709f84b486f;p=thirdparty%2Fglibc.git Fix clog / clog10 sign of zero result in round-downward mode (bug 16789). This patch fixes bug 16789, incorrect sign of (real part) zero result from clog and clog10 in round-downward mode, arising from that real part being computed as 0 - 0. To ensure that an underflow exception occurred, the code used an underflowing value (the next term in the series for log1p) in arithmetic computing the real part of the result, yielding the problematic 0 - 0 computation in some cases even when the mathematical result would be small but positive. The patch changes this code to use the math_force_eval approach to ensuring that an underflowing computation actually occurs. Tests of clog and clog10 are enabled in all rounding modes. Tested x86_64 and x86 and ulps updated accordingly. [BZ #16789] * math/s_clog.c (__clog): Use math_force_eval to ensure underflow instead of using underflowing value in computing result. * math/s_clog10.c (__clog10): Likewise. * math/s_clog10f.c (__clog10f): Likewise. * math/s_clog10l.c (__clog10l): Likewise. * math/s_clogf.c (__clogf): Likewise. * math/s_clogl.c (__clogl): Likewise. * math/libm-test.inc (clog_test): Use ALL_RM_TEST. (clog10_test): Likewise. * sysdeps/i386/fpu/libm-test-ulps: Update. * sysdeps/x86_64/fpu/libm-test-ulps: Likewise. --- diff --git a/ChangeLog b/ChangeLog index f623e8b79a3..4a514563b29 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2014-04-02 Joseph Myers + + [BZ #16789] + * math/s_clog.c (__clog): Use math_force_eval to ensure underflow + instead of using underflowing value in computing result. + * math/s_clog10.c (__clog10): Likewise. + * math/s_clog10f.c (__clog10f): Likewise. + * math/s_clog10l.c (__clog10l): Likewise. + * math/s_clogf.c (__clogf): Likewise. + * math/s_clogl.c (__clogl): Likewise. + * math/libm-test.inc (clog_test): Use ALL_RM_TEST. + (clog10_test): Likewise. + * sysdeps/i386/fpu/libm-test-ulps: Update. + * sysdeps/x86_64/fpu/libm-test-ulps: Likewise. + 2014-04-02 Alan Modra [BZ #16739] diff --git a/NEWS b/NEWS index d959fb33779..63e9303df2f 100644 --- a/NEWS +++ b/NEWS @@ -13,7 +13,8 @@ Version 2.20 16357, 16362, 16447, 16532, 16545, 16574, 16599, 16600, 16609, 16610, 16611, 16613, 16623, 16632, 16634, 16639, 16642, 16648, 16649, 16670, 16674, 16677, 16680, 16683, 16689, 16695, 16701, 16706, 16707, 16712, - 16713, 16714, 16731, 16739, 16743, 16758, 16759, 16760, 16770, 16786. + 16713, 16714, 16731, 16739, 16743, 16758, 16759, 16760, 16770, 16786, + 16789. * Running the testsuite no longer terminates as soon as a test fails. Instead, a file tests.sum (xtests.sum from "make xcheck") is generated, diff --git a/math/libm-test.inc b/math/libm-test.inc index 967b679e940..c6279e75a96 100644 --- a/math/libm-test.inc +++ b/math/libm-test.inc @@ -6122,9 +6122,7 @@ static const struct test_c_c_data clog_test_data[] = static void clog_test (void) { - START (clog, 0); - RUN_TEST_LOOP_c_c (clog, clog_test_data, ); - END_COMPLEX; + ALL_RM_TEST (clog, 0, clog_test_data, RUN_TEST_LOOP_c_c, END_COMPLEX); } @@ -6184,9 +6182,7 @@ static const struct test_c_c_data clog10_test_data[] = static void clog10_test (void) { - START (clog10, 0); - RUN_TEST_LOOP_c_c (clog10, clog10_test_data, ); - END_COMPLEX; + ALL_RM_TEST (clog10, 0, clog10_test_data, RUN_TEST_LOOP_c_c, END_COMPLEX); } diff --git a/math/s_clog.c b/math/s_clog.c index 8639868bbf2..077f8f23e39 100644 --- a/math/s_clog.c +++ b/math/s_clog.c @@ -68,12 +68,9 @@ __clog (__complex__ double x) double absy2 = absy * absy; if (absy2 <= DBL_MIN * 2.0) { -#if __FLT_EVAL_METHOD__ == 0 - __real__ result = absy2 / 2.0 - absy2 * absy2 / 4.0; -#else - volatile double force_underflow = absy2 * absy2 / 4.0; - __real__ result = absy2 / 2.0 - force_underflow; -#endif + double force_underflow = absy2 * absy2; + __real__ result = absy2 / 2.0; + math_force_eval (force_underflow); } else __real__ result = __log1p (absy2) / 2.0; diff --git a/math/s_clog10.c b/math/s_clog10.c index e75787949fc..aa0537c7c17 100644 --- a/math/s_clog10.c +++ b/math/s_clog10.c @@ -74,12 +74,9 @@ __clog10 (__complex__ double x) double absy2 = absy * absy; if (absy2 <= DBL_MIN * 2.0 * M_LN10) { -#if __FLT_EVAL_METHOD__ == 0 - __real__ result = (absy2 / 2.0 - absy2 * absy2 / 4.0) * M_LOG10E; -#else - volatile double force_underflow = absy2 * absy2 / 4.0; - __real__ result = (absy2 / 2.0 - force_underflow) * M_LOG10E; -#endif + double force_underflow = absy2 * absy2; + __real__ result = absy2 * (M_LOG10E / 2.0); + math_force_eval (force_underflow); } else __real__ result = __log1p (absy2) * (M_LOG10E / 2.0); diff --git a/math/s_clog10f.c b/math/s_clog10f.c index ca2cdf4f808..3403b6cd920 100644 --- a/math/s_clog10f.c +++ b/math/s_clog10f.c @@ -74,14 +74,9 @@ __clog10f (__complex__ float x) float absy2 = absy * absy; if (absy2 <= FLT_MIN * 2.0f * (float) M_LN10) { -#if __FLT_EVAL_METHOD__ == 0 - __real__ result - = (absy2 / 2.0f - absy2 * absy2 / 4.0f) * (float) M_LOG10E; -#else - volatile float force_underflow = absy2 * absy2 / 4.0f; - __real__ result - = (absy2 / 2.0f - force_underflow) * (float) M_LOG10E; -#endif + float force_underflow = absy2 * absy2; + __real__ result = absy2 * ((float) M_LOG10E / 2.0f); + math_force_eval (force_underflow); } else __real__ result = __log1pf (absy2) * ((float) M_LOG10E / 2.0f); diff --git a/math/s_clog10l.c b/math/s_clog10l.c index cdb5d610145..fd86ecb47d1 100644 --- a/math/s_clog10l.c +++ b/math/s_clog10l.c @@ -80,8 +80,11 @@ __clog10l (__complex__ long double x) { long double absy2 = absy * absy; if (absy2 <= LDBL_MIN * 2.0L * M_LN10l) - __real__ result - = (absy2 / 2.0L - absy2 * absy2 / 4.0L) * M_LOG10El; + { + long double force_underflow = absy2 * absy2; + __real__ result = absy2 * (M_LOG10El / 2.0); + math_force_eval (force_underflow); + } else __real__ result = __log1pl (absy2) * (M_LOG10El / 2.0L); } diff --git a/math/s_clogf.c b/math/s_clogf.c index 79117df6228..b48733419fd 100644 --- a/math/s_clogf.c +++ b/math/s_clogf.c @@ -68,12 +68,9 @@ __clogf (__complex__ float x) float absy2 = absy * absy; if (absy2 <= FLT_MIN * 2.0f) { -#if __FLT_EVAL_METHOD__ == 0 - __real__ result = absy2 / 2.0f - absy2 * absy2 / 4.0f; -#else - volatile float force_underflow = absy2 * absy2 / 4.0f; - __real__ result = absy2 / 2.0f - force_underflow; -#endif + float force_underflow = absy2 * absy2; + __real__ result = absy2 / 2.0f; + math_force_eval (force_underflow); } else __real__ result = __log1pf (absy2) / 2.0f; diff --git a/math/s_clogl.c b/math/s_clogl.c index bdf82c155a1..1b4a304e328 100644 --- a/math/s_clogl.c +++ b/math/s_clogl.c @@ -74,7 +74,11 @@ __clogl (__complex__ long double x) { long double absy2 = absy * absy; if (absy2 <= LDBL_MIN * 2.0L) - __real__ result = absy2 / 2.0L - absy2 * absy2 / 4.0L; + { + long double force_underflow = absy2 * absy2; + __real__ result = absy2 / 2.0L; + math_force_eval (force_underflow); + } else __real__ result = __log1pl (absy2) / 2.0L; } diff --git a/sysdeps/i386/fpu/libm-test-ulps b/sysdeps/i386/fpu/libm-test-ulps index a82de198ca4..0252d5bbafc 100644 --- a/sysdeps/i386/fpu/libm-test-ulps +++ b/sysdeps/i386/fpu/libm-test-ulps @@ -593,6 +593,102 @@ ifloat: 1 ildouble: 2 ldouble: 2 +Function: Real part of "clog10_downward": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 4 +ldouble: 4 + +Function: Imaginary part of "clog10_downward": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Real part of "clog10_towardzero": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 4 +ldouble: 4 + +Function: Imaginary part of "clog10_towardzero": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Real part of "clog10_upward": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 4 +ldouble: 4 + +Function: Imaginary part of "clog10_upward": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Real part of "clog_downward": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "clog_downward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: Real part of "clog_towardzero": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "clog_towardzero": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: Real part of "clog_upward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "clog_upward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + Function: "cos": ildouble: 1 ldouble: 1 diff --git a/sysdeps/x86_64/fpu/libm-test-ulps b/sysdeps/x86_64/fpu/libm-test-ulps index e2fa9b2ccbc..1b6ebe21ed7 100644 --- a/sysdeps/x86_64/fpu/libm-test-ulps +++ b/sysdeps/x86_64/fpu/libm-test-ulps @@ -624,6 +624,102 @@ ifloat: 1 ildouble: 2 ldouble: 2 +Function: Real part of "clog10_downward": +double: 3 +float: 3 +idouble: 3 +ifloat: 3 +ildouble: 4 +ldouble: 4 + +Function: Imaginary part of "clog10_downward": +double: 3 +float: 2 +idouble: 3 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Real part of "clog10_towardzero": +double: 3 +float: 2 +idouble: 3 +ifloat: 2 +ildouble: 4 +ldouble: 4 + +Function: Imaginary part of "clog10_towardzero": +double: 3 +float: 2 +idouble: 3 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Real part of "clog10_upward": +double: 4 +float: 3 +idouble: 4 +ifloat: 3 +ildouble: 4 +ldouble: 4 + +Function: Imaginary part of "clog10_upward": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Real part of "clog_downward": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "clog_downward": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 1 +ldouble: 1 + +Function: Real part of "clog_towardzero": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "clog_towardzero": +double: 1 +float: 2 +idouble: 1 +ifloat: 2 +ildouble: 1 +ldouble: 1 + +Function: Real part of "clog_upward": +double: 2 +float: 1 +idouble: 2 +ifloat: 1 +ildouble: 2 +ldouble: 2 + +Function: Imaginary part of "clog_upward": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 1 +ldouble: 1 + Function: "cos": ildouble: 1 ldouble: 1