Этаж / потолок с одной инструкцией доступен только с SSE4.1 roundsd
/ roundpd
, и только для XMM, не устаревшего x87.
С x87 вы устанавливаететекущий режим округления и затем используйте frndint
. (http://www.ray.masmcode.com/tutorial/fpuchap1.htm показывает, где биты RC находятся в контрольном слове x87). Доступные режимы округления: ближайший-четный (по умолчанию), в направлении + Inf (ceil), в направлении -Inf (floor) и в направлении нуля (trunc).
Не забудьте установить режим округления обратно, когдавсе готово.
Очевидно, frndint
медленно работает на некоторых процессорах (https://agner.org/optimize), так что на самом деле преобразование в целое число может быть быстрее и с fistp
/ fild
(все еще срежим округления установлен соответствующим образом.) Но это работает только для значений FP, которые могут быть представлены в виде 64-разрядного целого числа со знаком (при условии, что вы используете операнд памяти qword). Вместо этого вы можете добавить / вычесть соответствующее магическое число (чтобы сделать значениедействительно большое принудительное округление.) Опять же, это может потребовать установки режима округления.
Конечно, если вы хотите (int)floor(x)
, тогда определенно просто fistp
с установленным режимом округленияпо желанию.
В SSE3 вы можете использовать fisttp
для усечения до нуля (он был добавлен для ускорения приведения C float-> int в коде, который все еще хочет использовать устаревший x87, даже если SSEдоступен).
floor == trunc
для неотрицательных значений, чтобы вы могли воспользоваться эффективным усечением fisttp
или SSE XMM для этого случая.
В SSE4.1 для скалярных double
в регистрах XMM вы будете использовать roundsd
для округления до ближайшего целочисленного значения double
с выбранным вами режимом округления, определяемым какнепосредственный операнд. (Не преобразование, просто двойное> двойное округление, как frndint
, поэтому оно работает для любого значения). Доступны упакованные и скалярные версии с одинарной и двойной точностью.
С SSE4.1, roundsd
+ cvtsd2si
- ваш лучший выбор для (int)floor(x)
. Или , если вы знаете, что ваше значение неотрицательно, вы можете просто использовать SSE2 cvttsd2si
. Обратите внимание на дополнительные t
для «усечения». (То же самое для одинарной точности или для упакованного SIMD с cvtpd2dq
.)