Skip to content

gh-156693: correct complex powers with infinite bases - #156694

Closed
skirpichev wants to merge 19 commits into
python:mainfrom
skirpichev:fix-cpow-overflows/156693
Closed

gh-156693: correct complex powers with infinite bases#156694
skirpichev wants to merge 19 commits into
python:mainfrom
skirpichev:fix-cpow-overflows/156693

Conversation

@skirpichev

@skirpichev skirpichev commented Aug 31, 2026

Copy link
Copy Markdown
Member

Now we raise OverflowError's only if infinite result (i.e. cmath.isinf(result) is True) come from finite input.

This patch also adds private inline functions _Py_c_iszero(), _Py_c_isnan(), _Py_c_isinf() and _Py_c_isfinite().

Now we raise OverflowError's only if infinite result (i.e.
cmath.isinf(result) is True) come from finite input.  As proposed in
issue python#156145, we don't use platforms `errno` to manage exceptions
anymore.

This patch also adds private API functions `_Py_c_isnan()`,
`_Py_c_isinf()` and `_Py_c_isfinite()`.
@skirpichev

Copy link
Copy Markdown
Member Author

CC @serhiy-storchaka

I think this will be less controversial change vs #118000 or #124243. Anyway, I think it worth for a dedicated commit.

@skirpichev

Copy link
Copy Markdown
Member Author

CC @hpkfft

Comment thread Objects/complexobject.c
Comment thread Include/internal/pycore_complexobject.h Outdated
Comment thread Misc/NEWS.d/next/Core_and_Builtins/2026-08-31-07-33-05.gh-issue-156693.BuDcDc.rst Outdated
Comment thread Objects/complexobject.c
@bedevere-app

bedevere-app Bot commented Sep 1, 2026

Copy link
Copy Markdown

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

@skirpichev

Copy link
Copy Markdown
Member Author

I have made the requested changes; please review again

@bedevere-app

bedevere-app Bot commented Sep 1, 2026

Copy link
Copy Markdown

Thanks for making the requested changes!

@eendebakpt: please review the changes made to this pull request.

@eendebakpt eendebakpt left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more caseswhere the behavior changes: (1e-200+0j)**-2 (it would not happen under #156695, but that is not merged yet).

And can you add a test for complex(inf)**1j?

Comment thread Misc/NEWS.d/next/Core_and_Builtins/2026-08-31-07-33-05.gh-issue-156693.BuDcDc.rst Outdated
@skirpichev

Copy link
Copy Markdown
Member Author

One more caseswhere the behavior changes: (1e-200+0j)**-2

Indeed, I believe now all should be fixed.

I'll not add a test, though, because this behavior can be changed by #156695.

And can you add a test for complex(inf)**1j?

Done.

Last commit removes special handling for some corner cases, that's optional. Let me know if you prefer to keep this.

@skirpichev
skirpichev force-pushed the fix-cpow-overflows/156693 branch from 8e7ff19 to 935b0e6 Compare September 2, 2026 02:02
@eendebakpt

Copy link
Copy Markdown
Contributor

With your latest iteration: what about (0j)**complex(INF), (1e-200+0j)**-2 and _Py_c_pow(nan+0j, 0+0j) (C API)?

@skirpichev
skirpichev marked this pull request as draft September 2, 2026 10:41
@skirpichev skirpichev self-assigned this Sep 2, 2026
@hpkfft

hpkfft commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

In my opinion, anybody calling _Py_c_pow() (e.g., Numba) should get the same results as a Python developer calling pow(). The latter has an optimization for small integer exponents. Numba should be allowed to benefit from that.

You're welcome to look at my work-in-progress: hpkfft#1
I deleted c_powu(). Now, complex_pow() only calls c_pow() and raises a Python error if necessary. The C API function _Py_c_pow() also calls c_pow() and sets errno if necessary. If small integer exponent, c_pow() calls c_powi(), so the C API and the Python API give the same results.

@skirpichev

Copy link
Copy Markdown
Member Author

In my opinion, anybody calling _Py_c_pow() (e.g., Numba) should get the same results as a Python developer calling pow().

Anyone, calling _Py_c_pow() should be aware, that it's a soft-deprecated interface.

We decided to not provide low-level primitives, that works same as complex arithmetics in the Python. You can use either PyNumber_* API or some external library code (e.g. like GNU GSL) and/or C types (e.g. double _Complex, if available).

You're welcome to look at my work-in-progress: hpkfft#1

Thanks, but I'll try to limit this PR just for a bugfix.

IMO, cleanest alternative to using errno is floating-point exceptions. Though, my tests shows that this come with a severe speed loss. Lets decide on this later.

@skirpichev
skirpichev marked this pull request as ready for review September 3, 2026 03:00
@skirpichev

Copy link
Copy Markdown
Member Author

Ah, it seems that added complex('inf')**1j test is still in mercy of platforms libm. Test pass for me, but breaks CI. I'll revert it.

BTW, I'm not sure that ZeroDivisionError is a right thing here. On latest gmpy2:

>>> from gmpy2 import *
>>> get_context().trap_divzero = True
>>> mpc('inf')**mpc(1j)
mpc('nan+nanj')
>>> get_context()
context(precision=53, real_prec=Default, imag_prec=Default,
        round=RoundToNearest, real_round=Default, imag_round=Default,
        emax=1073741823, emin=-1073741823,
        subnormalize=False,
        trap_underflow=False, underflow=False,
        trap_overflow=False, overflow=False,
        trap_inexact=False, inexact=False,
        trap_invalid=False, invalid=True,
        trap_erange=False, erange=False,
        trap_divzero=True, divzero=False,
        allow_complex=False,
        rational_division=False,
        allow_release_gil=False)

@hpkfft

hpkfft commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

I'm not sure that ZeroDivisionError is a right thing here.

My preference would be ZeroDivisionError only if base is zero and exp is not a positive real number.
The following seems obviously wrong:

>>> import math
>>> c = complex(math.inf)
>>> c**1j
Traceback (most recent call last):
  File "<python-input-7>", line 1, in <module>
    c**1j
    ~^^~~
ZeroDivisionError: 0.0 to a negative or complex power

@serhiy-storchaka

Copy link
Copy Markdown
Member

Opened #156886 for ZeroDivisionError.

@eendebakpt

Copy link
Copy Markdown
Contributor

@skirpichev Do you plan to followup on this PR? Some of the added tests seem worthwhile to have in any case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants