I am using gcc (Ubuntu 13.2.0-23ubuntu4) 13.2.0. Ubuntu 24.04
I have a bug in my code where a numerical analysis function is giving very different answers. Each of the following returns true. x is a double.
assert (fpclassify(x) == FP_NORMAL);;
assert (x == x);
assert (!(isnan(x)));
assert (isnormal(x));
uint64_t abc = *((long long*)&x) ;
printf("%" PRIx64 "\n", abc);
/* Prints fff8000000000000 */
printf("%f",x);
/* Prints -nan */
uint64_t x4 = 0xfff8000000000000;
assert (x4 == abc);
I am calling the C code from OCaml so it is possible that the OCaml runtime is messing with the values.
Could this be a compiler bug or are here other explanations?
Edit: A previous version of this post mistakenly used bitwise negation instead of Boolean negation.
Per your comments, it appears your code is being built with -Ofast -ffast-math
. From the gcc manual, these enable -ffinite-math-only
, whose behavior is:
Allow optimizations for floating-point arithmetic that assume that arguments and results are not NaNs or +-Infs.
The compiler is not buggy; it's behaving as documented. But you've broken your contract with the compiler by promising that NaN will never appear, and then using one anyway.
In particular, among the optimizations in question is that isnan(x)
will be optimized to constant 0
, so that it appears to return false even when x
really is a NaN; x == x
will be optimized to constant 1; and isnormal
and fpclassify
will not check for NaN. Hence the contradictory results you are observing.
Try rebuilding without these options (-O3
is safe) and you should see the assertions fail.