]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-44339: Fix math.pow corner case to comply with IEEE 754 (GH-26606)
authorMark Dickinson <mdickinson@enthought.com>
Sat, 12 Jun 2021 09:23:02 +0000 (10:23 +0100)
committerGitHub <noreply@github.com>
Sat, 12 Jun 2021 09:23:02 +0000 (10:23 +0100)
Change the behaviour of `math.pow(0.0, -math.inf)` and `math.pow(-0.0, -math.inf)` to return positive infinity instead of raising `ValueError`. This makes `math.pow` consistent with the built-in `pow` (and the `**` operator) for this particular special case, and brings the `math.pow` special-case handling into compliance with IEEE 754.

Doc/library/math.rst
Doc/whatsnew/3.11.rst
Lib/test/ieee754.txt
Lib/test/test_math.py
Misc/NEWS.d/next/Library/2021-06-08-17-47-38.bpo-44339.9JwMSc.rst [new file with mode: 0644]
Modules/mathmodule.c

index 7aa543ae5d47eaccc2d227954febb33f171b9e50..71186788a652af826b8f51e7c31e14b97c9c26e6 100644 (file)
@@ -409,7 +409,7 @@ Power and logarithmic functions
 .. function:: pow(x, y)
 
    Return ``x`` raised to the power ``y``.  Exceptional cases follow
-   Annex 'F' of the C99 standard as far as possible.  In particular,
+   the IEEE 754 standard as far as possible.  In particular,
    ``pow(1.0, x)`` and ``pow(x, 0.0)`` always return ``1.0``, even
    when ``x`` is a zero or a NaN.  If both ``x`` and ``y`` are finite,
    ``x`` is negative, and ``y`` is not an integer then ``pow(x, y)``
@@ -419,6 +419,11 @@ Power and logarithmic functions
    its arguments to type :class:`float`.  Use ``**`` or the built-in
    :func:`pow` function for computing exact integer powers.
 
+   .. versionchanged:: 3.11
+      The special cases ``pow(0.0, -inf)`` and ``pow(-0.0, -inf)`` were
+      changed to return ``inf`` instead of raising :exc:`ValueError`,
+      for consistency with IEEE 754.
+
 
 .. function:: sqrt(x)
 
index ba7c456aa21565a80407dfca07d9306808d759f7..50d91a0adc141b50c46a84b922620f87c05834cb 100644 (file)
@@ -96,8 +96,14 @@ string.  (Contributed by Sergey B Kirpichev in :issue:`44258`.)
 math
 ----
 
-Add :func:`math.cbrt()`: return the cube root of x.
-(Contributed by Ajith Ramachandran in :issue:`44357`.)
+* Add :func:`math.cbrt`: return the cube root of x.
+  (Contributed by Ajith Ramachandran in :issue:`44357`.)
+
+* The behaviour of two :func:`math.pow` corner cases was changed, for
+  consistency with the IEEE 754 specification. The operations
+  ``math.pow(0.0, -math.inf)`` and ``math.pow(-0.0, -math.inf)`` now return
+  ``inf``. Previously they raised :exc:`ValueError`. (Contributed by Mark
+  Dickinson in :issue:`44339`.)
 
 
 Removed
index 89bb0c50a3d24a1ce4445575c585f93f13f67b0c..a8b8a0a2148f00d2bfb1d047822207de93b34904 100644 (file)
@@ -104,7 +104,7 @@ infinity and NaN.
 1.0
 
 The power of 0 raised to x is defined as 0, if x is positive. Negative
-values are a domain error or zero division error and NaN result in a
+finite values are a domain error or zero division error and NaN result in a
 silent NaN.
 
 >>> pow(0, 0)
@@ -112,9 +112,7 @@ silent NaN.
 >>> pow(0, INF)
 0.0
 >>> pow(0, -INF)
-Traceback (most recent call last):
-...
-ValueError: math domain error
+inf
 >>> 0 ** -1
 Traceback (most recent call last):
 ...
index da162844e202a07d77f3f630837c33f0c1ba5ce0..42b61c317c4e3af41140df8e8a3ecfc2558530b4 100644 (file)
@@ -1230,7 +1230,7 @@ class MathTests(unittest.TestCase):
         self.assertRaises(ValueError, math.pow, 0., -2.)
         self.assertRaises(ValueError, math.pow, 0., -2.3)
         self.assertRaises(ValueError, math.pow, 0., -3.)
-        self.assertRaises(ValueError, math.pow, 0., NINF)
+        self.assertEqual(math.pow(0., NINF), INF)
         self.assertTrue(math.isnan(math.pow(0., NAN)))
 
         # pow(INF, x)
@@ -1256,7 +1256,7 @@ class MathTests(unittest.TestCase):
         self.assertRaises(ValueError, math.pow, -0., -2.)
         self.assertRaises(ValueError, math.pow, -0., -2.3)
         self.assertRaises(ValueError, math.pow, -0., -3.)
-        self.assertRaises(ValueError, math.pow, -0., NINF)
+        self.assertEqual(math.pow(-0., NINF), INF)
         self.assertTrue(math.isnan(math.pow(-0., NAN)))
 
         # pow(NINF, x)
diff --git a/Misc/NEWS.d/next/Library/2021-06-08-17-47-38.bpo-44339.9JwMSc.rst b/Misc/NEWS.d/next/Library/2021-06-08-17-47-38.bpo-44339.9JwMSc.rst
new file mode 100644 (file)
index 0000000..10499eb
--- /dev/null
@@ -0,0 +1,3 @@
+Change ``math.pow(±0.0, -math.inf)`` to return ``inf`` instead of raising
+``ValueError``. This brings the special-case handling of ``math.pow`` into
+compliance with the IEEE 754 standard.
index b3429c5653c958fef772defa5e4f783dfae9c4b7..bd97b03205b7cae4ebc00ff606ca9cd3bd5abd3d 100644 (file)
@@ -2810,8 +2810,6 @@ math_pow_impl(PyObject *module, double x, double y)
                 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.;