你已经问了几个琐碎的问题,你可以通过查看C编译器如何做到这一点来回答.从那里,您可以查看它使用的说明,并决定您想要实际使用哪些.(在libm中有大量不同的舍入函数,因此首先选择正确的舍入函数并不总是那么容易).
使用-O3 -ffast-math内联获取最简单的libm函数(因为它不必errno在NaN上设置,或者像这样设置垃圾).
无论如何,编译器输入和输出,来自Godbolt Compiler Explorer上的gcc 5.3:
#include <math.h>
int floor_double(double x) { return (int) floor(x); }
roundsd xmm0, xmm0, 9
cvttsd2si eax, xmm0
ret
int truncate_double(double x) { return (int)x; }
cvttsd2si eax, xmm0
ret
Run Code Online (Sandbox Code Playgroud)
有关英特尔指令集参考手册pdf的链接,请参阅x86标签wiki.还有一个从PDF生成的非官方HTML版本.
cvttsd2si截断为零,trunc()而不是像floor()函数那样向-Infinity舍入.
这就是当该指令集可用时floor()编译为SSE4.1 的原因roundsd.(否则它必须摆弄舍入模式,你可以通过删除或更改-marchgodbolt上的选项来看到).
还有转换指令的打包版本,例如CVTTPD2DQ`一次执行2.(或AVX 4).