[Python-checkins] r62414 - in python/trunk: Lib/test/test_math.py Modules/mathmodule.c

Benjamin Peterson musiccomposition at gmail.com
Mon Apr 21 03:03:40 CEST 2008


Mark, can you fix the following compiler warning? (MacOS gcc)

py3k/Modules/mathmodule.c: In function 'math_pow':
py3k/Modules/mathmodule.c:597: warning: 'r' may be used uninitialized
in this function

On Sat, Apr 19, 2008 at 11:13 PM, mark.dickinson
<python-checkins at python.org> wrote:
> Author: mark.dickinson
>  Date: Sun Apr 20 06:13:13 2008
>  New Revision: 62414
>
>  Log:
>  Yet more explicit special case handling to make
>  math.pow behave on alpha Tru64.  All IEEE 754
>  special values are now handled directly; only
>  the finite**finite case is handled by libm.
>
>
>  Modified:
>    python/trunk/Lib/test/test_math.py
>    python/trunk/Modules/mathmodule.c
>
>  Modified: python/trunk/Lib/test/test_math.py
>  ==============================================================================
>  --- python/trunk/Lib/test/test_math.py  (original)
>  +++ python/trunk/Lib/test/test_math.py  Sun Apr 20 06:13:13 2008
>  @@ -498,6 +498,18 @@
>          self.assertEqual(math.pow(-1.1, INF), INF)
>          self.assertEqual(math.pow(-1.9, INF), INF)
>
>  +        # pow(x, y) should work for x negative, y an integer
>  +        self.ftest('(-2.)**3.', math.pow(-2.0, 3.0), -8.0)
>  +        self.ftest('(-2.)**2.', math.pow(-2.0, 2.0), 4.0)
>  +        self.ftest('(-2.)**1.', math.pow(-2.0, 1.0), -2.0)
>  +        self.ftest('(-2.)**0.', math.pow(-2.0, 0.0), 1.0)
>  +        self.ftest('(-2.)**-0.', math.pow(-2.0, -0.0), 1.0)
>  +        self.ftest('(-2.)**-1.', math.pow(-2.0, -1.0), -0.5)
>  +        self.ftest('(-2.)**-2.', math.pow(-2.0, -2.0), 0.25)
>  +        self.ftest('(-2.)**-3.', math.pow(-2.0, -3.0), -0.125)
>  +        self.assertRaises(ValueError, math.pow, -2.0, -0.5)
>  +        self.assertRaises(ValueError, math.pow, -2.0, 0.5)
>  +
>          # the following tests have been commented out since they don't
>          # really belong here:  the implementation of ** for floats is
>          # independent of the implemention of math.pow
>
>  Modified: python/trunk/Modules/mathmodule.c
>  ==============================================================================
>  --- python/trunk/Modules/mathmodule.c   (original)
>  +++ python/trunk/Modules/mathmodule.c   Sun Apr 20 06:13:13 2008
>  @@ -522,7 +522,7 @@
>   {
>         PyObject *ox, *oy;
>         double r, x, y;
>  -       int y_is_odd;
>  +       int odd_y;
>
>         if (! PyArg_UnpackTuple(args, "pow", 2, 2, &ox, &oy))
>                 return NULL;
>  @@ -531,53 +531,61 @@
>         if ((x == -1.0 || y == -1.0) && PyErr_Occurred())
>                 return NULL;
>
>  -       /* deal directly with various special cases, to cope with problems on
>  -          various platforms whose semantics don't exactly match C99 */
>  -
>  -       /* 1**x, x**0, and (-1)**(+-infinity) return 1., even if x is NaN or
>  -          an infinity. */
>  -       if (x == 1. || y == 0. || (x == -1. && Py_IS_INFINITY(y)))
>  -               return PyFloat_FromDouble(1.);
>  -       /* otherwise, return a NaN if either input was a NaN */
>  -       if (Py_IS_NAN(x))
>  -               return PyFloat_FromDouble(x);
>  -       if (Py_IS_NAN(y))
>  -               return PyFloat_FromDouble(y);
>  -       /* inf ** (nonzero, non-NaN) is one of +-0, +-infinity */
>  -       if (Py_IS_INFINITY(x) && !Py_IS_NAN(y)) {
>  -               y_is_odd = Py_IS_FINITE(y) && fmod(fabs(y), 2.0) == 1.0;
>  -               if (y > 0.)
>  -                       r = y_is_odd ? x : fabs(x);
>  -               else
>  -                       r = y_is_odd ? copysign(0., x) : 0.;
>  -               return PyFloat_FromDouble(r);
>  +       /* deal directly with IEEE specials, to cope with problems on various
>  +          platforms whose semantics don't exactly match C99 */
>  +       if (!Py_IS_FINITE(x) || !Py_IS_FINITE(y)) {
>  +               errno = 0;
>  +               if (Py_IS_NAN(x))
>  +                       r = y == 0. ? 1. : x; /* NaN**0 = 1 */
>  +               else if (Py_IS_NAN(y))
>  +                       r = x == 1. ? 1. : y; /* 1**NaN = 1 */
>  +               else if (Py_IS_INFINITY(x)) {
>  +                       odd_y = Py_IS_FINITE(y) && fmod(fabs(y), 2.0) == 1.0;
>  +                       if (y > 0.)
>  +                               r = odd_y ? x : fabs(x);
>  +                       else if (y == 0.)
>  +                               r = 1.;
>  +                       else /* y < 0. */
>  +                               r = odd_y ? copysign(0., x) : 0.;
>  +               }
>  +               else if (Py_IS_INFINITY(y)) {
>  +                       if (fabs(x) == 1.0)
>  +                               r = 1.;
>  +                       else if (y > 0. && fabs(x) > 1.0)
>  +                               r = y;
>  +                       else if (y < 0. && fabs(x) < 1.0) {
>  +                               r = -y; /* result is +inf */
>  +                               if (x == 0.) /* 0**-inf: divide-by-zero */
>  +                                       errno = EDOM;
>  +                       }
>  +                       else
>  +                               r = 0.;
>  +               }
>         }
>  -
>  -       errno = 0;
>  -       PyFPE_START_PROTECT("in math_pow", return 0);
>  -       r = pow(x, y);
>  -       PyFPE_END_PROTECT(r);
>  -       if (Py_IS_NAN(r)) {
>  -               errno = EDOM;
>  -       }
>  -       /* an infinite result arises either from:
>  -
>  -          (A) (+/-0.)**negative,
>  -          (B) overflow of x**y with both x and y finite (and x nonzero)
>  -          (C) (+/-inf)**positive, or
>  -          (D) x**inf with |x| > 1, or x**-inf with |x| < 1.
>  -
>  -          In case (A) we want ValueError to be raised.  In case (B)
>  -          OverflowError should be raised.  In cases (C) and (D) the infinite
>  -          result should be returned.
>  -       */
>  -       else if (Py_IS_INFINITY(r)) {
>  -               if (x == 0.)
>  -                       errno = EDOM;
>  -               else if (Py_IS_FINITE(x) && Py_IS_FINITE(y))
>  -                       errno = ERANGE;
>  -               else
>  -                       errno = 0;
>  +       else {
>  +               /* let libm handle finite**finite */
>  +               errno = 0;
>  +               PyFPE_START_PROTECT("in math_pow", return 0);
>  +               r = pow(x, y);
>  +               PyFPE_END_PROTECT(r);
>  +               /* a NaN result should arise only from (-ve)**(finite
>  +                  non-integer); in this case we want to raise ValueError. */
>  +               if (!Py_IS_FINITE(r)) {
>  +                       if (Py_IS_NAN(r)) {
>  +                               errno = EDOM;
>  +                       }
>  +                       /*
>  +                          an infinite result here arises either from:
>  +                          (A) (+/-0.)**negative (-> divide-by-zero)
>  +                          (B) overflow of x**y with x and y finite
>  +                       */
>  +                       else if (Py_IS_INFINITY(r)) {
>  +                               if (x == 0.)
>  +                                       errno = EDOM;
>  +                               else
>  +                                       errno = ERANGE;
>  +                       }
>  +               }
>         }
>
>         if (errno && is_error(r))
>  _______________________________________________
>  Python-checkins mailing list
>  Python-checkins at python.org
>  http://mail.python.org/mailman/listinfo/python-checkins
>



-- 
Cheers,
Benjamin Peterson


More information about the Python-checkins mailing list