mirror of
https://github.com/python/cpython.git
synced 2025-10-09 16:34:44 +00:00
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.
This commit is contained in:
parent
3ec3ee7d2e
commit
4a42cebf6d
6 changed files with 21 additions and 11 deletions
|
@ -409,7 +409,7 @@ Power and logarithmic functions
|
||||||
.. function:: pow(x, y)
|
.. function:: pow(x, y)
|
||||||
|
|
||||||
Return ``x`` raised to the power ``y``. Exceptional cases follow
|
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
|
``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,
|
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)``
|
``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
|
its arguments to type :class:`float`. Use ``**`` or the built-in
|
||||||
:func:`pow` function for computing exact integer powers.
|
: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)
|
.. function:: sqrt(x)
|
||||||
|
|
||||||
|
|
|
@ -96,8 +96,14 @@ string. (Contributed by Sergey B Kirpichev in :issue:`44258`.)
|
||||||
math
|
math
|
||||||
----
|
----
|
||||||
|
|
||||||
Add :func:`math.cbrt()`: return the cube root of x.
|
* Add :func:`math.cbrt`: return the cube root of x.
|
||||||
(Contributed by Ajith Ramachandran in :issue:`44357`.)
|
(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
|
Removed
|
||||||
|
|
|
@ -104,7 +104,7 @@ infinity and NaN.
|
||||||
1.0
|
1.0
|
||||||
|
|
||||||
The power of 0 raised to x is defined as 0, if x is positive. Negative
|
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.
|
silent NaN.
|
||||||
|
|
||||||
>>> pow(0, 0)
|
>>> pow(0, 0)
|
||||||
|
@ -112,9 +112,7 @@ silent NaN.
|
||||||
>>> pow(0, INF)
|
>>> pow(0, INF)
|
||||||
0.0
|
0.0
|
||||||
>>> pow(0, -INF)
|
>>> pow(0, -INF)
|
||||||
Traceback (most recent call last):
|
inf
|
||||||
...
|
|
||||||
ValueError: math domain error
|
|
||||||
>>> 0 ** -1
|
>>> 0 ** -1
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
|
|
|
@ -1230,7 +1230,7 @@ class MathTests(unittest.TestCase):
|
||||||
self.assertRaises(ValueError, math.pow, 0., -2.)
|
self.assertRaises(ValueError, math.pow, 0., -2.)
|
||||||
self.assertRaises(ValueError, math.pow, 0., -2.3)
|
self.assertRaises(ValueError, math.pow, 0., -2.3)
|
||||||
self.assertRaises(ValueError, math.pow, 0., -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)))
|
self.assertTrue(math.isnan(math.pow(0., NAN)))
|
||||||
|
|
||||||
# pow(INF, x)
|
# 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.)
|
||||||
self.assertRaises(ValueError, math.pow, -0., -2.3)
|
self.assertRaises(ValueError, math.pow, -0., -2.3)
|
||||||
self.assertRaises(ValueError, math.pow, -0., -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)))
|
self.assertTrue(math.isnan(math.pow(-0., NAN)))
|
||||||
|
|
||||||
# pow(NINF, x)
|
# pow(NINF, x)
|
||||||
|
|
|
@ -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.
|
|
@ -2810,8 +2810,6 @@ math_pow_impl(PyObject *module, double x, double y)
|
||||||
r = y;
|
r = y;
|
||||||
else if (y < 0. && fabs(x) < 1.0) {
|
else if (y < 0. && fabs(x) < 1.0) {
|
||||||
r = -y; /* result is +inf */
|
r = -y; /* result is +inf */
|
||||||
if (x == 0.) /* 0**-inf: divide-by-zero */
|
|
||||||
errno = EDOM;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
r = 0.;
|
r = 0.;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue