4

我正在为一种基于 LLVM 的小型编程语言编写数学函数,我目前对如何实现常见的舍入函数 floor、ceil 和 round(甚至)感到困惑。首先是因为我还没有找到这些函数的任何算法描述,其次是因为我不熟悉 LLVM 具有哪些功能。四舍五入。

能够正确舍入负数是必须的,而不是舍入到特定精度。四舍五入到整数值就可以了。简单地指出可以从 LLVM 位码中使用的任何现有实现也将起作用。

4

3 回答 3

2

您将要从LLVM 语言参考手册开始。

您可以从按照这些思路实现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 本身。

(这都是单精度;对于双精度,您可能想要使用i64,并且您需要使用 2^52 的阈值)

对于其他操作,如floorround,您可以从 开始trunc,然后检查残差x - trunc(x)并相应地调整结果。

或者,您可以调用您的主机平台的 C 库,其中已经包含这些函数。这是许多编程语言采用的方法。

于 2010-08-24T22:29:44.277 回答
1

如果您查看 Google 代码搜索,会有一些结果。链接示例假定 IEEE 浮点数。通常,普通 PC 的编译器只是编译floor为浮点指令。例如,最初的 387 算术处理器具有FPREM或多或少地完成您需要的部分的指令floor

于 2010-08-18T03:51:51.663 回答
1

我通过以下方式为浮点向量实现了下限:“截断”值 x,然后比较 x 和 trunc(x)。如果 trunc(x)>x,则减 1,因为 floor(x) 必须始终最多为 x。我已经在 Haskell 中对此进行了编码。我不知道,这是否对你有帮助。请参阅http://code.haskell.org/~thielema/llvm-extra/src/LLVM/Extra/Vector.hs中的 floorLogical

舍入到偶数通常很昂贵,而且没有多大用处。我只是使用地板(x + 0.5)。SSE4.1中还有roundss、roundps等。

于 2012-05-23T20:18:44.197 回答