Я столкнулся с проблемой сравнений с плавающей точкой.При сравнении значения с NaN с использованием оператора <
я ожидаю, что будет установлен флаг FE_INVALID
.Оператор <
должен поднять флаг в соответствии со стандартом C11 (а также в соответствии с IEEE-754):
Макрос isless
определяет, меньше ли его первый аргумент, чем его второй аргумент.Значение isless(x, y)
всегда равно (x) < (y)
;однако в отличие от (x) < (y)
, isless(x, y)
не вызывает "недопустимое" исключение с плавающей точкой , когда x
и y
являются неупорядоченными .
Вот пример программы для воспроизведения моей проблемы:
#include <stdio.h>
#include <math.h>
#include <fenv.h>
#pragma STDC FENV_ACCESS ON
int main()
{
volatile float a = 12.0f;
volatile float b = NAN;
volatile int c;
feclearexcept(FE_ALL_EXCEPT);
c = (a < b);
if (fetestexcept(FE_INVALID))
printf("FE_INVALID\n");
else
printf("Not invalid\n");
return 0;
}
На моей машине (Linux, march=broadwell
) возвращается «Неправильно».Я скомпилировал его, используя GCC v7.2.0, используя опцию -std=c11
(неиспользование ничего не изменило в результате).Излучаемая инструкция x86 - UCOMISS
, которая вызывает только исключения для сигнализации NaN - я ожидаю увидеть COMISS
, поскольку это вызовет исключение во всех сравнениях NaN, поскольку NaN неупорядочены независимо от того, сигнализируют они или нет.
Я допустил ошибку в своем коде или забыл какую-то опцию компилятора, чтобы сделать поведение IEEE-совместимым?Может ли это быть ошибка (или оптимизация производительности) в компиляторе, чтобы игнорировать необходимость вызывать исключение здесь?