You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
cmath.log(0, base) returns (-inf+nanj) instead of raising ValueError #161972
cmath.log(0) raises ValueError, but cmath.log(0, base) returns a value such as (-inf+nanj) for most bases. In cmath_log_impl, the domain error from c_log(z) is stored in errno, and the second call c_log(base) resets errno to 0 before it is checked.
importcmath, mathcmath.log(0) # ValueError: math domain errorcmath.log(0, 2) # (-inf+nanj)cmath.log(0, -1) # (nan+infj)math.log(0, 2) # ValueError: expected a positive input
Expected: cmath.log(0, base) raises ValueError: math domain error, the same as cmath.log(0) and math.log(0, 2). A zero or one base already raises (cmath.log(2, 0), cmath.log(2, 1)), because there the error comes from the second call or from the division.
CPython versions tested on:
3.15, CPython main branch
Operating systems tested on:
Linux
Found while building a Lean 4 model of CPython (https://broyojo.com/python-formalization/). AI tools (Claude) helped investigate the findings and prepare this report. The examples were rerun on CPython 3.15.2 and main, and the report received technical review. Record: mathint-cmath-log-base-errno
Rather we should keep errno unmodified or save/restore it on success.
I suspect that changing this will probably break code.
Maybe, but I think it worth. We should keep in mind general rule for the cmath module, given in the comment (that might be exposed as an implementation detail like in the math module):
/* First, the C functions that do the real work. Each of the c_*
functions computes and returns the C99 Annex G recommended result
and also sets errno as follows: errno = 0 if no floating-point
exception is associated with the result; errno = EDOM if C99 Annex
G recommends raising divide-by-zero or invalid for this result; and
errno = ERANGE where the overflow floating-point signal should be
raised.
The C standard (hopefully) has no two-argument log() function, but it's nothing more than a quotient of two logarithms. If either argument is 0 - we have log(0) in one operands of the division, that raises the "divide-by-zero" exception. And it should be enabled for the whole quotient as well.
In fact, sometimes such return values might be helpful, see #133895. But that's a separate feature request.
We should only decide whether the current behavior must be deprecated first. IMO, it's better just fix things. It's a bug.
I'd like to take this on. cmath.log(0) raises ValueError, but cmath.log(0, base) returns (-inf+nanj) because the second c_log(base) call resets errno before it's checked. I'm working on a fix in cmath_log_impl plus a regression test.
@tanveer-arch please go ahead, I won't open a PR for this one. Following @skirpichev's suggestion to fix it in c_log() makes sense. In case it helps with the test: besides cmath.log(0, 2), I'd check bases -1 and 1j (which currently give (nan+infj)), 0j/-0.0/complex(-0.0, -0.0) as the argument, inf and nan bases, and that cmath.log(2, 0), cmath.log(2, 1) and a non-numeric base keep their current errors.
Activity
ZeroIntensity commentedon Nov 14, 2026
cc @skirpichev
I suspect that changing this will probably break code.
skirpichev commentedon Nov 14, 2026
This is because of incorrect working with
errnoin thec_log()helper:cpython/Modules/cmathmodule.c
Line 637 in 9b633f5
Rather we should keep
errnounmodified or save/restore it on success.Maybe, but I think it worth. We should keep in mind general rule for the cmath module, given in the comment (that might be exposed as an implementation detail like in the math module):
cpython/Modules/cmathmodule.c
Lines 157 to 163 in 9b633f5
The C standard (hopefully) has no two-argument log() function, but it's nothing more than a quotient of two logarithms. If either argument is 0 - we have log(0) in one operands of the division, that raises the "divide-by-zero" exception. And it should be enabled for the whole quotient as well.
In fact, sometimes such return values might be helpful, see #133895. But that's a separate feature request.
We should only decide whether the current behavior must be deprecated first. IMO, it's better just fix things. It's a bug.
CC @mdickinson
tanveer-arch commentedon Nov 14, 2026
I'd like to take this on. cmath.log(0) raises ValueError, but cmath.log(0, base) returns (-inf+nanj) because the second c_log(base) call resets errno before it's checked. I'm working on a fix in cmath_log_impl plus a regression test.
Broyojo commentedon Nov 14, 2026
@tanveer-arch please go ahead, I won't open a PR for this one. Following @skirpichev's suggestion to fix it in
c_log()makes sense. In case it helps with the test: besidescmath.log(0, 2), I'd check bases-1and1j(which currently give(nan+infj)),0j/-0.0/complex(-0.0, -0.0)as the argument, inf and nan bases, and thatcmath.log(2, 0),cmath.log(2, 1)and a non-numeric base keep their current errors.pythongh-161972: Fix cmath.log(0, base) in c_log() instead of cmath_l…