我在许多正弦/余弦的实现中看到了所谓的扩展模块化精度算法。但是它的用途是什么? 例如在cephes implemetation中,在缩减到[0,pi / 4]范围之后,他们正在进行这种模块化精度算法以提高精度。
下面是代码:
z = ((x - y * DP1) - y * DP2) - y * DP3;
其中DP1,DP2和DP3是一些硬编码系数。 如何在数学上找到这些系数?我已经理解了大数字的“模块化扩展算术”的目的,但这里的确切目的是什么?
答案 0 :(得分:9)
在三角函数的参数减少的背景下,你所看到的是Cody-Waite参数减少,这是一本书中介绍的技术:William J. Cody和William Waite,基本函数软件手册< / em>,Prentice-Hall,1980。尽管subtractive cancellation在中间计算中,但目标是在一定幅度的论证中实现准确的减少的论证。为此,相关常量用超过原始精度表示,使用多个递减幅度的数字之和(此处:DP1
,DP2
,{{1这样,除了最不重要的产品之外的所有中间产品都可以在没有舍入误差的情况下进行计算。
以IEEE-754 DP3
(单精度)中sin(113)的计算为例。典型的参数减少在概念上会计算binary32
。最接近π/ 2的i=rintf(x/(π/2)); reduced_x = x-i*(π/2)
数字为binary32
。我们计算0x1.921fb6p+0
,产品轮次为i=72
,接近参数0x1.c463acp+6
。在减法期间,一些前导位取消,我们结束x=0x1.c40000p+6
。注意重整化引入的尾随零。这些零位不携带有用的信息。对减少的参数reduced_x = -0x1.8eb000p-4
应用精确的近似值,而真实的结果是sin(x) = -0x1.8e0eeap-4
。我们结束了较大的相对误差和较大的ulp误差。
我们可以通过使用两步Cody-Waite参数减少来解决这个问题。例如,我们可以使用-0x1.8e0e9d39...p-4
和pio2_hi = 0x1.921f00p+0
。注意pio2_lo = 0x1.6a8886p-17
的单精度表示中的八个尾随零位,这允许我们乘以任何8位整数pio2_hi
,并且仍然可以将产品i
表示为 < / em>作为单精度数。当我们计算i * pio2_hi
时,我们得到((x - i * pio2_hi) - i * pio2_lo)
,因此得到reduced_x = -0x1.8eafb4p-4
,这是一个非常准确的结果。
将常量分割为和的最佳方法取决于我们需要处理的sin(x) = -0x1.8e0e9ep-4
的大小,取决于给定参数范围的减法消除的最大位数(基于接近整数的程度) π/ 2的倍数可以得到整数)和性能考虑因素。典型的现实使用案例涉及两到四级的Cody-Waite减少方案。融合多重加法(FMA)的可用性允许使用具有较少尾随零比特的组成常数。参见本文:Sylvie Boldo,Marc Daumas和Ren-Cang Li,“用融合的乘法加法正式验证了参数的减少。” IEEE Transactions on Computers ,58:1139-1145,2009。对于使用i
的工作示例,您可能希望查看one of my previous answers中的代码。