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
ValueError for math.atan2(0.0, 0.0) and cmath.phase(0.0) using icx #153144
The math function atan2 and the cmath function phase should not raise ValueError when their arguments are zero. This is true when building CPython using an officially supported compiler such as GCC:
The math function atan2 and the cmath function phase should not raise ValueError when their arguments are zero.
Why?
The C standard has no phase function, though it's just carg(), and here we have:
Errors and special cases are handled as if the function is implemented as atan2(cimag(z), creal(z))
In turn, you noted, that C standard says (long time ago in fact) for atan2:
A domain error may occur if both arguments are zero.
Also, in section 7.12.1:
On a domain error, the function returns an implementation-defined value; if the integer expression math_errhandling & MATH_ERRNO is nonzero, the integer expression errno acquires the value EDOM; if the integer expression math_errhandling & MATH_ERREXCEPT is nonzero, the "invalid" floating-point excep-
tion is raised.
That's interesting, because Annex F.10.1.4 also says:
atan2(0, 0) does not raise the "invalid" floating-point exception, nor does atan2(y, 0) raise the "divide-by-zero" floating-point exception.
So, assuming the icc supports Annex F nowadays - the described behavior looks as a compiler bug. Though, I don't think that icc defines some __STDC_IEC_60559_* macro. If so, I don't think we can count this as a platform bug and introduce some workaround (like ignoring errno).
The math/cmath modules should be thin wrappers over system libm. And in this case it's so: EDOM from the libm's function is correctly translated to the ValueError exception.
In general, on an IEEE-754 platform the aim is to follow the C99
standard, including Annex 'F', whenever possible. Where the
standard recommends raising the 'divide-by-zero' or 'invalid'
floating-point exceptions, Python should raise a ValueError. Where
the standard recommends raising 'overflow', Python should raise an
OverflowError. In all other circumstances a value should be
returned.
Using icx and the Intel math library, atan2(0, 0) returns the correct value. It also sets errno to EDOM. This appears to be allowed by the C standard. C programmers can look at errno or not, as they choose. What should Python do--would users prefer to get the result (the same result calculated by glibc) or get ValueError? That seems to be a choice that's up to Python to make.
What is the motivation for examining errno for atan2()? Is there a situation (on any platform with any compiler) in which Python does not want to return the floating-point result? [This is a genuine question. I don't know whether there's some platform with a math library that does something for atan2() that I have not considered.] On the other hand, if CPython is reading errno for atan2() and then ignoring it here and here, then it seems better not to read it in the first place (which is what this PR does).
If, philosophically, the math/cmath modules should be thin wrappers over system libm, then would you support changing the tests in Lib/test/test_math.py and Lib/test/test_cmath.py to allow ValueError as a correct result for atan2(0,0) and phase(0), respectively?
So, at least, the correct return value is unambiguous is Python prefers to always return a value regardless of whether the system/platform math library sets errno.
Is that true? Or, does Python instead strive to present consistent math functions regardless of the system?
Yes. You might try to convince people change this on the d.p.o (ideas). Good luck.
Using icx and the Intel math library, atan2(0, 0) returns the correct value. It also sets errno to EDOM.
What about floating-point exceptions?
What is the motivation for examining errno for atan2()?
We do this just as for other libm's functions. See e.g. math_1() wrapper. The atan2() just is not a special one.
Regarding the floating-point return value, Annex F specifies
Unfortunately, I suspect that the intel compiler doesn't announce support for that Annex.
If that was the case - it would be a platform bug, because:
"atan2(0, 0) does not raise the "invalid" floating-point exception"
but
"On a domain error, the function returns an implementation-defined value; if the integer expression math_errhandling & MATH_ERRNO is nonzero, the integer expression errno acquires the value EDOM; if the integer expression math_errhandling & MATH_ERREXCEPT is nonzero, the "invalid" floating-point exception is raised."
Using icx and the Intel math library, atan2(0, 0) returns the correct value. It also sets errno to EDOM.
What about floating-point exceptions?
The only floating-point exception (if it were unmasked) is INEXACT for when the infinitely precise result is Pi.
See compiler explorer
We do this just as for other libm's functions.
So, no reason? Just easier to re-use existing code?
The C standard allows setting errno to EDOM when both arguments are zero. Intel's math library does this.
The C standard does not allow atan2 to cause invalid nor divide-by-zero. Intel's math library does neither.
The C standard in Annex F prescribes return values when both arguments are zero. Intel's math library follows this.
You seem to be arguing that statements (1) and (2) imply that a math library CANNOT (according to the standard) set errno to EDOM. But the standard clearly says it's OK to do so.
I think (2) simply provides a general mechanism for converting a domain error to an invalid floating-point exception.
Probably, (1) should say "atan2(0, 0) does not itself raise the 'invalid' floating-point exception but general mechanisms for converting domain errors to the 'invalid' floating-point exception still apply"
I think it would be a mistake for Python's math.atan2 and cmath.phase to allow the compiler's math library's setting of errno to determine whether or not to raise ValueError when the functions' arguments are zero. Python's users would be better served by following the statement written in mathmodule.c, "Where the standard recommends raising the 'divide-by-zero' or 'invalid' floating-point exceptions, Python should raise a ValueError. Where the standard recommends raising 'overflow', Python should raise an OverflowError. In all other circumstances a value should be returned."
icx declares conformance to the Annex F, which says that no "invalid" exceptions should be reported. On another hand, it sets EDOM. But then it must raise an "invalid" exception if math_errhandling & MATH_ERREXCEPT is nonzero.
So, no reason?
Why we should handle errors differently?
You seem to be arguing that statements (1) and (2) imply that a math library CANNOT (according to the standard) set errno to EDOM.
Yeah, hmmm, indeed. I've been trying to interpret the C standard in such a way as to make the Intel math library (and the one from Sun Microsystems) compliant. I have failed. Since these libraries have been around for a while, one might guess it was the intention of the C standard to allow their atan(0,0) behavior. But that's just a guess. Regardless, I think the C standard could be improved to make the implications of Annex F clearer.
The math library in musl libc follows Annex F, and I confirmed (using gcc) that __STDC_IEC_559__ is defined.
Musl does not provide errno based error handling; math_errhandling is MATH_ERREXCEPT.
Activity
skirpichev commentedon Jul 6, 2026
Why?
The C standard has no phase function, though it's just carg(), and here we have:
In turn, you noted, that C standard says (long time ago in fact) for atan2:
Also, in section 7.12.1:
That's interesting, because Annex F.10.1.4 also says:
So, assuming the icc supports Annex F nowadays - the described behavior looks as a compiler bug. Though, I don't think that icc defines some
__STDC_IEC_60559_*macro. If so, I don't think we can count this as a platform bug and introduce some workaround (like ignoring errno).The math/cmath modules should be thin wrappers over system libm. And in this case it's so: EDOM from the libm's function is correctly translated to the ValueError exception.
hpkfft commentedon Jul 6, 2026
Is that true? Or, does Python instead strive to present consistent math functions regardless of the system?
cpython/Modules/mathmodule.c
Lines 46 to 52 in b175621
Using
icxand the Intel math library, atan2(0, 0) returns the correct value. It also setserrnotoEDOM. This appears to be allowed by the C standard. C programmers can look aterrnoor not, as they choose. What should Python do--would users prefer to get the result (the same result calculated by glibc) or get ValueError? That seems to be a choice that's up to Python to make.What is the motivation for examining
errnofor atan2()? Is there a situation (on any platform with any compiler) in which Python does not want to return the floating-point result? [This is a genuine question. I don't know whether there's some platform with a math library that does something for atan2() that I have not considered.] On the other hand, if CPython is readingerrnofor atan2() and then ignoring it here and here, then it seems better not to read it in the first place (which is what this PR does).If, philosophically, the math/cmath modules should be thin wrappers over system libm, then would you support changing the tests in
Lib/test/test_math.pyandLib/test/test_cmath.pyto allow ValueError as a correct result for atan2(0,0) and phase(0), respectively?hpkfft commentedon Jul 6, 2026
Regarding the floating-point return value, Annex F specifies
So, at least, the correct return value is unambiguous is Python prefers to always return a value regardless of whether the system/platform math library sets
errno.skirpichev commentedon Jul 6, 2026
Yes. You might try to convince people change this on the d.p.o (ideas). Good luck.
What about floating-point exceptions?
We do this just as for other libm's functions. See e.g. math_1() wrapper. The atan2() just is not a special one.
Unfortunately, I suspect that the intel compiler doesn't announce support for that Annex.
If that was the case - it would be a platform bug, because:
but
See #138573 for a similar issue.
hpkfft commentedon Jul 6, 2026
The only floating-point exception (if it were unmasked) is INEXACT for when the infinitely precise result is Pi.
See compiler explorer
So, no reason? Just easier to re-use existing code?
The C standard allows setting
errnotoEDOMwhen both arguments are zero. Intel's math library does this.The C standard does not allow atan2 to cause invalid nor divide-by-zero. Intel's math library does neither.
The C standard in Annex F prescribes return values when both arguments are zero. Intel's math library follows this.
You seem to be arguing that statements (1) and (2) imply that a math library CANNOT (according to the standard) set
errnotoEDOM. But the standard clearly says it's OK to do so.I think (2) simply provides a general mechanism for converting a domain error to an invalid floating-point exception.
Probably, (1) should say "atan2(0, 0) does not itself raise the 'invalid' floating-point exception but general mechanisms for converting domain errors to the 'invalid' floating-point exception still apply"
I think it would be a mistake for Python's
math.atan2andcmath.phaseto allow the compiler's math library's setting oferrnoto determine whether or not to raise ValueError when the functions' arguments are zero. Python's users would be better served by following the statement written inmathmodule.c, "Where the standard recommends raising the 'divide-by-zero' or 'invalid' floating-point exceptions, Python should raise a ValueError. Where the standard recommends raising 'overflow', Python should raise an OverflowError. In all other circumstances a value should be returned."skirpichev commentedon Jul 7, 2026
Hmm, indeed. I did additional tests and now it looks as a bug for me: https://godbolt.org/z/Teqvfvaq5
icx declares conformance to the Annex F, which says that no "invalid" exceptions should be reported. On another hand, it sets EDOM. But then it must raise an "invalid" exception if math_errhandling & MATH_ERREXCEPT is nonzero.
Why we should handle errors differently?
Yes, if it conforms to the Annex F.
hpkfft commentedon Jul 7, 2026
Yeah, hmmm, indeed. I've been trying to interpret the C standard in such a way as to make the Intel math library (and the one from Sun Microsystems) compliant. I have failed. Since these libraries have been around for a while, one might guess it was the intention of the C standard to allow their atan(0,0) behavior. But that's just a guess. Regardless, I think the C standard could be improved to make the implications of Annex F clearer.
skirpichev commentedon Jul 7, 2026
BTW, this issue should be reported to Intel.
hpkfft commentedon Jul 7, 2026
I've reported it unofficially. (I used to work in the numerics team at Intel.)
hpkfft commentedon Jul 8, 2026
The math library in musl libc follows Annex F, and I confirmed (using gcc) that
__STDC_IEC_559__is defined.Musl does not provide errno based error handling;
math_errhandlingisMATH_ERREXCEPT.pythongh-153144: Added NEWS entry
pythongh-153144: Modify comments as requested in review
skirpichev commentedon Aug 16, 2026
FYI: https://discuss.python.org/t/out-of-range-error-when-building-python-3-14-7-with-gcc-16-2-0/108539/13