summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Dickinson <mdickinson@enthought.com>2021-06-12 09:23:02 (GMT)
committerGitHub <noreply@github.com>2021-06-12 09:23:02 (GMT)
commit4a42cebf6dd769e2fa4e234a9e91093b3ad1cb63 (patch)
tree925efc812b8810d8c5fb6c1040307d1cacf4b976
parent3ec3ee7d2e9b45b586e486e429b412d6d0ca530f (diff)
downloadcpython-4a42cebf6dd769e2fa4e234a9e91093b3ad1cb63.zip
cpython-4a42cebf6dd769e2fa4e234a9e91093b3ad1cb63.tar.gz
cpython-4a42cebf6dd769e2fa4e234a9e91093b3ad1cb63.tar.bz2
bpo-44339: Fix math.pow corner case to comply with IEEE 754 (GH-26606)
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.
-rw-r--r--Doc/library/math.rst7
-rw-r--r--Doc/whatsnew/3.11.rst10
-rw-r--r--Lib/test/ieee754.txt6
-rw-r--r--Lib/test/test_math.py4
-rw-r--r--Misc/NEWS.d/next/Library/2021-06-08-17-47-38.bpo-44339.9JwMSc.rst3
-rw-r--r--Modules/mathmodule.c2
6 files changed, 21 insertions, 11 deletions
diff --git a/Doc/library/math.rst b/Doc/library/math.rst
index 7aa543a..7118678 100644
--- a/Doc/library/math.rst
+++ b/Doc/library/math.rst
@@ -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)
diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst
index ba7c456..50d91a0 100644
--- a/Doc/whatsnew/3.11.rst
+++ b/Doc/whatsnew/3.11.rst
@@ -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
diff --git a/Lib/test/ieee754.txt b/Lib/test/ieee754.txt
index 89bb0c5..a8b8a0a 100644
--- a/Lib/test/ieee754.txt
+++ b/Lib/test/ieee754.txt
@@ -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):
...
diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py
index da16284..42b61c3 100644
--- a/Lib/test/test_math.py
+++ b/Lib/test/test_math.py
@@ -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
index 0000000..10499eb
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2021-06-08-17-47-38.bpo-44339.9JwMSc.rst
@@ -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.
diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c
index b3429c5..bd97b03 100644
--- a/Modules/mathmodule.c
+++ b/Modules/mathmodule.c
@@ -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.;