Что предотвращает inlining sqrt при компиляции без -ffast-math [duplicate]

В дополнение к другим правильным ответам вы можете рассмотреть возможность масштабирования ваших значений, чтобы избежать проблем с арифметикой с плавающей запятой.

Например:

var result = 1.0 + 2.0;     // result === 3.0 returns true

... вместо:

var result = 0.1 + 0.2;     // result === 0.3 returns false

Выражение 0.1 + 0.2 === 0.3 возвращает false в JavaScript, но, к счастью, целочисленная арифметика в плавающей запятой является точной, поэтому ошибки с десятичным представлением можно избежать путем масштабирования.

В качестве практического примера, чтобы избежать проблем с плавающей запятой, где точность имеет первостепенное значение, рекомендуется обрабатывать деньги как целое число, представляющее число центов: 2550 центов вместо 25.50 долларов.


1 Дуглас Крокфорд: JavaScript: Хорошие детали: Приложение A - Ужасные части (стр. 105) .

14
задан Stone 5 March 2016 в 20:39
поделиться

1 ответ

Используется функция библиотеки sqrt для обработки ошибок. См. Документацию glibc: 20.5.4. Отчеты об ошибках с помощью математических функций : набор математических функций errno для совместимости с системами, которые не имеют флагов исключений IEEE754. Связано: glibc's math_error(7) справочная страница.

В качестве оптимизации сначала пытается выполнить квадратный корень с помощью встроенной команды sqrtsd, а затем проверяет результат на себя, используя ucomisd, которая устанавливает флаги следующим образом:

CASE (RESULT) OF
   UNORDERED:    ZF,PF,CF  111;
   GREATER_THAN: ZF,PF,CF  000;
   LESS_THAN:    ZF,PF,CF  001;
   EQUAL:        ZF,PF,CF  100;
ESAC;

В частности, сравнение QNaN с самим собой вернет UNORDERED, что и будет get, если вы попытаетесь взять квадратный корень из отрицательного числа. Это распространяется на ветвь jp. Проверка je - это просто паранойя, проверяющая точное равенство.


Также обратите внимание, что gcc имеет параметр -fno-math-errno , который пожертвует этой обработкой ошибок для скорости. Этот параметр является частью -ffast-math, но может использоваться сам по себе, не позволяя оптимизаторам, изменяющим результат.

sqrtsd сам по себе производит NaN для отрицательных и NaN-входов и устанавливает IEEE754 Неверный флаг. Проверка и ветвь - только , чтобы сохранить семантику errno -setting, на которую не полагается большинство кода.

-fno-math-errno является значением по умолчанию в Darwin (OS X) , где математическая библиотека никогда не устанавливает errno, поэтому функции могут быть встроены без этой проверки.

23
ответ дан Peter Cordes 26 August 2018 в 04:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: