Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Usefulness of signaling NaN?

People also ask

What is the value of NaN?

NaN means "Not A Number". It is a special value that denotes the result of a computation that either is impossible (division by zero, f.e.) or cannot be stored using the floating point format. It represents a value that is unknown or cannot be computed (or stored) using the floating point format.

What does NaN not a number stand for in artillery?

What does NaN (Not a Number) stand for. not sufficient response.

What does NaN mean C++?

NaN, an acronym for Not a Number is an exception that usually occurs in the cases when an expression results in a number that is undefined or can't be represented. It is used for floating-point operations. For example: The square root of negative numbers.

How is NaN represented in C?

— Macro: float NAN An expression representing a value which is “not a number”. This macro is a GNU extension, available only on machines that support the “not a number” value—that is to say, on all machines that support IEEE floating point. You can use '#ifdef NAN' to test whether the machine supports NaN.


As I understand it, the purpose of signaling NaN is to initialize data structures, but, of course runtime initialization in C runs the risk of having the NaN loaded into a float register as part of initialization, thereby triggering the signal because the the compiler isn't aware that this float value needs to be copied using an integer register.

I would hope that you could could initialize a static value with a signaling NaN, but even that would require some special handling by the compiler to avoid having it converted to a quiet NaN. You could perhaps use a bit of casting magic to avoid having it treated as a float value during initialization.

If you were writing in ASM, this would not be an issue. but in C and especially in C++, I think you will have to subvert the type system in order to initialize a variable with NaN. I suggest using memcpy.


Using special values (even NULL) can make your data a lot muddier and your code a lot messier. It would be impossible to distinguish between a QNaN result and a QNaN "special" value.

You might be better maintaining a parallel data structure to track validity, or perhaps having your FP data in a different (sparse) data structure to only keep valid data.

This is fairly general advice; special values are very useful in certain cases (e.g. really tight memory or performance constraints), but as the context grows larger they can cause more difficulty than they're worth.


Here are the bit-patterns of the different double NaNs:

A signalling NaN is represented by any bit pattern between 7FF0000000000001 and 7FF7FFFFFFFFFFFF or between FFF0000000000001 and FFF7FFFFFFFFFFFF

A quiet NaN is represented by any bit pattern between 7FF8000000000000 and 7FFFFFFFFFFFFFFF or between FFF8000000000000 and FFFFFFFFFFFFFFFF

Source: https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html

Disclaimer: As others have pointed out, casting magic is potentially dangerous and may cause undefined behavior. Using memcpy has been suggested as a safer alternative.

That being said, for academical purposes, or if you know it is safe on the intended hardware:

In theory, it seems like it should work to just have a const uint64_t where the bits have been set to those of a signaling nan. As long as you treat it as an integer type, the signaling nan is not different from other integers. Then, barring architectural special case issues, maybe you could write it where you want through pointer-casting. If it works as intended, it might even be faster than memcpy. For some embedded systems it might even be useful.

Example:

const uint64_t sNan = 0xFFF7FFFFFFFFFFFF;
double[] myData;
...
uint64_t* copier = (uint64_t*) &myData[index];
*copier = sNan & ~myErrorFlags;