Skip to content

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

Merged
merged 26 commits into from
Apr 28, 2025

Conversation

skirpichev
Copy link
Member

@skirpichev skirpichev commented Feb 22, 2025

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.


@skirpichev skirpichev force-pushed the fix-nan-packing/130317 branch from a6e99f9 to 971fd98 Compare February 23, 2025 03:15
@skirpichev skirpichev marked this pull request as ready for review February 23, 2025 03:53
vstinner

This comment was marked as outdated.

@skirpichev

This comment was marked as outdated.

@skirpichev skirpichev marked this pull request as draft February 25, 2025 06:04
@skirpichev skirpichev changed the title gh-130317: fix PyFloat_Pack2/Unpack2 for NaN's with payload gh-130317: fix PyFloat_Pack/Unpack[24] for NaN's with payload Feb 25, 2025
@skirpichev skirpichev force-pushed the fix-nan-packing/130317 branch from 139501d to e6c1c12 Compare February 25, 2025 08:24
@skirpichev skirpichev marked this pull request as ready for review February 25, 2025 09:12
@skirpichev
Copy link
Member Author

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.

@skirpichev skirpichev requested a review from vstinner February 25, 2025 09:16
@vstinner
Copy link
Member

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?

@skirpichev
Copy link
Member Author

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.

@skirpichev skirpichev force-pushed the fix-nan-packing/130317 branch 2 times, most recently from 05a1528 to 98b6947 Compare April 27, 2025 12:20
@skirpichev skirpichev force-pushed the fix-nan-packing/130317 branch from 98b6947 to 6137c75 Compare April 27, 2025 13:07
@skirpichev skirpichev marked this pull request as ready for review April 27, 2025 13:10
@skirpichev
Copy link
Member Author

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 (PyFloat_Unpack*).

@skirpichev skirpichev requested a review from vstinner April 27, 2025 15:18
@skirpichev skirpichev requested a review from vstinner April 28, 2025 11:57
Copy link
Member

@vstinner vstinner left a 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):
Copy link
Member

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?

Suggested change
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.

Copy link
Member Author

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>
@vstinner vstinner merged commit 6157135 into python:main Apr 28, 2025
42 checks passed
@vstinner
Copy link
Member

Merged, thank you.

@vstinner
Copy link
Member

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.

@skirpichev skirpichev deleted the fix-nan-packing/130317 branch April 28, 2025 13:29
@skirpichev
Copy link
Member Author

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).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants