]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Fix clog / clog10 sign of zero result in round-downward mode (bug 16789).
authorJoseph Myers <joseph@codesourcery.com>
Wed, 2 Apr 2014 13:10:19 +0000 (13:10 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Wed, 2 Apr 2014 13:10:19 +0000 (13:10 +0000)
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.

ChangeLog
NEWS
math/libm-test.inc
math/s_clog.c
math/s_clog10.c
math/s_clog10f.c
math/s_clog10l.c
math/s_clogf.c
math/s_clogl.c
sysdeps/i386/fpu/libm-test-ulps
sysdeps/x86_64/fpu/libm-test-ulps

index f623e8b79a30142077112a66bc6844dc2424c8e4..4a514563b29e23c85351b500129b26db4138ceed 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2014-04-02  Joseph Myers  <joseph@codesourcery.com>
+
+       [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  <amodra@gmail.com>
 
        [BZ #16739]
diff --git a/NEWS b/NEWS
index d959fb33779799bc3271b6617257e47900621091..63e9303df2fc3b4026a2c159dabccbb6e241c282 100644 (file)
--- 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,
index 967b679e9407ab5f0b88ff046fc92387933c1eaf..c6279e75a96a2c5a51fe5b21130db27bf937a078 100644 (file)
@@ -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);
 }
 
 
index 8639868bbf211e58c3d84bd8471430281888d7d4..077f8f23e39fb8b70e173dca99345be6576e75bd 100644 (file)
@@ -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;
index e75787949fcfe3d0e1e8e6c73148f5757ee8b6d8..aa0537c7c1782d1a24bea1c49ca43947dcc9417d 100644 (file)
@@ -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);
index ca2cdf4f8086ea0ca0e85a0a8da2ee7eff1a54c6..3403b6cd9200232f643da950ee75c12b43681799 100644 (file)
@@ -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);
index cdb5d610145673ec0a8f2810ee59de0a5d69528d..fd86ecb47d18fd089fb8a1a1793a7fa3efa92615 100644 (file)
@@ -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);
        }
index 79117df6228e066abc607e7b0277a02ed7e47db4..b48733419fdd70fa129f8b2c54bcf1d57dcd3b4c 100644 (file)
@@ -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;
index bdf82c155a12f4691e45b6e23501f68f9b81eb47..1b4a304e3285dc27b2466650449b8e8d8291a9b2 100644 (file)
@@ -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;
        }
index a82de198ca43b55e13d0d19af3184bc9b09b32e0..0252d5bbafc1b2c1493017aa19d876e52fe78b3f 100644 (file)
@@ -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
index e2fa9b2ccbc1d58720ef879556cdfc4049df6001..1b6ebe21ed700becb142052b000627e2fde4bf49 100644 (file)
@@ -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