Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-117999: use generic algorithm in complex_pow() if base has special components #123283

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
5 changes: 5 additions & 0 deletions Lib/test/test_complex.py
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,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.
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
38 changes: 1 addition & 37 deletions Objects/complexobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -177,32 +175,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)
{
Expand Down Expand Up @@ -563,15 +535,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);
}
else {
p = _Py_c_pow(a, b);
}

p = _Py_c_pow(a, b);
_Py_ADJUST_ERANGE2(p.real, p.imag);
if (errno == EDOM) {
PyErr_SetString(PyExc_ZeroDivisionError,
Expand Down
Loading