I've encountered a bug, where my variable with infinity is not equal to infinity. And I'm not even sure, in which cases.
Here is minimal example:
#include <iostream>
#include <limits>
#include <cmath>
using namespace std;
constexpr auto NT_INF = std::numeric_limits<double>::infinity();
// prints a number byte-by-byte
void printN(double n){
auto tmp = (uint8_t*)&n;
for (int i = 0; i < 8; i++) {
wprintf(L"%4d ", tmp[i]);
}
wprintf(L"\n");
};
double * genNumbers() {
double * numbers = new double[6];
numbers[0] = 100;
numbers[1] = 1;
numbers[2] = 198263783302;
numbers[3] = 198263783302;
numbers[4] = 100;
numbers[5] = 0;
return numbers;
}
int main()
{
// leave no chance for the compiler to optimize variables away
double * numbers = genNumbers();
// floor((100. * 1.) / (198263783302. - 198263783302.)) / 100.;
numbers[5] = floor((numbers[0] * numbers[1]) / (numbers[2] - numbers[3])) / numbers[4];
double number = numbers[5];
printN(number);
printN(NT_INF);
wprintf(L"%f, %f, %d, %d, %d, %d\n", number, NT_INF, number == 1.0 / 0.0, number == NT_INF, isinf(NT_INF), isinf(number));
delete numbers;
return 0;
}
My compiler flags for GCC are:
-fno-reorder-blocks -ffast-math -march=native -fno-exceptions -Ofast -fmodulo-sched -fgcse-sm -fgcse-las -fno-inline-small-functions -flto=2 -fgcse-lm -fira-region=all
If you try to run it in onlinegdb, then you will get something like
0 0 0 0 0 0 240 127
0 0 0 0 0 0 240 127
inf, inf, 1, 1, 1, 0
So NT_INF
and number
are the same, judging by printN
output.
At the same time, isinf
says number
is not infinity... But printf says it is???
If I try to compile locally, the situation is even worse (I suppose, it's so due to -march=native
).
0 0 0 0 0 0 240 127
0 0 0 0 0 0 240 127
inf, inf, 0, 0, 1, 0
So here the number
variable isn't even equal to infinity, using simple ==
I have absolutely no idea what's wrong with this example (an my real code). Maybe it's due to some flag or their combination, but there is too much of combinations to try them.