mirror of https://github.com/python/cpython
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().
This commit is contained in:
parent
81480e6edb
commit
8a284e1896
|
@ -79,6 +79,8 @@ pointers. This is consistent throughout the API.
|
||||||
If *num* is null and *exp* is not a positive real number,
|
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`.
|
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
|
Complex Numbers as Python Objects
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
@ -226,7 +226,11 @@ class CAPIComplexTest(unittest.TestCase):
|
||||||
|
|
||||||
self.assertEqual(_py_c_pow(0j, -1)[1], errno.EDOM)
|
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(0j, 1j)[1], errno.EDOM)
|
||||||
self.assertEqual(_py_c_pow(*[DBL_MAX+1j]*2)[0], complex(*[INF]*2))
|
max_num = DBL_MAX+1j
|
||||||
|
self.assertEqual(_py_c_pow(max_num, max_num),
|
||||||
|
(complex(INF, INF), errno.ERANGE))
|
||||||
|
self.assertEqual(_py_c_pow(max_num, 2),
|
||||||
|
(complex(INF, INF), errno.ERANGE))
|
||||||
|
|
||||||
|
|
||||||
def test_py_c_abs(self):
|
def test_py_c_abs(self):
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Set :data:`errno` in :c:func:`_Py_c_pow` on overflows. Patch by Sergey B
|
||||||
|
Kirpichev.
|
|
@ -173,6 +173,8 @@ _Py_c_pow(Py_complex a, Py_complex b)
|
||||||
}
|
}
|
||||||
r.real = len*cos(phase);
|
r.real = len*cos(phase);
|
||||||
r.imag = len*sin(phase);
|
r.imag = len*sin(phase);
|
||||||
|
|
||||||
|
_Py_ADJUST_ERANGE2(r.real, r.imag);
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -567,12 +569,12 @@ complex_pow(PyObject *v, PyObject *w, PyObject *z)
|
||||||
// a faster and more accurate algorithm.
|
// a faster and more accurate algorithm.
|
||||||
if (b.imag == 0.0 && b.real == floor(b.real) && fabs(b.real) <= 100.0) {
|
if (b.imag == 0.0 && b.real == floor(b.real) && fabs(b.real) <= 100.0) {
|
||||||
p = c_powi(a, (long)b.real);
|
p = c_powi(a, (long)b.real);
|
||||||
|
_Py_ADJUST_ERANGE2(p.real, p.imag);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
p = _Py_c_pow(a, b);
|
p = _Py_c_pow(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
_Py_ADJUST_ERANGE2(p.real, p.imag);
|
|
||||||
if (errno == EDOM) {
|
if (errno == EDOM) {
|
||||||
PyErr_SetString(PyExc_ZeroDivisionError,
|
PyErr_SetString(PyExc_ZeroDivisionError,
|
||||||
"zero to a negative or complex power");
|
"zero to a negative or complex power");
|
||||||
|
|
Loading…
Reference in New Issue