Skip to content

Commit 8a284e1

Browse files
authored
gh-119771: Set errno on overflows in _Py_c_pow() (#120256)
Before we did this in complex_pow() and behavior of the public C API function _Py_c_pow() was different from the pure-python pow().
1 parent 81480e6 commit 8a284e1

File tree

4 files changed

+12
-2
lines changed

4 files changed

+12
-2
lines changed

Doc/c-api/complex.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ pointers. This is consistent throughout the API.
7979
If *num* is null and *exp* is not a positive real number,
8080
this method returns zero and sets :c:data:`errno` to :c:macro:`!EDOM`.
8181
82+
Set :c:data:`errno` to :c:macro:`!ERANGE` on overflows.
83+
8284
8385
Complex Numbers as Python Objects
8486
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Lib/test/test_capi/test_complex.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,11 @@ def test_py_c_pow(self):
226226

227227
self.assertEqual(_py_c_pow(0j, -1)[1], errno.EDOM)
228228
self.assertEqual(_py_c_pow(0j, 1j)[1], errno.EDOM)
229-
self.assertEqual(_py_c_pow(*[DBL_MAX+1j]*2)[0], complex(*[INF]*2))
229+
max_num = DBL_MAX+1j
230+
self.assertEqual(_py_c_pow(max_num, max_num),
231+
(complex(INF, INF), errno.ERANGE))
232+
self.assertEqual(_py_c_pow(max_num, 2),
233+
(complex(INF, INF), errno.ERANGE))
230234

231235

232236
def test_py_c_abs(self):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Set :data:`errno` in :c:func:`_Py_c_pow` on overflows. Patch by Sergey B
2+
Kirpichev.

Objects/complexobject.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@ _Py_c_pow(Py_complex a, Py_complex b)
173173
}
174174
r.real = len*cos(phase);
175175
r.imag = len*sin(phase);
176+
177+
_Py_ADJUST_ERANGE2(r.real, r.imag);
176178
}
177179
return r;
178180
}
@@ -567,12 +569,12 @@ complex_pow(PyObject *v, PyObject *w, PyObject *z)
567569
// a faster and more accurate algorithm.
568570
if (b.imag == 0.0 && b.real == floor(b.real) && fabs(b.real) <= 100.0) {
569571
p = c_powi(a, (long)b.real);
572+
_Py_ADJUST_ERANGE2(p.real, p.imag);
570573
}
571574
else {
572575
p = _Py_c_pow(a, b);
573576
}
574577

575-
_Py_ADJUST_ERANGE2(p.real, p.imag);
576578
if (errno == EDOM) {
577579
PyErr_SetString(PyExc_ZeroDivisionError,
578580
"zero to a negative or complex power");

0 commit comments

Comments
 (0)