Быстрое сравнение IEEE с плавающей точкой больше нуля путем обмана

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

inline bool GreaterThanZero( float value )
{
const int value_as_int = *(int*)&value;
return ( value_as_int > 0 );
}

Глядя на сгенерированную сборку, киоски исчезли, и функция стала более производительной.

Это работает? Я в замешательстве, потому что все оптимизации для трюков IEEE используют SIGNMASKS и множество операций AND / OR (http://www.lomont.org/Math/Papers/2005/CompareFloat.pdf например). Помогает ли приведение к подписанному int? Тестирование в простой проводке не обнаруживает проблем.

Любое понимание было бы хорошо.

2

Решение

Выражение *(int*)&value > 0 тесты если value является любым положительным числом с плавающей точкой от наименьшего положительного денормаля (который имеет то же представление 0x00000001) до наибольшего конечного числа с представлением 0x7f7fffff) а также +inf (который имеет такое же представление, как 0x7f800000). Хитрость обнаруживает как положительное количество, но не все, представления NaN (представления NaN выше 0x7f800001). Хорошо, если вам не нужны некоторые значения NaN, делающие тест верным.

Это все работает из-за представление форматов IEEE 754.

Функции манипуляции с битами, которые вы видели в литературе для целей эмуляции операций IEEE 754, вероятно, были нацелены на идеальную эмуляцию с учетом особенностей поведения NaN и подписанные нули. Например, вариация *(int*)&value >= 0 не будет эквивалентно value >= 0.0f, так как -0.0fв виде 0x80000000 как без знака Int и, таким образом, как -0x80000000 как подписанный, делает последнее условие истинным, а первое ложным. Это может сделать такие функции довольно сложными.

Делает ли бросок подписанный int Помогите?

Ну да, потому что знак биты float а также int находятся в том же месте, и оба указывают положительное число, когда не установлено. Но состояние value > 0.0f может быть реализовано путем повторного перевода value как целое число без знака тоже.


Примечание: преобразование в int* адреса value нарушает строгие правила псевдонимов, но это может быть приемлемо, если ваш компилятор гарантирует, что он придает смысл этим программам (возможно, с параметром командной строки).

6

Другие решения


По вопросам рекламы [email protected]