Есть случаи, когда вы знаете, что определенное выражение с плавающей точкой всегда будет неотрицательным. Например, при вычислении длины вектора выполняется sqrt(a[0]*a[0] + ... + a[N-1]*a[N-1])
(примечание: мне известно о std::hypot
, это не относится к вопросу), и выражение под квадратным корнем явно неотрицательно. Однако GCC выводит следующую сборку для sqrt(x*x)
:
mulss xmm0, xmm0
pxor xmm1, xmm1
ucomiss xmm1, xmm0
ja .L10
sqrtss xmm0, xmm0
ret
.L10:
jmp sqrtf
То есть он сравнивает результат x*x
с нулем, а если результат неотрицательный, он выполняет инструкцию sqrtss
, в противном случае он вызывает sqrtf
.
Итак, мой вопрос: как я могу заставить GCC предположить, что x*x
всегда неотрицателен, так что он пропускает сравнение и вызов sqrtf
, не записывая встроенную сборку?
Я хочу подчеркнуть, что меня интересует локальное решение, а не такие вещи, как -ffast-math
, -fno-math-errno
или -ffinite-math-only
(хотя они действительно решают проблему, благодаря ks1322, Гарольду и Эрику Постпишилу в комментарии).
Кроме того, "заставить GCC предполагать, что x*x
неотрицателен", следует интерпретировать как assert(x*x >= 0.f)
, поэтому это также исключает случай, когда x*x
является NaN.
Я в порядке с решениями для компиляторов, платформ, процессоров и т.д.