Currently we compute such powers as (1+0j)/z**(-n) (unless absolute value of n is too big to use specialized algorithm for integer exponents). This approach, however, introduce huge accuracy loss due to underflows in division.
For example:
>>> from gmpy2 import*
>>> import math
>>> x, y =map(float.fromhex, ['0x1.47e9c711723f5p+81',
... '0x1.38afd1168e49fp+85'])
>>> z =complex(x, y)
>>> pr =pow(z, -12); pr
0j
>>> pr2 =pow((1/z), 12); pr2
(5.562684646267994e-309+5.56268464626799e-309j)
>>> gr =complex(pow(mpc(z), -12))
>>> abs((pr2-gr).real)/math.ulp(gr.real)
2.0
>>> abs((pr2-gr).imag)/math.ulp(gr.imag)
2.0
Using instead ((1+0j)/z)**(-n) reduced error in this example from ~1e15 ULP to 2ULP. Note that, generic power algorithm is not affected by this issue:
There is also the case when x**|n| underflows to zero:
>>> (1e-161+0j)**-2
Traceback (most recent call last):
...
OverflowError: complex exponentiation
>>> (1e-162+0j)**-2
Traceback (most recent call last):
...
ZeroDivisionError: zero to a negative or complex power
OverflowError is correct in both cases, the base is not zero. The scaling in #156757 would give it, but it is skipped here because of the errno != EDOM condition.
Activity
pythongh-156695: Improve accuracy of complex powers with small negati…
serhiy-storchaka commented on Sep 3, 2026
There is also the case when x**|n| underflows to zero:
OverflowError is correct in both cases, the base is not zero. The scaling in #156757 would give it, but it is skipped here because of the errno != EDOM condition.