16

When I was debugging code, I found that GCC and Clang both yield nan for 0.0/0.0 which is what I was expecting, but GCC yields an nan with the sign bit set to 1, while Clang sets it to 0 (in agreement with ICC, if I remember correctly).

Now apparently both forms are allowed, but I keep wondering why 0.0/0.0 would make GCC output a "negative" result (printing it gives -nan), and -(0.0/0.0) gives a "positive" result? What is even more confusing is that -0.0/0.0 is "negative" again. Is this a constant folding weirdness?

edit

Actually, it's the constant folding that makes it a positive nan. If I force the computation at runtime, I get negative nan on both GCC and Clang

volatile float zero = 0.0;
std::cout << (zero/zero); // -nan

Can someone sched some light on this please? Is the sign bit set to 1 on the x86 FPU?

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212

1 Answers1

10

IEEE-754 does not specify the sign of a NaN:

When either an input or result is NaN, this standard does not interpret the sign of a NaN. Note, however, that operations on bit strings - copy, negate, abs, copySign — specify the sign bit of a NaN result, sometimes based upon the sign bit of a NaN operand. The logical predicate totalOrder is also affected by the sign bit of a NaN operand. For all other operations, this standard does not specify the sign bit of a NaN result, even when there is only one input NaN, or when the NaN is produced from an invalid operation.

Now lets look at the Intel 64 and IA-32 Architectures Software Developer’s Manual Volume 1: Basic Architecture.

Therein, Intel does specify a specific value of NaN in this case, which is called QNaN Floating-Point Indefinite (see Table 4-1), which is returned upon an #IA (invalid arithmetic exception) (see Table 8-10). Look for division 0 by 0.

You see that for that value, the sign bit is set.

marc
  • 6,103
  • 1
  • 28
  • 33
  • Ah i see. So clang and icc seem yield inconsistent results depending on whether you directly compute 0/0 or enable optimizations. Is that on purpose? – Johannes Schaub - litb Aug 26 '15 at 12:20
  • Not sure what you mean. The compiler can do whatever it wants to the sign bit. The sign bit is unspecified in the IEEE standard. It is the compilers good right to use +NaN or -NaN here. However, x86 Intel CPUs will always yield a NaN with negative sign bit, which is also valid as per the standard. Some compilers may know about that hardware behaviour, some don't, and some probably don't care. If you are curious, the clang source for this is llvm/lib/Support/APFloat.cpp, the divideSpecial method. I really can't be bothered to dive into gcc source ^^ – marc Aug 26 '15 at 12:43
  • 3
    FYI the ARM VFP will yield a positive sign, its not like there is agreement among hardware manufacturers. – marc Aug 26 '15 at 13:50