3

This code is from UE4 and I have some trouble understanding it.

static FORCEINLINE bool IsNaN( float A ) 
{
    return ((*(uint32*)&A) & 0x7FFFFFFF) > 0x7F800000;
}

(uint32 is just an unsigned int)

The first part is interpreting a float as an uint32, that is the easy part but why bitwise and it with 0x7FFFFFFF? What are the last 4 bits telling us and why do we compare the result with 0x7F800000?

Maik Klein
  • 15,548
  • 27
  • 101
  • 197

3 Answers3

4

This definition follows the NaN definition provided in IEEE 754 standard.

In IEEE 754 standard-conforming floating point storage formats, NaNs are identified by specific, pre-defined bit patterns unique to NaNs.

0x7FFFFFFF is the largest value, that can be represented on 31 bits. In this case, it simply ignores the bit sign, because:

The sign bit does not matter.

0x7F800000 is the mask for bits of the exponential field.

For example, a bit-wise IEEE floating-point standard single precision (32-bit) NaN would be: s111 1111 1xxx xxxx xxxx xxxx xxxx xxxx where s is the sign (most often ignored in applications) and x is non-zero (the value zero encodes infinities).

Where s111 1111 1xxx xxxx xxxx xxxx xxxx xxxx with s = 0 (ignored by anding with 0x7FFFFFFF) and x = 0 is equal to 0x7F800000.

operator > is used, because if any bit in the significand is set (any x), resulting value will be greater than 0x7F800000.

And why should it be set? Because:

The state/value of the remaining bits [...] are not defined by the standard except that they must not be all zero.

Source: NaN on Wikipedia.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Mateusz Grzejek
  • 11,698
  • 3
  • 32
  • 49
3

This is the definition a NaN. You can read this in detail on wikipedia.
0x7FFFFFFF is used because the sign bit does not matter in the check.
The definition says that for a nan the exponential field is filled with ones and some non-zero number is in the significand.
0x7F80000 this is the bit mask for the exponential field. So if a bit is set in the significand the the number must be larger than 0x7F800000

Note that is assumes that a sizeof(float) == 4.

mkaes
  • 13,781
  • 10
  • 52
  • 72
0

isnan()

You can either use the isnan implementation which is environment defined but has historical issues (it was a macro, then became a function under tr1 and in some implementations is still a macro).

f != f

Or, in case you cant track it in your standard library, you can rely on the IEEE standard stating that NaN values have the special property of being different from itself: f != f.
Check out this really interesting answer from Stephen Canon who was in the IEEE-754 committee, and explains the rationale behind it.

note that not all compilers will respect this when some optimization flags are turned on (for instance -ffast-math on gcc).

Community
  • 1
  • 1
ArnonZ
  • 3,822
  • 4
  • 32
  • 42