Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In what cases does Python complex exponentiation throw an OverflowError?

I’m trying to figure out the pattern here:

>>> 1e300 ** 2
OverflowError: (34, 'Result too large')
>>> 1e300j ** 2
OverflowError: complex exponentiation
>>> (1e300 + 1j) ** 2
OverflowError: complex exponentiation
>>> (1e300 + 1e300j) ** 2
(nan+nanj)

The behavior seems to be not only unspecified in theory, but also weird in practice! What explains this?

like image 833
Jason Orendorff Avatar asked Jan 12 '23 15:01

Jason Orendorff


1 Answers

A look at the source for complex exponentiation shows that Python only checks for overflow at the end of the computation. Also, there's a special case for small integer exponents that uses exponentiation by squaring, which involves complex multiplication.

r.real = a.real*b.real - a.imag*b.imag;
r.imag = a.real*b.imag + a.imag*b.real;

This is the formula for complex multiplication. Note the following:

a.real*b.real - a.imag*b.imag

When a and b are very large, this becomes floating-point infinity minus floating-point infinity, which is nan. The nan results propagate, and after a few operations, the result is (nan+nanj). Py_ADJUST_ERANGE2 only sets errno if it sees an infinity, so it misses the overflow and goes on its way.

In summary, Python only checks the end result for overflow, not intermediate values, and this causes it to miss the overflow in the middle because it's all nans by the end. The expressions that do raise OverflowError do so because they never try to subtract infinities, so the error is spotted by the end. It doesn't look like a deliberate design decision; you could fix it by changing the way the overflow check works.

like image 78
user2357112 supports Monica Avatar answered Jan 16 '23 02:01

user2357112 supports Monica