Fix pow (0.0, -Inf) (bug 14241)

Andreas Jaeger aj@suse.com
Fri Jun 15 07:53:00 GMT 2012


On 06/14/2012 10:57 PM, Joseph S. Myers wrote:
> Bug 14241 is a regression in pow where pow (0.0, -Inf) returns the
> wrong result on architectures using the dbl-64/e_pow.c
> implementation.  The problem is in the use of ABS(x) (inside the case
> where x is a zero); the ABS macro in mydefs.h is
>
> #define ABS(x)   (((x)>0)?(x):-(x))
>
> which gives -0.0 when x is 0.0.  (This also affects the similar code
> in the case for finite negative powers with absolute value up to 1e20
> and not odd integers, but this doesn't show as testsuite failures
> because in those cases the correct return value ends up coming from
> __kernel_standard.)
>
> I propose this patch fixing this by using 0.0 instead of ABS(x) in the
> relevant places (not changing the definition of the ABS macro, given
> that I don't know the reasons behind the present choice and given all
> the other uses of that macro).  Tested x86 and x86_64.  Note that the
> use of DIVIDE_BY_ZERO_EXCEPTION_OK is in accordance with C11 where
> this exception is permitted but not required in this case (a
> correction to C99 following N1515; ideally the exception would not be
> present for these cases of infinite exponent, but now is not the time
> to ensure and test consistency in this regard across the various pow
> implementations).
>
> 2012-06-14  Joseph Myers  <joseph@codesourcery.com>
>
> 	[BZ #14241]
> 	* sysdeps/ieee754/dbl-64/e_pow.c (__ieee754_pow): Use 0.0 instead
> 	of ABS(x) in calculating zero to negative powers other than odd
> 	integers.
> 	* math/libm-test.inc (pow_test): Add more tests.
>
> diff --git a/math/libm-test.inc b/math/libm-test.inc
> index d32dde3..8e4d02e 100644
> --- a/math/libm-test.inc
> +++ b/math/libm-test.inc
> @@ -6290,6 +6290,8 @@ pow_test (void)
>     TEST_ff_f (pow, minus_zero, 11.1L, 0);
>     TEST_ff_f (pow, 0, plus_infty, 0);
>     TEST_ff_f (pow, minus_zero, plus_infty, 0);
> +  TEST_ff_f (pow, 0, minus_infty, plus_infty, DIVIDE_BY_ZERO_EXCEPTION_OK);
> +  TEST_ff_f (pow, minus_zero, minus_infty, plus_infty, DIVIDE_BY_ZERO_EXCEPTION_OK);
>
>   #ifndef TEST_INLINE
>     /* pow (x, +inf) == +inf for |x| > 1.  */
> diff --git a/sysdeps/ieee754/dbl-64/e_pow.c b/sysdeps/ieee754/dbl-64/e_pow.c
> index 6c41af9..3fd5e65 100644
> --- a/sysdeps/ieee754/dbl-64/e_pow.c
> +++ b/sysdeps/ieee754/dbl-64/e_pow.c
> @@ -112,12 +112,12 @@ __ieee754_pow(double x, double y) {
>       if (((v.i[HIGH_HALF] & 0x7fffffff) == 0x7ff00000 && v.i[LOW_HALF] != 0)
>   	|| (v.i[HIGH_HALF] & 0x7fffffff) > 0x7ff00000)
>         return y;
> -    if (ABS(y) > 1.0e20) return (y>0)?0:1.0/ABS(x);
> +    if (ABS(y) > 1.0e20) return (y>0)?0:1.0/0.0;
>       k = checkint(y);
>       if (k == -1)
>         return y < 0 ? 1.0/x : x;
>       else
> -      return y < 0 ? 1.0/ABS(x) : 0.0;                               /* return 0 */
> +      return y < 0 ? 1.0/0.0 : 0.0;                               /* return 0 */
>     }
>
>     qx = u.i[HIGH_HALF]&0x7fffffff;  /*   no sign   */
>

Your previous change was:

commit 2460d3aa21f04cdf28497683bd3e29183189f779
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Wed Mar 21 12:14:57 2012 +0000

     Fix pow of zero and infinity to large powers.

diff --git a/sysdeps/ieee754/dbl-64/e_pow.c b/sysdeps/ieee754/dbl-64/e_pow.c
index f936a72..26ffaad 100644
--- a/sysdeps/ieee754/dbl-64/e_pow.c
+++ b/sysdeps/ieee754/dbl-64/e_pow.c
@@ -111,7 +111,7 @@ __ieee754_pow(double x, double y) {
      if (((v.i[HIGH_HALF] & 0x7fffffff) == 0x7ff00000 && v.i[LOW_HALF] 
!= 0)
         || (v.i[HIGH_HALF] & 0x7fffffff) > 0x7ff00000)
        return y;
-    if (ABS(y) > 1.0e20) return (y>0)?0:INF.x;
+    if (ABS(y) > 1.0e20) return (y>0)?0:1.0/ABS(x);
      k = checkint(y);
      if (k == -1)
        return y < 0 ? 1.0/x : x;

Can't we just revert this - just using INF.x in both places? Why do we 
need the division here?

Andreas
-- 
  Andreas Jaeger aj@{suse.com,opensuse.org} Twitter/Identica: jaegerandi
   SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
    GF: Jeff Hawn,Jennifer Guild,Felix Imendörffer,HRB16746 (AG Nürnberg)
     GPG fingerprint = 93A3 365E CE47 B889 DF7F  FED1 389A 563C C272 A126




More information about the Libc-alpha mailing list