指令 FYL2XP1

MZ9*_*Z97 4 floating-point x86 assembly instructions x87

我想知道为什么FYL2XP1x86 架构上的指令精确地计算数学公式 y · log 2 ( x + 1)。

这个公式有什么特别之处?

Mar*_*oom 9

y操作通常是一个编译时间常数,一时忘记了x + 1

由于log_b(x) = log_b(2) * log_2(x)该指令允许以 的任何底数计算对数x + 1
请注意,这log_b(2)是一个常数,因为很少需要计算具有基数自由度的对数。

FYL2XP1FYL2X是仅有的两条计算对数的 x87 指令。
如果对数是代数函数,一条指令就足够了,但由于它是超越的,英特尔给出了两个版本。

FYL2X适用于对数的整个域,但在整个范围内并不完全准确,特别是对于非常小的值x(可能更慢,我相信它必须进行范围缩减,使用截断的泰勒展开或帕德近似和而不是通过查表提高准确性)。

FYL2XP1而是仅适用于小范围内的输入 ±( 1 – sqrt(2) ? 2 )。
这应该更快(不减少范围),更重要的是,对于给定的输入范围,所使用的近似方法的精度应等于或大于 x87 80 位浮点精度。

此指令为接近 0 的 epsilon [寄存器 ST(0) 中的值] 的值提供最佳精度。对于较小的 epsilon (?) 值,使用 FYL2XP1 指令可以保留比使用 (?+ 1) 作为 FYL2X 指令的参数。

@Mysticial 的评论是一个点:在所有其他必要步骤之后, 使用
的算法FYL2X可能正在使用 的近似公式log(x + 1)
要将其转换为公式,log(x)输入必须减一。一x - 1,如果操作将失去精度x是非常小的(因为在两个数字的指数较大的差异会转移大部分x的数字向右边)。
FYL2XP1不会x - 1,也不会失去精度。

  • @Mysticial IIRC,最初的 8087 带有额外的三位用于内部计算,即总共 67 个尾数位。如果您确实需要了解,请查看 John F. Palmer、Stephen P. Morse,“The 8087 Primer”,Wiley 1984。如果 y=1,我认为 FYL2XP1 < 1 ulp 中的错误。对于 AMD 速龙处理器内的 x87 FPU,我们使用了 68 位内部精度。请参阅:Stuart F. Oberman,“浮点除法和平方根算法以及 AMD-K7™ 微处理器中的实现”,在 *Proceedings 14th IEEE Symposium on Computer Arithmetic*,第 106-115 页。IEEE 1999. FYL2XP1 中的误差 < 1 ulp 对于任何 x, y (4认同)
  • `log(x)` 的泰勒级数通常是关于 `x = 1` 完成的。所以每一项都会有`x - 1`。如果你试图为一个非常小的 `x` 计算 `log(x + 1)`,直接调用 `log(x + 1)` 将导致 `x + 1 - 1` 这将丢弃所有`x` 的低阶位 - 如果 `x` 非常小,则会失去精度。然后,内置的“log(x+1)”可以省略此“x + 1 - 1”步骤​​并保留完整精度。 (2认同)
  • 该系列是`log(x+1) = x - x^2/2 + x^3/3 - x^4/4...` 分母是线性的,因此可以忽略不计。`x = 1/sqrt(2)` 将每两个项下降 2 倍。(因为`x^2 = 1/2`)因此0.5 位/项。同样,对于给定的 `x`,收敛速度是 `-log(|x|)/log(2)` 比特/项,其中 `|x| < 1` 在复平面上。在这些界限之外,它会发生分歧。 (2认同)
  • @Mysticial Taylor 展开很少用于在固定大小的 FP 算术中计算超越数。Rafi Nave,“数值处理器上超越函数的实现”,*微处理和微编程* 11 (1983) 221-225 指出 8087 使用 CORDIC 和有理近似(大概是极小极大类)的组合来计算超越函数。对于 Athlon,对于主要近似区间上的 log2(1+x),我使用了恒等式 log(1+x) = 2*atanh(x/(x+2)),并使用了有理的极小极大近似来计算atanh()。需要的术语很少。 (2认同)