gh-153144: Avoid checking errno for atan2 - #153148
Conversation
|
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
|
If this PR is merged, it looks to me like #146402 can (and should) be reverted. |
skirpichev
left a comment
There was a problem hiding this comment.
No, I doubt that this is a right approach. We must handle error in same way for all libm functions.
Perhaps, m_atan2() (like m_log1p() we have currently) could be restored (see #122681) to workaround broken platform functions.
The mathmodule currently has 3 ways of handling 1-argument libm functions:
Maybe it's not so bad to have |
|
Perhaps, we could modify math_2() helper to check that errno!=EDOM, if inputs and output are finite. When domain error occurs - result should be nan. But I think that a little wrapper for libm's atan2 is better, if we are going to add some workaround for the given issue. |
skirpichev
left a comment
There was a problem hiding this comment.
Please revert unrelated changes.
|
@vstinner, can you look at this at your convenience? |
| errno = 0; | ||
| phi = atan2(z.imag, z.real); /* should not cause any exception */ | ||
| if (errno != 0) | ||
| return math_error(); |
There was a problem hiding this comment.
I expected a test_cmath failure when this code path is removed. Is it because glibc math library doesn't errno in this case?
There was a problem hiding this comment.
Yes. With the exception of the Intel and Solaris math libraries, errno is not set in this case by any math library that Python cares about. I say this because test_phase in Lib/test/test_cmath.py has asserted that return values are correct since Python 3.14, and nobody has complained. If errno were set by the C math library, the unittest would fail with ValueError: math domain error.
🌱 Some math libraries (e.g., musl) don't set errno for anything, so Python cannot rely on errno for detecting overflow or invalid. I would think that errno checking can be removed everywhere....
|
You also could use new helper function for copysign. On another hand, I would prefer just remove errno stuff from math_2(), per #156145. It should be possible for all two-argument functions: atan2, atan2pi, copysign, remainder and fmod (which could utilize same wrapper). |
My thinking is only to do what is necessary to fix the bug (the incorrect results when building with Intel or Solaris math libraries). Then, I would recommend applying this fix to Python 3.14 and 3.15. With that in mind, I don't want to make any enhancements that are not necessary to fix the reported bug.
Yes, 156145 can have a more ambitious goal. Can you trigger the buildbots to run this PR? I am not able to check myself that it works on Solaris. (I do think it will work based on what I read in the Solaris bug report.) |
Then we loose chance of using new helper function for copysign().
!buildbot Solaris |
|
!buildbot Solaris |
|
🤖 New build scheduled with the buildbot fleet by @skirpichev for commit 5b6d005 🤖 Results will be shown at: https://buildbot.python.org/all/#/grid?branch=refs%2Fpull%2F153148%2Fmerge The command will test the builders whose names match following regular expression: The builders matched are:
|
OK, I'll add that commit tomorrow. Since it will be a separate commit, it can easily be reverted (or skipped when squashing all the commits before the final merge). The same is true for the comments Victor requested--they're in their own separate commit. |
|
I'm happy to see that the math and cmath tests pass on Solaris. |
|
Hi @StanFromIreland, Can you please advise whether I should create a separate bug report for an issue @serhiy-storchaka observed: or whether #153144 can be updated with this extra information? Note that #153144 affects the current version of the Intel math library and the Solaris math library, so it's correctly labelled |
|
Hum. It's uneasy for me to take a decision on this change. The bug report is about supporting Intel compiler (icx) which sets errno for atan2() and phase(). But the PR also changes cmath.phase() behavior on overflow and underflow of imag/real. I'm not sure if |
Python already returns the correct result, This PR changes cmath.phase() behavior on UNDERflow of imag/real (bug observed in #155527 (comment)). The C standard in 7.3.9.1 says:
Note that there's no possibility of overflow--the result is bounded. (The implementation may or may not actually perform a floating-point division of imag/real, but that's an implementation detail, and whether or not some intermediate calculation overflows must not affect what the user observes.) There is the possibility of underflow. The infinitely precise result of The result is too small to be represented in double precision, so it underflows to Python does not raise an exception on underflow, only on overflow. For example: I created the bug report because existing tests were failing when building Python with the Intel math library. I made this PR to ignore errno because I could see no reason for checking it, and I believed that not checking it was always correct. I did not stop to consider that the old code (checking errno) led to more Python bugs. After reading Serhiy's comment, I added tests to this PR and updated the NEWS. |
The C23 standard states that for
atan2andatan2pi:Since Python should not raise ValueError in either of these cases (i.e., when both arguments are zero or when the computation underflows), this PR avoids checking
errnowhen calling these trig functions. As a bonus,math.atan2()is about 4% faster.math.atan2(0.0, 0.0)andcmath.phase(0.0)using icx #153144The statement about range error in the standard should, I think, be interpreted as: