Skip to content
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 single algorithm for complex power (case of small integer exponents was
handled before by a special method). 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