# min(NaN,5) = NaN (why no @fastmath?)

**URL:** <https://discourse.julialang.org/t/min-nan-5-nan-why-no-fastmath/93736>\
**Category:** General Usage\
**Tags:** nan\
**Created:** [January 29, 2023, 5:07pm UTC](https://discourse.julialang.org/t/min-nan-5-nan-why-no-fastmath/93736 "2023-01-29T17:07:14Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Marcell\_Havlik](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marcell_havlik/32/37424_2.png) [@Marcell\_Havlik](https://discourse.julialang.org/u/Marcell_Havlik)\
**Post date:** [January 29, 2023, 5:07pm UTC](https://discourse.julialang.org/t/min-nan-5-nan-why-no-fastmath/93736/1 "2023-01-29T17:07:14Z")

</div>

Hey Julianners,  
I just want to ask, as I ran into this problem 4th times even after that I know what causes this problem.

Shouldn’t we make it happen to be correct as it is expected like in other languages?  
 ![image](https://global.discourse-cdn.com/julialang/original/3X/4/2/42c1899464d940abe6dcdaf05cd9152a18f3f150.png)  
So basically the `@fastmath` version would be always correct if I am correct. Anyone else who would want to run it otherwise should have an option like `@nofastmath` or something?

But yeah… I of course I see the problem that… the whole julia should be started with `--math-mode=fast` so it would work like expected consistently. I don’t know what do you guys think? Shouldn’t julia maybe run with fast mode automatically all in all, so beginners doesn’t run into this trap?

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [January 29, 2023, 5:10pm UTC](https://discourse.julialang.org/t/min-nan-5-nan-why-no-fastmath/93736/2 "2023-01-29T17:10:47Z")

</div>

```julia
julia> min(NaN,5.0)
NaN

julia> min(5.0,NaN)
NaN

julia> @fastmath min(NaN,5.0)
5.0

julia> @fastmath min(5.0,NaN)
NaN

```

The `@fastmath` version returns a different answer based on order of the arguments.  
I’m not sure what you mean by it is always correct?

Also, on Julia master, `--math-mode=fast` doesn’t do anything anymore.

---

<div class="post-metadata">

**Author:** ![Marcell\_Havlik](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marcell_havlik/32/37424_2.png) [@Marcell\_Havlik](https://discourse.julialang.org/u/Marcell_Havlik)\
**Post date:** [January 29, 2023, 5:13pm UTC](https://discourse.julialang.org/t/min-nan-5-nan-why-no-fastmath/93736/3 "2023-01-29T17:13:08Z")

</div>

Well it is wrong in both case without `@fastmath`. But fair point. Still very bad with fastmath too! 😃

Omg… I didn’t know about this.  
 ![image](https://global.discourse-cdn.com/julialang/original/3X/5/9/5934920fccb6b85552259b0b111343110e1d2b1a.png)

Ok… I have nothing to add. This is very bad situation. I will just accept the truth that we cannot handle it anyhow else like I have to pay attention and handle NaN and Inf in each case.

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [January 29, 2023, 5:16pm UTC](https://discourse.julialang.org/t/min-nan-5-nan-why-no-fastmath/93736/4 "2023-01-29T17:16:23Z")

</div>

> [@Elrod](#):
>
> Also, on Julia master, `--math-mode=fast` doesn’t do anything anymore.

That is because some code was written in a manner assuming IEEE math.  
This code was broken under `--math-mode=fast`. `sinpi` and `cospi` are examples.

I do agree though that most code doesn’t assume it, and most of the code that does is written by experts in a deliberate manner, so IMO it isn’t totally unreasonable to at least generally have `contract` enabled.  
It also seems silly that `a::Float64 + 0.0` cannot be optimized away without `@fastmath`, but `a + (-0.0)` can.  
But you should prefer `0.0` over `-0.0` in cases where it cannot be optimized away, because the former is cheaper for the CPU to generate, meaning which to choose depends on knowing whether or not it’s likely to be optimized away in this case…  
`@fastmath` is simpler in these cases, but also likely to pessimize generic code like `ForwardDiff.Dual`s which use fallback definitions for the fast functions, resulting in lots of code not getting inlined that otherwise should.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [January 29, 2023, 5:34pm UTC](https://discourse.julialang.org/t/min-nan-5-nan-why-no-fastmath/93736/5 "2023-01-29T17:34:42Z")

</div>

> [@Marcell\_Havlik](#):
>
> Well it is wrong in both case without `@fastmath`. But fair point. Still very bad with fastmath too! 😃

`NaN` propagating through operations is intended behavior, following IEEE 754

> [@Marcell\_Havlik](#):
>
> Ok… I have nothing to add. This is very bad situation. I will just accept the truth that we cannot handle it anyhow else like I have to pay attention and handle NaN and Inf in each case.

You’ll have to thank Intel for this, who, in their infinite wisdom, decided that this is how it should behave in x86… See also [this](https://www.felixcloutier.com/x86/minss):

> Compares the low single-precision floating-point values in the first source operand and the second source operand and returns the minimum value to the low doubleword of the destination operand.
> 
> If the values being compared are both 0.0s (of either sign), the value in the second source operand is returned. If a value in the second operand is an SNaN, that SNaN is returned unchanged to the destination (that is, a QNaN version of the SNaN is not returned).
> 
> If only one value is a NaN (SNaN or QNaN) for this instruction, the second source operand, either a NaN or a valid floating-point value, is written to the result. If instead of this behavior, it is required that the NaN in either source operand be returned, the action of MINSD can be emulated using a sequence of instructions, such as, a comparison followed by AND, ANDN and OR.

The situation is of course the same for `Float64` i.e. double precision. Fixing this in x86 is kind of impossible, practically speaking.

---

<div class="post-metadata">

**Author:** ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)\
**Post date:** [January 29, 2023, 7:35pm UTC](https://discourse.julialang.org/t/min-nan-5-nan-why-no-fastmath/93736/6 "2023-01-29T19:35:26Z")

</div>

> [@Marcell\_Havlik](#):
>
> Shouldn’t we make it happen to be correct as it is expected like in other languages?

Which language do you have in mind that doesn’t behave like this?

---

<div class="post-metadata">

**Author:** ![Marcell\_Havlik](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marcell_havlik/32/37424_2.png) [@Marcell\_Havlik](https://discourse.julialang.org/u/Marcell_Havlik)\
**Post date:** [January 29, 2023, 7:37pm UTC](https://discourse.julialang.org/t/min-nan-5-nan-why-no-fastmath/93736/7 "2023-01-29T19:37:07Z")

</div>

I think python. But pretty supprised as Sakura mentioned it is IEEE754 standard so… I can even imagine I didn’t even know about it when I was using Python? 😃 Would be crazy… 😃

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [January 29, 2023, 8:26pm UTC](https://discourse.julialang.org/t/min-nan-5-nan-why-no-fastmath/93736/8 "2023-01-29T20:26:51Z")

</div>

Huh, python doesn’t follow IEEE754:

```python
In [1]: import numpy as np

In [2]: min(5.0, np.nan)
Out[2]: 5.0

In [3]: min(np.nan, 5.0)
Out[3]: nan

```

---

<div class="post-metadata">

**Author:** ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)\
**Post date:** [January 29, 2023, 9:09pm UTC](https://discourse.julialang.org/t/min-nan-5-nan-why-no-fastmath/93736/9 "2023-01-29T21:09:53Z")

</div>

You’re right, Python doesn’t follow IEEE 754, and I believe that’s the way to use NaN without NumPy (so syntax (and semantics) with or without numpy is non-ideal):

```julia
>>> min(5.0, float("nan"))
5.0

```

You implied to me that you (fully, you didn’t) used NumPy, but to be fair its function works:

```julia
>>> np.minimum(5.0, np.nan)
nan

>>> np.nanmin(np.array([5.0, np.nan])) # Here "ignoring any NaNs. When all-NaN slices are encountered a RuntimeWarning s raised and NaN is returned for that slice." and order doesn't matter.
5.0

```

Yes, people claim e.g. Python’s min and max are buggy (I would agree IEEE should be followed, and some non-default way to ignore its rules, as in Julia, e.g. with NaNmath.jl), though not all did agree…:

> **[NaN breaks min, max and sorting functions. A solution](https://discuss.python.org/t/nan-breaks-min-max-and-sorting-functions-a-solution/2868/16)**
>
> It really isn’t. That’s nice for them. In Python, we have min and max functions that are under no obligation to work like minNum and maxNum. In practical terms, either you care about NaNs or you don’t. If you don’t, filtering them out is...

> > [@](#):
> >
> > The IEEE 754-2008 standard defines the functions minNum and maxNum giving the minimum and maximum of two inputs, respectively.
> 
> That’s nice for them. In Python, we have `min` and `max` functions that are under no obligation to work like `minNum` and `maxNum`. In practical terms, either you care about NaNs or you don’t. If you don’t, filtering them out is trivial. […]

---

<div class="post-metadata">

**Author:** ![arch.d.robison](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/arch.d.robison/32/17699_2.png) [@arch.d.robison](https://discourse.julialang.org/u/arch.d.robison)\
**Post date:** [January 31, 2023, 3:10pm UTC](https://discourse.julialang.org/t/min-nan-5-nan-why-no-fastmath/93736/10 "2023-01-31T15:10:11Z")

</div>

IEEE rules require that NaN _not_ propagate through min and max unless both operands are NaN. See [William Kahan’s remarks](https://github.com/JuliaLang/julia/issues/7866#issuecomment-53079589) here. But also in that thread, the consensus was that the rule was surprising and perhaps should not be followed by Julia.

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [January 31, 2023, 3:28pm UTC](https://discourse.julialang.org/t/min-nan-5-nan-why-no-fastmath/93736/11 "2023-01-31T15:28:29Z")

</div>

> [@arch.d.robison](#):
>
> perhaps should not be followed by Julia.

Saddly

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [January 31, 2023, 3:48pm UTC](https://discourse.julialang.org/t/min-nan-5-nan-why-no-fastmath/93736/12 "2023-01-31T15:48:04Z")

</div>

What justification do you have for why `max(NaN, x)` should be `x`, aside from appeal to the spec? The IEEE 754 recommendation of min and max functions ignoring NaNs is _extremely questionable_, as Kahan writes in the above response to Arch’s query. Under the “not a real” interpretation of NaN there’s never any justification of not propagating a NaN since it’s a permanent poison value. This is the most conservative interpretation of NaN and the one we use pretty much everywhere. Even under the more relaxed “unknown real” interpretation of NaN, `max(NaN, x) == x` can only be justified when `x == Inf` and otherwise the result must be `NaN`, which is the rule that Kahan suggests.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [January 31, 2023, 3:50pm UTC](https://discourse.julialang.org/t/min-nan-5-nan-why-no-fastmath/93736/13 "2023-01-31T15:50:42Z")

</div>

> [@arch.d.robison](#):
>
> IEEE rules require that NaN _not_ propagate through min and max unless both operands are NaN.

Mea culpa - I must confess that I do not possess a copy of IEEE 754 (the horror!) and can’t look it up myself 🙂

> [@StefanKarpinski](#):
>
> Under the “not a real” interpretation of NaN there’s never any justification of not propagating a NaN since it’s a permanent poison value.

Interestingly, some part of that `minNum`/`maxNum`/`fmin`/`fmax` kerfuffle depend not only on the programming language, but also on which version of the standard the language implements (and possibly the hardware, depending on if it’s compiled properly):

> **[minNum\_maxNum\_Removal\_Demotion\_v3.pdf](https://grouper.ieee.org/groups/msc/ANSI_IEEE-Std-754-2019/background/minNum_maxNum_Removal_Demotion_v3.pdf)**
>
> 597.90 KB

Do we distinguish between quiet and signaling NaNs at all? I don’t think so 🤔

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [January 31, 2023, 3:51pm UTC](https://discourse.julialang.org/t/min-nan-5-nan-why-no-fastmath/93736/14 "2023-01-31T15:51:51Z")

</div>

> [@Sukera](#):
>
> Do we distinguish between quiet and signaling NaNs at all?

No, since LLVM doesn’t support it well enough to be usable.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [January 31, 2023, 3:58pm UTC](https://discourse.julialang.org/t/min-nan-5-nan-why-no-fastmath/93736/15 "2023-01-31T15:58:17Z")

</div>

> [@StefanKarpinski](#):
>
> No, since LLVM doesn’t support it well enough to be usable.

That makes sense.

Scrolling down through that thread, it seems [Agner Fog also left us a comment](https://github.com/JuliaLang/julia/issues/7866#issuecomment-369495006) with good reasoning for the existing `min` behavior - vector instructions can generate more than one NaN at a time, making it impossible to distinguish where the bad one occured. Propagating thus makes more sense.

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [January 31, 2023, 4:02pm UTC](https://discourse.julialang.org/t/min-nan-5-nan-why-no-fastmath/93736/16 "2023-01-31T16:02:04Z")

</div>

One real case for me is to produce images out of grids, which is a common task on Geophysics. To map float numbers of a grid into the integers (uint8) via a color table one must know the array’s min/max. And it is also common that those grids (arrays of floats) have NaNs in them to indicate no-value numbers (for example any grid of an oceanographic variable that covers also a part of land). For those cases I was forced to write custom min/max functions that ignore NaNs.

You may also remember that old Matlab versions used to have the Julia behavior but they changed to _min,max ignore NaNs_ long time ago.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [January 31, 2023, 4:07pm UTC](https://discourse.julialang.org/t/min-nan-5-nan-why-no-fastmath/93736/17 "2023-01-31T16:07:11Z")

</div>

Isn’t it lucky that you can write custom `min` and `max` functions that will be fast enough? 😀 Ignoring NaNs seems convenient for working with images, but that’s a weak justification for a dangerous behavior in a function that everyone uses.

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [January 31, 2023, 4:17pm UTC](https://discourse.julialang.org/t/min-nan-5-nan-why-no-fastmath/93736/18 "2023-01-31T16:17:54Z")

</div>

> [@StefanKarpinski](#):
>
> weak justification for a dangerous behavior in a function that everyone uses.

I think that weakness depends on ones view point. I don’t remember to have seen any complain (though ofc there should have been some) from Matlab users. 😐

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [January 31, 2023, 4:26pm UTC](https://discourse.julialang.org/t/min-nan-5-nan-why-no-fastmath/93736/19 "2023-01-31T16:26:49Z")

</div>

It’s even easier than writing custom min/max!

```julia
julia> using Skipper
julia> maximum(skip(isnan, A))

```

or

```julia
julia> using Skipnan
julia> maximum(skipnan(A))

```

Without any allocations, even though somewhat slower than regular `maximum(A)` due to worse SIMD.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [January 31, 2023, 4:27pm UTC](https://discourse.julialang.org/t/min-nan-5-nan-why-no-fastmath/93736/20 "2023-01-31T16:27:13Z")

</div>

This works:

```julia
maximum(filter(!isnan, x))  

```

At least in Julia Version 1.9.0-beta3.  
Ditto for `findmax`, `extrema`, etc.

[Next page](https://discourse.julialang.org/t/min-nan-5-nan-why-no-fastmath/93736.md?page=2)
