August 25, 2022
On 8/19/2022 8:15 PM, Steven Schveighoffer wrote:
> But I also find it ironic that you are promoting using the struct's init value as a feature, but not a basic type's init value.

The difference is it must be intentionally set for a field's value, and it is only for that field's value. It is not the default.

August 25, 2022
On Thursday, 25 August 2022 at 16:39:14 UTC, Walter Bright wrote:
> [...]
> If you aren't looking at your output, then why are you calculating the value?

To make decisions?

   double compute_pop ()
   {
      double pop;
      // forgot to implement the computation
      // or ran into a nan by an instable computation
      pop = sqrt (-1.);
      pop += 0.;
      return pop;
   }

   int main ()
   {
      auto pop = compute_pop ();
      if (pop < .5)
         writeln ("It will not rain.");
      else
         writeln ("It will rain.");
      return 0;
   }
August 25, 2022
On Thursday, 25 August 2022 at 16:36:41 UTC, Walter Bright wrote:
> Your anecdote was surely not the elevators or ailerons. It might have been the rudder, where the pilots would have more of a chance.

I found the story again, here's the wikipedia article on it that has its references too:

https://en.wikipedia.org/wiki/Air_Astana_Flight_1388

"The investigation revealed that the aileron cables were installed incorrectly."

Only a few years ago too, in 2018!

There's youtube videos too talking about it too:

https://www.youtube.com/watch?v=5ywaMkMTwWk (this guy generally goes over the incident report with some nice animations to explain it too)
https://www.youtube.com/watch?v=kIc8Rr-cKd8 (atc recording part 1)
https://www.youtube.com/watch?v=evYLkhxoP3U (part 2)

i know im pretty far off topic but i just enjoy these aviation things.
August 25, 2022

On 8/25/22 12:39 PM, Walter Bright wrote:

>

On 8/24/2022 8:08 PM, Steven Schveighoffer wrote:

>

NaN fails at that. It's silently swallowed by just about everything. Only when a human looks at some printout does it become obvious.

Seriously, when is 0 better than that?

If you aren't looking at your output, then why are you calculating the value?

Very few programs have a purpose to print an actual floating point number as text. Instead they are used for other things.

Another example, let's say you are using a FP calculation to determine some sort of timing for bandwidth limiting. You might have something like:

if(val > maxBW) delaySending();

If val or maxBW are NaN, this will always be a false condition (because of the wonderful property that comparisons with NaN are always false), so that code effectively never executes. Note that there's no printf here, and the code happily compiles and runs, it just does something unexepected.

0 is no better here but also no worse.

-Steve

August 25, 2022

On Monday, 22 August 2022 at 22:11:23 UTC, jmh530 wrote:

>

On Monday, 22 August 2022 at 20:29:57 UTC, Bastiaan Veelo wrote:

>

I had some fun with isNaN the other day. We used it to check for initialisation in an access function to cache an expensive computation. This worked brilliantly until we noticed a malfunction in the release version. It took a while until I realised that I had given the LDC fastmath option to the release build, which assumes NaN does not occur, which makes isNaN misbehave.

Is there a simple example of this behavior?

Yes:

import std;
void main()
{
    assert(isNaN(double.nan));
}

Compile with LDC and options --ffast-math -O.

-- Bastiaan.

August 25, 2022

On Thursday, 25 August 2022 at 18:05:36 UTC, Bastiaan Veelo wrote:

>

On Monday, 22 August 2022 at 22:11:23 UTC, jmh530 wrote:

>

On Monday, 22 August 2022 at 20:29:57 UTC, Bastiaan Veelo wrote:

>

I had some fun with isNaN the other day. We used it to check for initialisation in an access function to cache an expensive computation. This worked brilliantly until we noticed a malfunction in the release version. It took a while until I realised that I had given the LDC fastmath option to the release build, which assumes NaN does not occur, which makes isNaN misbehave.

Is there a simple example of this behavior?

Yes:

import std;
void main()
{
    assert(isNaN(double.nan));
}

Compile with LDC and options --ffast-math -O.

-- Bastiaan.

One of the nice things about UDAs and so on is that you can use them to opt into specific optimizations LLVM can do without opting into the blatantly dangerous ones.

http://johanengelen.github.io/ldc/2016/10/11/Math-performance-LDC.html

