diff --git a/Lib/test/test_complex.py b/Lib/test/test_complex.py index ecc97315e50d31..40d804ed37823a 100644 --- a/Lib/test/test_complex.py +++ b/Lib/test/test_complex.py @@ -338,6 +338,11 @@ def test_pow(self): except OverflowError: pass + # Check that complex numbers with special components + # are correctly handled. + self.assertComplexesAreIdentical(complex(1, +0.0)**2, complex(1, +0.0)) + self.assertComplexesAreIdentical(complex(1, -0.0)**2, complex(1, -0.0)) + def test_pow_with_small_integer_exponents(self): # Check that small integer exponents are handled identically # regardless of their type. diff --git a/Misc/NEWS.d/next/Library/2024-08-24-10-46-35.gh-issue-117999.5K_BiA.rst b/Misc/NEWS.d/next/Library/2024-08-24-10-46-35.gh-issue-117999.5K_BiA.rst new file mode 100644 index 00000000000000..2e3c45ad97215f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-08-24-10-46-35.gh-issue-117999.5K_BiA.rst @@ -0,0 +1,2 @@ +Use a single algorithm for complex exponentiation (the case where the exponent +is a small integer was previously handled separately). Patch by Sergey B Kirpichev. diff --git a/Objects/complexobject.c b/Objects/complexobject.c index 787235c63a6be1..b996844a2029f4 100644 --- a/Objects/complexobject.c +++ b/Objects/complexobject.c @@ -23,8 +23,6 @@ class complex "PyComplexObject *" "&PyComplex_Type" /* elementary operations on complex numbers */ -static Py_complex c_1 = {1., 0.}; - Py_complex _Py_c_sum(Py_complex a, Py_complex b) { @@ -179,32 +177,6 @@ _Py_c_pow(Py_complex a, Py_complex b) return r; } -static Py_complex -c_powu(Py_complex x, long n) -{ - Py_complex r, p; - long mask = 1; - r = c_1; - p = x; - while (mask > 0 && n >= mask) { - if (n & mask) - r = _Py_c_prod(r,p); - mask <<= 1; - p = _Py_c_prod(p,p); - } - return r; -} - -static Py_complex -c_powi(Py_complex x, long n) -{ - if (n > 0) - return c_powu(x,n); - else - return _Py_c_quot(c_1, c_powu(x,-n)); - -} - double _Py_c_abs(Py_complex z) { @@ -565,16 +537,7 @@ complex_pow(PyObject *v, PyObject *w, PyObject *z) return NULL; } errno = 0; - // Check whether the exponent has a small integer value, and if so use - // 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); - } - + p = _Py_c_pow(a, b); if (errno == EDOM) { PyErr_SetString(PyExc_ZeroDivisionError, "zero to a negative or complex power");