Fun with NaNs (different behavior in cling/clang)

Consider this code (file testnan.cxx)

#include <iostream>
#include <limits>
#include <cfenv>

void test(double d) {
  std::feclearexcept(FE_ALL_EXCEPT);
  double dd = d+1;
  std::cout << std::fetestexcept(FE_ALL_EXCEPT) << '\n';
}

void nantest() {
  test(std::numeric_limits<double>::quiet_NaN());
  test(std::numeric_limits<double>::signaling_NaN());
}

int main(){nantest();}

Depending on how I execute it, I can get 3 different results:
a)

$ clang++-3.9 -std=c++14 ~/test/nantest.cxx && ./a.out
0
1

b) in ROOT (From heads/master@v6-09-02-1807-g616eba4, Jul 27 2017)

$ root -b -q ~/test/nantest.cxx

Processing ~/test/nantest.cxx...
0
0

c) interactive:

root [0] double d=numeric_limits<double>::quiet_NaN();
root [1] feclearexcept(FE_ALL_EXCEPT);
root [2] double dd = d+1;
root [3] fetestexcept(FE_ALL_EXCEPT)
(int) 33
// 33 = FE_INVALID + FE_INEXACT

// the same for signaling, however the value seems to come from elsewhere
root [4] feclearexcept(FE_ALL_EXCEPT);
root [5] fetestexcept(FE_ALL_EXCEPT)
(int) 32
// 32 = FE_INEXACT

I can understand that c) is different, probably the state is changed between the commands. However, shouldn’t a) and b) give identical results?

1 Like

Is the result of incrementing a NaN implementation dependent or undefined behaviour?

Actually, I don’t think it is the adding that in impl. defined (1+nan = nan in IEEE 754) but the whole fp-flag business (the side effect) seems implementation defined. C++ standard only references the C standard (26.4.1: “The header defines all functions, types, and macros the same as Clause 7.6 of the C standard.”) and only specifies thread-local storage. The C standard states that even the FE_* error macros are implementation defined (may not exist at all, in which case FE_ALL_EXCEPT=0). So I’d think it is all implementation defined, not undefined.

And #pragma STDC FENV_ACCESS on seems to work in gcc only (neither in clang nor in ROOT).

However, I’m not a language lawyer but are more interested in if I can use any of this in ROOT. Can I somehow differentiate between signaling and quiet NaNs (in ROOT)? Should I be able to do so?

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.