From b72592e75fdecb34e2ac5f931730409a1fb68e8a Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Fri, 23 May 2014 12:07:50 +0000 Subject: Fix log10 (1) in round-downward mode (bug 16977). As with various other issues of this kind, bug 16977 is log10 (1) wrongly returning -0 rather than +0 in round-downward mode because of an implementation effectively in terms of log1p (x - 1). This patch fixes the issue in the same way used for log. Tested x86_64 and x86 and ulps updated accordingly. Also tested for mips64 to confirm a fix was needed for ldbl-128 and to validate that fix (also applied to ldbl-128ibm since that version of logl is essentially the same as the ldbl-128 one). [BZ #16977] * sysdeps/i386/fpu/e_log10.S (__ieee754_log10): Take absolute value when x - 1 is zero. * sysdeps/i386/fpu/e_log10f.S (__ieee754_log10f): Likewise. * sysdeps/i386/fpu/e_log10l.S (__ieee754_log10l): Likewise. * sysdeps/ieee754/ldbl-128/e_log10l.c (__ieee754_log10l): Return 0.0L for an argument of 1.0L. * sysdeps/ieee754/ldbl-128ibm/e_log10l.c (__ieee754_log10l): Likewise. * sysdeps/x86_64/fpu/e_log10l.S (__ieee754_log10l): Take absolute value when x - 1 is zero. * math/libm-test.inc (log10_test): Use ALL_RM_TEST. * sysdeps/i386/fpu/libm-test-ulps: Update. * sysdeps/x86_64/fpu/libm-test-ulps: Likewise. --- ChangeLog | 17 +++++++++++++++++ NEWS | 2 +- math/libm-test.inc | 4 +--- sysdeps/i386/fpu/e_log10.S | 8 +++++++- sysdeps/i386/fpu/e_log10f.S | 8 +++++++- sysdeps/i386/fpu/e_log10l.S | 8 +++++++- sysdeps/i386/fpu/libm-test-ulps | 24 ++++++++++++++++++++++++ sysdeps/ieee754/ldbl-128/e_log10l.c | 3 +++ sysdeps/ieee754/ldbl-128ibm/e_log10l.c | 3 +++ sysdeps/x86_64/fpu/e_log10l.S | 8 +++++++- sysdeps/x86_64/fpu/libm-test-ulps | 24 ++++++++++++++++++++++++ 11 files changed, 101 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index a7a9185e85..c035c9f882 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2014-05-23 Joseph Myers + + [BZ #16977] + * sysdeps/i386/fpu/e_log10.S (__ieee754_log10): Take absolute + value when x - 1 is zero. + * sysdeps/i386/fpu/e_log10f.S (__ieee754_log10f): Likewise. + * sysdeps/i386/fpu/e_log10l.S (__ieee754_log10l): Likewise. + * sysdeps/ieee754/ldbl-128/e_log10l.c (__ieee754_log10l): Return + 0.0L for an argument of 1.0L. + * sysdeps/ieee754/ldbl-128ibm/e_log10l.c (__ieee754_log10l): + Likewise. + * sysdeps/x86_64/fpu/e_log10l.S (__ieee754_log10l): Take absolute + value when x - 1 is zero. + * math/libm-test.inc (log10_test): Use ALL_RM_TEST. + * sysdeps/i386/fpu/libm-test-ulps: Update. + * sysdeps/x86_64/fpu/libm-test-ulps: Likewise. + 2014-05-23 Rasmus Villemoes * manual/filesys.texi (Scanning Directory Content): Fix prototype of diff --git a/NEWS b/NEWS index 8aaf2f4cb5..1c44fd6e2d 100644 --- a/NEWS +++ b/NEWS @@ -18,7 +18,7 @@ Version 2.20 16760, 16770, 16786, 16789, 16791, 16799, 16800, 16815, 16823, 16824, 16831, 16838, 16849, 16854, 16876, 16877, 16885, 16888, 16890, 16912, 16915, 16916, 16917, 16922, 16927, 16928, 16932, 16943, 16958, 16966, - 16967, 16965. + 16967, 16965, 16977. * The minimum Linux kernel version that this version of the GNU C Library can be used with is 2.6.32. diff --git a/math/libm-test.inc b/math/libm-test.inc index de7bc8ad94..0d467a2195 100644 --- a/math/libm-test.inc +++ b/math/libm-test.inc @@ -7798,9 +7798,7 @@ static const struct test_f_f_data log10_test_data[] = static void log10_test (void) { - START (log10, 0); - RUN_TEST_LOOP_f_f (log10, log10_test_data, ); - END; + ALL_RM_TEST (log10, 0, log10_test_data, RUN_TEST_LOOP_f_f, END); } diff --git a/sysdeps/i386/fpu/e_log10.S b/sysdeps/i386/fpu/e_log10.S index ce6a81abb6..17277084ca 100644 --- a/sysdeps/i386/fpu/e_log10.S +++ b/sysdeps/i386/fpu/e_log10.S @@ -46,7 +46,13 @@ ENTRY(__ieee754_log10) fnstsw // x-1 : x : log10(2) andb $0x45, %ah jz 2f - fstp %st(1) // x-1 : log10(2) + fxam + fnstsw + andb $0x45, %ah + cmpb $0x40, %ah + jne 5f + fabs // log10(1) is +0 in all rounding modes. +5: fstp %st(1) // x-1 : log10(2) fyl2xp1 // log10(x) ret diff --git a/sysdeps/i386/fpu/e_log10f.S b/sysdeps/i386/fpu/e_log10f.S index 8c20723555..72a3b88251 100644 --- a/sysdeps/i386/fpu/e_log10f.S +++ b/sysdeps/i386/fpu/e_log10f.S @@ -47,7 +47,13 @@ ENTRY(__ieee754_log10f) fnstsw // x-1 : x : log10(2) andb $0x45, %ah jz 2f - fstp %st(1) // x-1 : log10(2) + fxam + fnstsw + andb $0x45, %ah + cmpb $0x40, %ah + jne 5f + fabs // log10(1) is +0 in all rounding modes. +5: fstp %st(1) // x-1 : log10(2) fyl2xp1 // log10(x) ret diff --git a/sysdeps/i386/fpu/e_log10l.S b/sysdeps/i386/fpu/e_log10l.S index cde987b137..45b9c6d21d 100644 --- a/sysdeps/i386/fpu/e_log10l.S +++ b/sysdeps/i386/fpu/e_log10l.S @@ -48,7 +48,13 @@ ENTRY(__ieee754_log10l) fnstsw // x-1 : x : log10(2) andb $0x45, %ah jz 2f - fstp %st(1) // x-1 : log10(2) + fxam + fnstsw + andb $0x45, %ah + cmpb $0x40, %ah + jne 5f + fabs // log10(1) is +0 in all rounding modes. +5: fstp %st(1) // x-1 : log10(2) fyl2xp1 // log10(x) ret diff --git a/sysdeps/i386/fpu/libm-test-ulps b/sysdeps/i386/fpu/libm-test-ulps index 946cad489b..1e89284455 100644 --- a/sysdeps/i386/fpu/libm-test-ulps +++ b/sysdeps/i386/fpu/libm-test-ulps @@ -1536,6 +1536,30 @@ Function: "log10": ildouble: 1 ldouble: 1 +Function: "log10_downward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "log10_towardzero": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "log10_upward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + Function: "log1p": ildouble: 1 ldouble: 1 diff --git a/sysdeps/ieee754/ldbl-128/e_log10l.c b/sysdeps/ieee754/ldbl-128/e_log10l.c index b403f815fb..618255f2fa 100644 --- a/sysdeps/ieee754/ldbl-128/e_log10l.c +++ b/sysdeps/ieee754/ldbl-128/e_log10l.c @@ -193,6 +193,9 @@ __ieee754_log10l (long double x) if (hx >= 0x7fff000000000000LL) return (x + x); + if (x == 1.0L) + return 0.0L; + /* separate mantissa from exponent */ /* Note, frexp is used so that denormal numbers diff --git a/sysdeps/ieee754/ldbl-128ibm/e_log10l.c b/sysdeps/ieee754/ldbl-128ibm/e_log10l.c index 1a6a4a0fa3..7477791b77 100644 --- a/sysdeps/ieee754/ldbl-128ibm/e_log10l.c +++ b/sysdeps/ieee754/ldbl-128ibm/e_log10l.c @@ -195,6 +195,9 @@ __ieee754_log10l (long double x) if (hx >= 0x7ff0000000000000LL) return (x + x); + if (x == 1.0L) + return 0.0L; + /* separate mantissa from exponent */ /* Note, frexp is used so that denormal numbers diff --git a/sysdeps/x86_64/fpu/e_log10l.S b/sysdeps/x86_64/fpu/e_log10l.S index 6c07024c19..2607ad199b 100644 --- a/sysdeps/x86_64/fpu/e_log10l.S +++ b/sysdeps/x86_64/fpu/e_log10l.S @@ -46,7 +46,13 @@ ENTRY(__ieee754_log10l) fnstsw // x-1 : x : log10(2) andb $0x45, %ah jz 2f - fstp %st(1) // x-1 : log10(2) + fxam + fnstsw + andb $0x45, %ah + cmpb $0x40, %ah + jne 5f + fabs // log10(1) is +0 in all rounding modes. +5: fstp %st(1) // x-1 : log10(2) fyl2xp1 // log10(x) ret diff --git a/sysdeps/x86_64/fpu/libm-test-ulps b/sysdeps/x86_64/fpu/libm-test-ulps index d47287696c..bb549d2b0d 100644 --- a/sysdeps/x86_64/fpu/libm-test-ulps +++ b/sysdeps/x86_64/fpu/libm-test-ulps @@ -1611,6 +1611,30 @@ ifloat: 2 ildouble: 1 ldouble: 1 +Function: "log10_downward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "log10_towardzero": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "log10_upward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + Function: "log1p": float: 1 ifloat: 1 -- cgit 1.4.1