-
-
Notifications
You must be signed in to change notification settings - Fork 31.7k
gh-130317: fix PyFloat_Pack/Unpack[24] for NaN's with payload #130452
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
7da9a1f
to
a6e99f9
Compare
a6e99f9
to
971fd98
Compare
This comment was marked as outdated.
This comment was marked as outdated.
139501d
to
e6c1c12
Compare
Ok, I've added new tests in test_capi.test_floats (in principle, test_struct's tests are redundant). win32 behavior (you can't unset "quiet" bit for NaN) looks as a bug for me. |
Any idea why there is a bug only on Windows? |
Only on win32. Though, I suspect the situation could be worse. Maybe I should revert win32-workaround and test this with some buildbots? C17 says: "This specification does not define the behavior of signaling NaNs." But I don't think this means you can't flip appropriate bit in float/double to make a signaling NaN. |
05a1528
to
98b6947
Compare
98b6947
to
6137c75
Compare
Ok, I think it's ready for review. Test for Windows failed in 32-bit mode (signaling NaN type not preserved in roundtrip), that seems to be a known issue: https://developercommunity.visualstudio.com/t/155064 (sNaN returned from function becomes qNaN). See also https://developercommunity.visualstudio.com/t/903305 and https://en.delphipraxis.net/topic/12198-delphi-win32-quiets-signaling-nan-on-function-return/. In principle, it's possible to workaround this for the struct module. But not for C-API ( |
Co-authored-by: Victor Stinner <vstinner@python.org>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. I just have some minor comments.
def test_pack_unpack_roundtrip_for_nans(self): | ||
pack = _testcapi.float_pack | ||
unpack = _testcapi.float_unpack | ||
for _ in range(1000): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
100 tests should be enough to validate the implementation, no?
for _ in range(1000): | |
for _ in range(100): |
1000 tests might be a little bit too slow, I don't think that it's worth it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Up to you, the test looks instantaneous on my system. 0.3sec vs 0.03. Where the threshold?
Co-authored-by: Victor Stinner <vstinner@python.org>
Merged, thank you. |
Should we backport this change? It's unclear to me if it's a new feature or a bugfix. The issue is reported as a bug report. |
Strictly speaking, it's a bug, though maybe a very minor one (that's why there was no label for 3.13 backport). From IEEE 754 (2008), 6.2.3: "Conversion of a quiet NaN from a narrower format to a wider format in the same radix, and then back to the same narrower format, should not change the quiet NaN payload in any way except to make it canonical." E.g. in C nan's payload is preserved in conversions (e.g. float->double) or partially preserved (e.g. double -> float). |
Previously (1) all NaN's payload in PyFloat_Pack/Unpack2() was ignored and (2) type conversions (float <-> double) in PyFloat_Pack/Unpack4() broke pack-unpack round-trip for sNaN's.
nan
floats is non-invertible #130317