我正在编写基于LLVM的小型编程语言的数学函数, 而我目前对如何实现常见的舍入函数floor,ceil和round(to even)感到困惑。首先是因为我没有找到这些函数的任何算法描述,其次是因为我不熟悉LLVM具有的功能。四舍五入。
能够正确地舍入负数是必须的,舍入到特定的精度不是。舍入为整数值即可。简单地指出可以从LLVM bitcode使用的任何现有实现也将起作用。
答案 0 :(得分:1)
如果您查看Google代码搜索,则会有一些results。链接的示例假设IEEE浮点数。通常,普通PC的编译器只需将floor
编译为浮点指令。例如,原始的387算术处理器具有FPREM
指令,该指令或多或少地为floor
所需的一部分。
答案 1 :(得分:1)
您将要开始使用LLVM language reference manual。
你可以从实现trunc( )
开始,就像沿着这些方向做某事一样(警告,实际上不要使用它;它只是作为一个例子,并且不正确。见下面的讨论):
define float @trunc(float %x) {
%rounded = fptosi float %x to i32
%asFloat = sitofp i32 %rounded to float
ret float %asFloat
}
fptosi ... to ...
指令记录为根据舍入到零舍入模式将浮点值舍入为整数值。 sitofp ... to ...
指令将该值转换回浮点值以返回。
但是,这个实现存在问题;读取我链接的语言参考,“如果舍入到最接近的整数的结果不适合目标类型,则fptosi ... to ...
的行为是未定义的。”
这很容易解决,因为所有足够大的浮点数都已经是整数,并且不需要舍入;如果x
的绝对值大于或等于2 ^ 23,则可以返回x本身。
(这是单精度的全部;对于double,你可能想要使用i64
,你需要使用2 ^ 52的阈值
对于其他操作,例如floor
和round
,您可以从trunc
开始,然后检查剩余x - trunc(x)
并相应地调整结果。
或者,您可以调用主机平台的C库,该库已包含这些功能。这是许多编程语言采用的方法。
答案 2 :(得分:1)
我已经通过以下方式实现了浮点向量的底层:'截断'值x,然后比较x和trunc(x)。其中trunc(x)> x,减去1,因为floor(x)必须始终最多为x。 我在Haskell编写了这个代码。我不知道,这是否对你有所帮助。见floorLogical in http://code.haskell.org/~thielema/llvm-extra/src/LLVM/Extra/Vector.hs
圆形到均匀通常是昂贵的并且没有多大用处。我只是使用floor(x + 0.5)。 在SSE4.1中还有roundss,roundps et.al。