I'm using -Ofast
gcc option in my program cause latency requirements. I wrote simple test program:
#include <iostream>
#include <math.h>
static double quiet_NaN = std::numeric_limits<double>::quiet_NaN();
int main()
{
double newValue = 130000;
double curValue = quiet_NaN;
printf("newValue = %f\n", newValue);
printf("curValue = %f\n", curValue);
printf("isnan(newValue) = %d\n", isnan(newValue));
printf("isnan(curValue) = %d\n", isnan(curValue));
printf("newValue == curValue %d\n", (newValue == curValue));
printf("newValue != curValue %d\n", (newValue != curValue));
}
I've tried to run it with default flags and with -Ofast:
$ g++ TestPointer.cpp
$./a.out
newValue = 130000.000000
curValue = nan
isnan(newValue) = 0
isnan(curValue) = 1
newValue == curValue 0
newValue != curValue 1
$ g++ -Ofast TestPointer.cpp
$ ./a.out
newValue = 130000.000000
curValue = nan
isnan(newValue) = 0
isnan(curValue) = 1
newValue == curValue 1
newValue != curValue 0
So the result of !=
and ==
can not be trusted. Does it mean that I should ==
and !=
only when both values are known to be not nan, otherwise I should test with isnan
before?
Is it guaranteed that isnan
works correctly with -Ofast
?
How correctly ==
and !=
works for double with -Ofast
?
Can someone provide complete list of limitations added by -Ofast
?
You're observing the effects of -ffast-math
.
From the docs:
-Ofast
Disregard strict standards compliance. -Ofast enables all -O3 optimizations. It also enables optimizations that are not valid for all standard-compliant programs. It turns on -ffast-math and the Fortran-specific -fno-protect-parens and -fstack-arrays.
and
-ffast-math
Sets -fno-math-errno, -funsafe-math-optimizations, -fno-trapping-math, -ffinite-math-only, -fno-rounding-math, -fno-signaling-nans and fcx-limited-range.
and
-ffinite-math-only
Allow optimizations for floating-point arithmetic that assume that arguments and results are not NaNs or +-Infs.
There are several gcc bug reports for this marked invalid.
Problems with -ffast-math and isnan
Additionally, comparison of strict IEEE floating points always results in false.
Checking if a double (or float) is NaN in C++
This doesn't necessarily apply for -ffast-math
but it explains what you show.
gcc does not describe a formal standard for how -ffast-math
floats work so you'll just have to work out the details empirically if you must and not assume consistency between versions of gcc. Better yet, completely avoid the combination of NaN
and -ffast-math
.