August 25, 2022
On 8/25/22 11:05, Bastiaan Veelo wrote:
> On Monday, 22 August 2022 at 22:11:23 UTC, jmh530 wrote:
>> On Monday, 22 August 2022 at 20:29:57 UTC, Bastiaan Veelo wrote:
>>> I had some fun with `isNaN` the other day. We used it to check for initialisation in an access function to cache an expensive computation. This worked brilliantly until we noticed a malfunction in the release version. It took a while until I realised that I had given the LDC `fastmath` option to the release build, which assumes NaN does not occur, which makes `isNaN` misbehave.
>>>
>>
>> Is there a simple example of this behavior?
> 
> Yes:
> ```d
> import std;
> void main()
> {
>      assert(isNaN(double.nan));
> }
> ```
> 
> Compile with LDC and options `--ffast-math -O`.
> 
> -- Bastiaan.

I found documentation on --fast-math here:

  https://clang.llvm.org/docs/UsersManual.html

It includes "compiler make[s] [...] assumptions [...] Operands to floating-point operations are not equal to NaN and Inf"

This is contrary to Walter's understanding, which I understand as "operations on NaN stay NaN". LLVM (at least Clang) seems to have a different take on NaN.

And here is Phobos' isNaN implementation in math/traits.d:

bool isNaN(X)(X x) @nogc @trusted pure nothrow
if (isFloatingPoint!(X))
{
    version (all)
    {
        return x != x;
    }
    else
    {
        /*
        Code kept for historical context. At least on Intel, the simple test
        x != x uses one dedicated instruction (ucomiss/ucomisd) that runs in one
        cycle. Code for 80- and 128-bits is larger but still smaller than the
        integrals-based solutions below. Future revisions may enable the code
        below conditionally depending on hardware.
        */
     // ... Removed by Ali
   }
}

LLVM must be thinking x != x is not a valid operation on NaN. Could we use a bit pattern check instead? Or write it as an asm block?

Ali
August 25, 2022
On Thursday, 25 August 2022 at 19:21:08 UTC, Ali Çehreli wrote:
> I found documentation on --fast-math here:
>
>   https://clang.llvm.org/docs/UsersManual.html
>
> It includes "compiler make[s] [...] assumptions [...] Operands to floating-point operations are not equal to NaN and Inf"
>
> This is contrary to Walter's understanding, which I understand as "operations on NaN stay NaN". LLVM (at least Clang) seems to have a different take on NaN.

It is not just "contrary to Walter's understanding", it is contrary to the IEEE 754 standard. Here is an article that goes into more detail about it:

https://simonbyrne.github.io/notes/fastmath/

> LLVM must be thinking x != x is not a valid operation on NaN. Could we use a bit pattern check instead? Or write it as an asm block?

LLVM with fast-math assumes that all floating-point operands are finite, which means that it can optimize `x != x` to `false` at compile time. A sufficiently smart optimizer could in principle perform the same optimization on a bit pattern check, if it recognized the bit pattern for NaN.
August 25, 2022

On Thursday, 25 August 2022 at 11:38:22 UTC, max haughton wrote:

>

On Thursday, 25 August 2022 at 09:07:54 UTC, user1234 wrote:

>

On Thursday, 25 August 2022 at 07:15:58 UTC, bauss wrote:

>

[...]

I'm shocked by this idea. What if I want high performance nothrow FP code ?

Turn the check off. The hardware basically already supports doing this (NaNs don't have to be quiet) but almost no one uses it - it's quite hard to trigger at all on a modern system.

We agree there, we talk about a check that does not even exist but that has to be disabled.

August 25, 2022

On Thursday, 25 August 2022 at 18:11:11 UTC, max haughton wrote:

>

One of the nice things about UDAs and so on is that you can use them to opt into specific optimizations LLVM can do without opting into the blatantly dangerous ones.

http://johanengelen.github.io/ldc/2016/10/11/Math-performance-LDC.html

Yes, that is the only responsible way to use this power. The individual flags are these: https://llvm.org/docs/LangRef.html#fast-math-flags to be used with this UDA: https://wiki.dlang.org/LDC-specific_language_changes#.40.28ldc.attributes.llvmFastMathFlag.28.22flag.22.29.29.

Examples can be seen in Mir: http://mir-core.libmir.org/mir_math_common.html

— Bastiaan.