From: Joseph Myers Date: Tue, 10 Jun 2014 12:07:15 +0000 (+0000) Subject: Fix log2 (1) in round-downward mode (bug 17042). X-Git-Tag: glibc-2.20~363 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f8ba1b5654d876c8db4c9a020e6fa976d434f988;p=thirdparty%2Fglibc.git Fix log2 (1) in round-downward mode (bug 17042). As with other issues of this kind, bug 17042 is log2 (1) wrongly returning -0 instead of +0 in round-downward mode because of implementations effectively in terms of log1p (x - 1). This patch fixes the issue in the same way used for log and log10. 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 log2l is essentially the same as the ldbl-128 one). [BZ #17042] * sysdeps/i386/fpu/e_log2.S (__ieee754_log2): Take absolete value when x - 1 is zero. * sysdeps/i386/fpu/e_log2f.S (__ieee754_log2f): Likewise. * sysdeps/i386/fpu/e_log2l.S (__ieee754_log2l): Likewise. * sysdeps/ieee754/ldbl-128/e_log2l.c (__ieee754_log2l): Return 0.0L for an argument of 1.0L. * sysdeps/ieee754/ldbl-128ibm/e_log2l.c (__ieee754_log2l): Likewise. * sysdeps/x86_64/fpu/e_log2l.S (__ieee754_log2l): Take absolute value when x - 1 is zero. * math/libm-test.inc (log2_test): Use ALL_RM_TEST. * sysdeps/i386/fpu/libm-test-ulps: Update. * sysdeps/x86_64/fpu/libm-test-ulps: Likewise. --- diff --git a/ChangeLog b/ChangeLog index 0ace298b9ed..9055159cf0a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2014-06-10 Joseph Myers + + [BZ #17042] + * sysdeps/i386/fpu/e_log2.S (__ieee754_log2): Take absolete value + when x - 1 is zero. + * sysdeps/i386/fpu/e_log2f.S (__ieee754_log2f): Likewise. + * sysdeps/i386/fpu/e_log2l.S (__ieee754_log2l): Likewise. + * sysdeps/ieee754/ldbl-128/e_log2l.c (__ieee754_log2l): Return + 0.0L for an argument of 1.0L. + * sysdeps/ieee754/ldbl-128ibm/e_log2l.c (__ieee754_log2l): + Likewise. + * sysdeps/x86_64/fpu/e_log2l.S (__ieee754_log2l): Take absolute + value when x - 1 is zero. + * math/libm-test.inc (log2_test): Use ALL_RM_TEST. + * sysdeps/i386/fpu/libm-test-ulps: Update. + * sysdeps/x86_64/fpu/libm-test-ulps: Likewise. + 2014-06-09 Bernard Ogden [BZ #15119] diff --git a/NEWS b/NEWS index 622cdbf21d2..ca3ef633b01 100644 --- a/NEWS +++ b/NEWS @@ -19,7 +19,7 @@ Version 2.20 16791, 16796, 16799, 16800, 16815, 16823, 16824, 16831, 16838, 16849, 16854, 16876, 16877, 16878, 16882, 16885, 16888, 16890, 16912, 16915, 16916, 16917, 16922, 16927, 16928, 16932, 16943, 16958, 16965, 16966, - 16967, 16977, 16978, 16984, 16990, 17009. + 16967, 16977, 16978, 16984, 16990, 17009, 17042. * 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 0d467a21951..fa8e2385dc1 100644 --- a/math/libm-test.inc +++ b/math/libm-test.inc @@ -7840,9 +7840,7 @@ static const struct test_f_f_data log2_test_data[] = static void log2_test (void) { - START (log2, 0); - RUN_TEST_LOOP_f_f (log2, log2_test_data, ); - END; + ALL_RM_TEST (log2, 0, log2_test_data, RUN_TEST_LOOP_f_f, END); } diff --git a/sysdeps/i386/fpu/e_log2.S b/sysdeps/i386/fpu/e_log2.S index a202bc731df..73ff0fffd38 100644 --- a/sysdeps/i386/fpu/e_log2.S +++ b/sysdeps/i386/fpu/e_log2.S @@ -47,7 +47,13 @@ ENTRY(__ieee754_log2) fnstsw // x-1 : x : 1 andb $0x45, %ah jz 2f - fstp %st(1) // x-1 : 1 + fxam + fnstsw + andb $0x45, %ah + cmpb $0x40, %ah + jne 5f + fabs // log2(1) is +0 in all rounding modes. +5: fstp %st(1) // x-1 : 1 fyl2xp1 // log(x) ret diff --git a/sysdeps/i386/fpu/e_log2f.S b/sysdeps/i386/fpu/e_log2f.S index f4f9a8c3bfc..344eeb495e4 100644 --- a/sysdeps/i386/fpu/e_log2f.S +++ b/sysdeps/i386/fpu/e_log2f.S @@ -47,7 +47,13 @@ ENTRY(__ieee754_log2f) fnstsw // x-1 : x : 1 andb $0x45, %ah jz 2f - fstp %st(1) // x-1 : 1 + fxam + fnstsw + andb $0x45, %ah + cmpb $0x40, %ah + jne 5f + fabs // log2(1) is +0 in all rounding modes. +5: fstp %st(1) // x-1 : 1 fyl2xp1 // log(x) ret diff --git a/sysdeps/i386/fpu/e_log2l.S b/sysdeps/i386/fpu/e_log2l.S index bd51b5651ec..0f5f7e5789a 100644 --- a/sysdeps/i386/fpu/e_log2l.S +++ b/sysdeps/i386/fpu/e_log2l.S @@ -47,7 +47,13 @@ ENTRY(__ieee754_log2l) fnstsw // x-1 : x : 1 andb $0x45, %ah jz 2f - fstp %st(1) // x-1 : 1 + fxam + fnstsw + andb $0x45, %ah + cmpb $0x40, %ah + jne 5f + fabs // log2(1) is +0 in all rounding modes. +5: fstp %st(1) // x-1 : 1 fyl2xp1 // log(x) ret diff --git a/sysdeps/i386/fpu/libm-test-ulps b/sysdeps/i386/fpu/libm-test-ulps index 1e892844550..d7424a6f86a 100644 --- a/sysdeps/i386/fpu/libm-test-ulps +++ b/sysdeps/i386/fpu/libm-test-ulps @@ -1588,6 +1588,22 @@ ifloat: 1 ildouble: 1 ldouble: 1 +Function: "log2_towardzero": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "log2_upward": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + Function: "log_downward": ildouble: 1 ldouble: 1 diff --git a/sysdeps/ieee754/ldbl-128/e_log2l.c b/sysdeps/ieee754/ldbl-128/e_log2l.c index 6c7da0e44b9..991a3b73e2e 100644 --- a/sysdeps/ieee754/ldbl-128/e_log2l.c +++ b/sysdeps/ieee754/ldbl-128/e_log2l.c @@ -188,6 +188,9 @@ __ieee754_log2l (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_log2l.c b/sysdeps/ieee754/ldbl-128ibm/e_log2l.c index 323ded0c0fa..442ad972545 100644 --- a/sysdeps/ieee754/ldbl-128ibm/e_log2l.c +++ b/sysdeps/ieee754/ldbl-128ibm/e_log2l.c @@ -190,6 +190,9 @@ __ieee754_log2l (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_log2l.S b/sysdeps/x86_64/fpu/e_log2l.S index 956489fc3eb..c12906d456c 100644 --- a/sysdeps/x86_64/fpu/e_log2l.S +++ b/sysdeps/x86_64/fpu/e_log2l.S @@ -45,7 +45,13 @@ ENTRY(__ieee754_log2l) fnstsw // x-1 : x : 1 andb $0x45, %ah jz 2f - fstp %st(1) // x-1 : 1 + fxam + fnstsw + andb $0x45, %ah + cmpb $0x40, %ah + jne 5f + fabs // log2(1) is +0 in all rounding modes. +5: fstp %st(1) // x-1 : 1 fyl2xp1 // log(x) ret diff --git a/sysdeps/x86_64/fpu/libm-test-ulps b/sysdeps/x86_64/fpu/libm-test-ulps index bb549d2b0d7..92fef5a134f 100644 --- a/sysdeps/x86_64/fpu/libm-test-ulps +++ b/sysdeps/x86_64/fpu/libm-test-ulps @@ -1665,6 +1665,28 @@ ifloat: 1 ildouble: 1 ldouble: 1 +Function: "log2_downward": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 + +Function: "log2_towardzero": +double: 1 +float: 1 +idouble: 1 +ifloat: 1 +ildouble: 1 +ldouble: 1 + +Function: "log2_upward": +double: 2 +float: 2 +idouble: 2 +ifloat: 2 +ildouble: 1 +ldouble: 1 + Function: "log_downward": float: 1 ifloat: 1