Skip to content

Commit

Permalink
pythongh-119771: adjust errno on overflows in _Py_c_pow()
Browse files Browse the repository at this point in the history
Before we did this in complex_pow() and behaviour of the public C API
function ``_Py_c_pow()`` was different from the pure-python pow().
  • Loading branch information
skirpichev committed Jun 8, 2024
1 parent 5c02ea8 commit d09fb10
Show file tree
Hide file tree
Showing 4 changed files with 11 additions and 2 deletions.
2 changes: 2 additions & 0 deletions Doc/c-api/complex.rst
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ pointers. This is consistent throughout the API.
If *num* is null and *exp* is not a positive real number,
this method returns zero and sets :c:data:`errno` to :c:macro:`!EDOM`.
Set :c:data:`errno` to :c:macro:`!ERANGE` on overflows.
Complex Numbers as Python Objects
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
5 changes: 4 additions & 1 deletion Lib/test/test_capi/test_complex.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,10 @@ def test_py_c_pow(self):

self.assertEqual(_py_c_pow(0j, -1)[1], errno.EDOM)
self.assertEqual(_py_c_pow(0j, 1j)[1], errno.EDOM)
self.assertEqual(_py_c_pow(*[DBL_MAX+1j]*2)[0], complex(*[INF]*2))
self.assertEqual(_py_c_pow(*[DBL_MAX+1j]*2),
(complex(*[INF]*2), errno.ERANGE))
self.assertEqual(_py_c_pow(DBL_MAX+1j, 2),
(complex(*[INF]*2), errno.ERANGE))


def test_py_c_abs(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Set :data:`errno` in :c:func:`_Py_c_pow` on overflows. Patch by Sergey B
Kirpichev.
4 changes: 3 additions & 1 deletion Objects/complexobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ _Py_c_pow(Py_complex a, Py_complex b)
}
r.real = len*cos(phase);
r.imag = len*sin(phase);

_Py_ADJUST_ERANGE2(r.real, r.imag);
}
return r;
}
Expand Down Expand Up @@ -546,12 +548,12 @@ complex_pow(PyObject *v, PyObject *w, PyObject *z)
// a faster and more accurate algorithm.
if (b.imag == 0.0 && b.real == floor(b.real) && fabs(b.real) <= 100.0) {
p = c_powi(a, (long)b.real);
_Py_ADJUST_ERANGE2(p.real, p.imag);
}
else {
p = _Py_c_pow(a, b);
}

_Py_ADJUST_ERANGE2(p.real, p.imag);
if (errno == EDOM) {
PyErr_SetString(PyExc_ZeroDivisionError,
"zero to a negative or complex power");
Expand Down

0 comments on commit d09fb10

Please sign in to comment.