Как вы думаете, fabs()
и fabsf()
реализованы в вашей системе, или в этом отношении сравнения с константой 0? Если это не побитовые операции, это вполне возможно, потому что авторы компиляторов не думают, что это будет быстрее.
Проблемы с переносимостью этого кода:
- float и int могут не иметь одинаковую последовательность или даже одинаковый размер. Следовательно, маски тоже могут быть неправильными.
- float не может быть IEEE представлением
- Вы нарушаете строгие правила наложения имен. Компилятору разрешается предполагать, что указатель / ссылка на float и указатель / ссылка на int не могут указывать на одну и ту же ячейку памяти. Так, например, стандарт не гарантирует, что
r
инициализируется с 1.0, прежде чем он будет изменен в следующей строке. Это может изменить порядок операций. Это не пустое предположение, и в отличие от (1) и (2) оно не определено, не определено реализацией, поэтому вы не можете просто найти его для своего компилятора. При достаточной оптимизации я видел, что GCC пропускает инициализацию переменных с плавающей точкой, на которые ссылаются только через указатель типа.
Сначала я бы сделал очевидную вещь и проверил выдаваемый код. Только если это кажется хитрым, стоит подумать о чем-то другом. У меня нет особых причин думать, что я знаю больше о побитовом представлении чисел, чем мой компилятор; -)
inline float fast_sign(float f) {
if (f > 0) return 1;
return (f == 0) ? 0 : -1;
// or some permutation of the order of the 3 cases
}
[Редактировать: на самом деле, GCC делает что-то вроде еды даже с -O3. Передаваемый код не обязательно медленный, но он использует операции с плавающей запятой, поэтому неясно, что он быстрый. Поэтому следующим шагом является тестирование, проверка того, является ли альтернатива более быстрой на любом компиляторе, на который вы можете положиться, и если это так, сделайте это тем, что люди, портирующие ваш код, могут включить с помощью #define
или чем-то еще, в соответствии с результатами их собственный тест.]