[Numpy-discussion] Floating point warnings/errors for comparisons, etc.?

Sebastian Berg sebastian at sipsolutions.net
Wed Jul 7 11:51:52 EDT 2021


Hi all,

I am trying to clean up our floating point warning handling:

    https://github.com/numpy/numpy/pull/19316

And an upcoming PR to remove most floating point error clearing.  There
are some things I am unsure about, though.

Part of why it got so confusing, is that GCC seemed to have
fixed/changed their behaviour for comparisons with NaN.  In GCC 7 it
did not give the warning, but GCC 8 does (correctly).


Comparison with NaN
-------------------

IEEE says that the default comparisons should give warnings for
comparison with NaN (except == and !=).  And notes that an alternative
should be provided (C99 does this with `isless`, etc.).

We currently break this by suppressing invalid value warnings for all
comparisons (e.g. also `NaN > 0.`).

We can easily do either version (aside possibly compiler issues).
Making it give warnings had one test case fail for `quantile`, which
uses the pattern:

    if not (np.all(q >= 0) and np.all(q <= 1)):
        raise ValueError("bad q")

This would additionally (and first) give an "invalid value" warning and
require `np.errstate(invalid="ignore") to suppress it.

I dislike diverging from IEEE, but Python also does not warn for [1]:

    float("nan") >= 0

and presumably the user either explicitly created the NaN or has seen a
warning earlier during computation when the NaN was first created.

(IEEE does not distinguish creating a new NaN with `0./0.` from a
comparison with `NaN > 0.` [2].  So we can't easily make this settable
via `np.errstate` or so.)

So, should we ignore the warning here?


Compiler Issues
---------------

Some compilers may get flags wrong.  How much effort do we want to
spend on details few users will notice?

My current problem is `1 % 0` and `divmod(1, 0)`.  The MacOS/clang CI
does not set the correct "invalid value" warning flag.  (The remainder
is NaN, so a new NaN is created and that should be indicated but the
C99 `fmod` does not set it.)


Signalling NaNs
---------------

I propose dropping any special concern for signalling NaNs.  Which
means they raise almost always.  Although, rarely we might suppress the
warning if we do it manually for normal NaNs [0].

We have two tests which check for behaviour on signalling NaNs. I could
not find having any logic to them besides someone being surprised at
signalling NaN behaviour at the time – not based on use-cases.
Even functions like `isnan` give a warning for signalling NaNs!

The "fix" for anyone having sNaN's is to convert them to qNaNs as early
as possible.  Which e.g. `np.positive(arr, out=arr)` should probably
do.  If this becomes an issue, maybe we could have an explicit ufunc.


Cheers,

Sebastian



[0] Mainly it seems SSE2 does not provide some non-error comparisons. 
So trying to avoid manually clearing errors might make some SSE code
considerable slower (e.g. `isfinite`, `np.min`).

[1] Probably Python just does not check the CPU warning flags

[2] https://www.gnu.org/software/libc/manual/html_node/FP-Exceptions.html



More information about the NumPy-Discussion mailing list