Почему gcc -ffast-math отключает правильный результат isnan() и isinf()?
Я понимаю, что используя flag разрешает небезопасные математические операции и отключает сигнализацию NaN. Однако я ожидал, что функции и по-прежнему смогут возвращать правильные результаты, а они этого не делают.
Вот пример:
Файл
test_isnan.c
:
#include <stdio.h>
#include <math.h>
int main(void){
/* Produce a NaN */
const float my_nan = sqrtf(-1.f);
/* Produce an inf */
const float my_inf = 1.f/0.f;
printf("This should be a NaN: %.6e\n", my_nan);
printf("This should be inf: %.6e\n", my_inf);
if (isnan(my_nan)) {
printf("Caugth the nan!\n");
} else {
printf("isnan failed?\n");
}
if (isinf(my_inf)) {
printf("Caugth the inf!\n");
} else {
printf("isinf failed?\n");
}
}
Теперь скомпилируем и запустим программу без
-ffast-math
:
$ gcc test_isnan.c -lm -o test_isnan.o && ./test_isnan.o
This should be a NaN: -nan
This should be inf: inf
Caugth the nan!
Caugth the inf!
Но с этим:
$ gcc test_isnan.c -lm -o test_isnan.o -ffast-math && ./test_isnan.o
This should be a NaN: -nan
This should be inf: inf
isnan failed?
isinf failed?
Так почему бы не
isnan()
а также
isinf()
поймать эти
nan
песок
inf
с? Что мне не хватает?
Если это может быть актуально, вот мой
gcc
версия:
gcc (Spack GCC) 10.2.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
2 ответа
Из https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html:
-ffast-math
Устанавливает параметры -fno-math-errno, -funsafe-math-optimizations, -ffinite-math-only , -fno-rounding-math, -fno-signaling-nans, -fcx-limited-range и - fexcess-precision = быстро.
Где:
-ffinite-math-only
Разрешить оптимизацию арифметики с плавающей запятой, предполагающую, что аргументы и результаты не являются NaN или +-Infs.
В тот момент, когда вы нарушите это предположение, вы не сможете ожидать, что эти функции будут работать.
Я понимаю, что вы надеялись, что этот параметр оптимизирует все другие операции, при этом обеспечивая правильный результат для этих двух функций, но это просто не так, как это работает. Я не думаю, что есть способ решить эту проблему. Может быть, вы можете взглянуть на Clang, но я не ожидаю, что он будет другим.
-ffast-math
Устанавливает параметры ... -ffinite-math-only ...
-ffinite-math-only - только математика
Разрешить оптимизацию для арифметики с плавающей запятой, предполагающую, что аргументы и результаты не являются NaN или +-Infs.
Компилятор оптимизирует код, чтобы:
printf("This should be a NaN: %.6e\n", sqrtf(-1.f));
printf("This should be inf: %.6e\n", 1.f/0.f);
printf("isnan failed?\n");
printf("isinf failed?\n");
потому что компилятор знает, что выражения не могут возвращать
nan
или
inf
.