-
-
Notifications
You must be signed in to change notification settings - Fork 30.4k
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
IEEE floating point signalling bit can be inverted on MIPS (Python assumes its not) #104263
Comments
Repeating and clarifying some comments from the PR: Replacing
But with the proposed change we'd get instead (at least on my machine):
(And yes, people shouldn't care about signs on NaNs, but I guarantee that there would be bug reports if this changed.) Could we look for solutions that only affect MIPS? E.g., a preprocessor define (we could either have something indirect that tells us that the meaning of bit 51 is inverted from its usual meaning, or we could have a FWIW, CPython is now requiring that |
How come My assumption here is that I am very surprised by the above sign issue and I would suggest rather adding a test for If CPython requires IEEE 754 float format now, then the PR is just a step in the right direction of removing unnecessarily confusing code. Or am I missing something? |
Because on Intel 64 machines, that's what the default NaN is. It's exactly this sort of machine dependence I'd like to get away from, which is why I'd prefer to move away from
Why would it be? |
N.B. The right way to do this in new code, now that we're able to rely both on IEEE 754 |
True, but I would argue it is better to do that via testing the desired behavior if we must:
My poin is that more than half of even caring to touch this code for me was that it seems like you can remove ~200 lines of code and a layer of complexity that seems to serves no purpose anymore but to be subtly buggy. Adding a "quiet NaN bit has reverse meaning" flag would add another layer of confusion instead. I don't really see the unexpected sign bit on my computer or https://godbolt.org/z/Eqv78Gz8Y, although I do believe you that it happens on some platforms even without What I do wonder if you really want the So if you say the right way is to use |
Btw. I didn't care about backporting. If we want to backport this, then I agree the fix should probably just be some weird |
It's definitely true that the current code isn't as clean as it could be, mostly for historical and lack-of-cycles reasons (dating from days when we couldn't even assume that NaNs and infinities existed at all on the target platform); I agree it would be good to clean it up. People do notice signs of NaNs and complain when they change; I do think we need to avoid changing those. I could be persuaded that no-one notices or cares about payloads, given that to the best of my knowledge modern systems don't bother setting interesting payloads anyway. (Apple's SANE did make use of payloads, but that was some time and some number of architectures ago ...). Taking things out of order a bit:
Huh, that's interesting. Looks like
Fair enough.
Yes please.
Let's not bother. Unlike signs, I don't have any evidence that anyone cares about payloads in real life. And if we're using
Again I wouldn't bother, mostly because we're at the mercy of the CPU/FPU here. We either accept that we'll get differently-signed results on different systems, or we try to force the sign of the result by adding code to check whether the subtraction result is a NaN and replace it with our own NaN if so. The latter doesn't seem like a good use of cycles, and would be a needless behaviour change.
It doesn't actually matter, because those
But if it weren't for the above, I don't see as strong a need for standardisation of the returned NaN from those math functions as I do for
That could work. I think the risk of unintended consequences is high enough that this is a change that we wouldn't want to backport, though - it goes beyond just a bugfix. So if we want a fix that can be backported to 3.10 and 3.11 for MIPS, that would need to be a separate PR with smaller scope. |
Confirmed with a test. Compiling the following #include <math.h>
#include <stdio.h>
double sub(double x, double y) {
return x - y;
}
int main (void) {
double x = NAN;
double y = __builtin_nan("");
double z = sub(INFINITY, INFINITY);
printf("NAN signbit: %d\n", signbit(x));
printf("__builtin_nan() signbit: %d\n", signbit(y));
printf("INF - INF signbit: %d\n", signbit(z));
return 0;
} with
If I inline the |
Looks like you already commented about this, and I missed that comment while I was writing the earlier one ... Seems we're on the same page here. |
OK, that makes things easier. IIRC, R uses payloads to tag on masked values, which is a reasonable use-case for them and I may well be interested in doing similar things as an addition on top of NumPy long-term. Well, if you look at Trying around a bit, I am surprised, but not actually sure that MIPS doesn't set a weird payload (and who knows, maybe even expects it somehow).
Heh, but I guess we can agree that TL;DR: I will suggest I add the test for the sign bit to my PR, also for I am not sure about a test that fails on MIPS, because honestly I can't really think of one that doesn't dive into C and that seems a bit harder than worth it. |
Agreed that adding and using |
Those are examples of cases where the returned For example: >>> from math import gamma
>>> gamma(-2.0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: math domain error |
This PR removes `_Py_dg_stdnan` and `_Py_dg_infinity` in favour of using the standard `NAN` and `INFINITY` macros provided by C99. This change has the side-effect of fixing a bug on MIPS where the hard-coded value used by `_Py_dg_stdnan` gave a signalling NaN rather than a quiet NaN. --------- Co-authored-by: Mark Dickinson <dickinsm@gmail.com>
Fixed in #104202. Not backporting the fix to 3.11 or below, as discussed above. |
* main: pythonGH-102181: Improve specialization stats for SEND (pythonGH-102182) pythongh-103000: Optimise `dataclasses.asdict` for the common case (python#104364) pythongh-103538: Remove unused TK_AQUA code (pythonGH-103539) pythonGH-87695: Fix OSError from `pathlib.Path.glob()` (pythonGH-104292) pythongh-104263: Rely on Py_NAN and introduce Py_INFINITY (pythonGH-104202) pythongh-104010: Separate and improve docs for `typing.get_origin` and `typing.get_args` (python#104013) pythongh-101819: Adapt _io._BufferedIOBase_Type methods to Argument Clinic (python#104355) pythongh-103960: Dark mode: invert image brightness (python#103983) pythongh-104252: Immortalize Py_EMPTY_KEYS (pythongh-104253) pythongh-101819: Clean up _io windows console io after pythongh-104197 (python#104354) pythongh-101819: Harden _io init (python#104352) pythongh-103247: clear the module cache in a test in test_importlib/extensions/test_loader.py (pythonGH-104226) pythongh-103848: Adds checks to ensure that bracketed hosts found by urlsplit are of IPv6 or IPvFuture format (python#103849) pythongh-74895: adjust tests to work on Solaris (python#104326) pythongh-101819: Refactor _io in preparation for module isolation (python#104334) pythongh-90953: Don't use deprecated AST nodes in clinic.py (python#104322) pythongh-102327: Extend docs for "url" and "headers" parameters to HTTPConnection.request() pythongh-104328: Fix typo in ``typing.Generic`` multiple inheritance error message (python#104335)
* main: (27 commits) pythongh-87849: fix SEND specialization family definition (pythonGH-104268) pythongh-101819: Adapt _io.IOBase.seek and _io.IOBase.truncate to Argument Clinic (python#104384) pythongh-101819: Adapt _io._Buffered* methods to Argument Clinic (python#104367) pythongh-101819: Refactor `_io` futher in preparation for module isolation (python#104369) pythongh-101819: Adapt _io.TextIOBase methods to Argument Clinic (python#104383) pythongh-101117: Improve accuracy of sqlite3.Cursor.rowcount docs (python#104287) pythonGH-92184: Convert os.altsep to '/' in filenames when creating ZipInfo objects (python#92185) pythongh-104357: fix inlined comprehensions that close over iteration var (python#104368) pythonGH-90208: Suppress OSError exceptions from `pathlib.Path.glob()` (pythonGH-104141) pythonGH-102181: Improve specialization stats for SEND (pythonGH-102182) pythongh-103000: Optimise `dataclasses.asdict` for the common case (python#104364) pythongh-103538: Remove unused TK_AQUA code (pythonGH-103539) pythonGH-87695: Fix OSError from `pathlib.Path.glob()` (pythonGH-104292) pythongh-104263: Rely on Py_NAN and introduce Py_INFINITY (pythonGH-104202) pythongh-104010: Separate and improve docs for `typing.get_origin` and `typing.get_args` (python#104013) pythongh-101819: Adapt _io._BufferedIOBase_Type methods to Argument Clinic (python#104355) pythongh-103960: Dark mode: invert image brightness (python#103983) pythongh-104252: Immortalize Py_EMPTY_KEYS (pythongh-104253) pythongh-101819: Clean up _io windows console io after pythongh-104197 (python#104354) pythongh-101819: Harden _io init (python#104352) ...
Probably better links for this, but on MIPS, the floating point signalling bit seems typically inverted: https://sourceware.org/binutils/docs/as/MIPS-NaN-Encodings.html
However, Python's _Py_dg_stdnan should create quiet NaNs, but hard-codes the bit to 0.
This again continues to do weird things if mixed with NumPy apparently visible in some
fmin
downstream test failures (to be clear, I don't think the signalling bit should matter for that, but it is incorrect anyway; the bit should never be set in our part of the world). (See numpy/numpy#23158)To me, all of that is a bit moot though. Python has this manual definition for NaN and Inf, but also defines
Py_NAN
andPy_HUGE_VAL
. In theory,Py_HUGE_VAL
doesn't need to be inf andPy_NAN
I am not actually sure what it could be if NaN is not available...But... If you have IEEE doubles and setting the bit-pattern manually is reasonable. You certainly can assume that both are defined to the right thing and
Py_NAN
is in fact aNaN
value. Doing that simplifies the code, but should also solve the MIPS issue sincePy_NAN
presumably is correctly defined to a quiet NaN.This is done in gh-104202. I suppose a test might be:
The text was updated successfully, but these errors were encountered: