从log1pf()计算asinhf()的最准确方法是什么?

从log1pf()计算asinhf()的最准确方法是什么?,第1张

概述反双曲函数asinh()与自然对数密切相关.我试图确定从C99标准数学函数log1p()计算asinh()的最准确方法.为了便于实验,我现在仅限于IEEE-754单精度计算,这就是我在看asinhf()和log1pf().我打算重新使用完全相同的算法进行双精度计算,即asinh()和log1p(). 我的主要目标是最小化ulp错误,次要目标是最小化错误舍入结果的数量,在改进代码最多比下面发布的版本 反双曲函数asinh()与自然对数密切相关.我试图确定从C99标准数学函数log1p()计算asinh()的最准确方法.为了便于实验,我现在仅限于IEEE-754单精度计算,这就是我在看asinhf()和log1pf().我打算重新使用完全相同的算法进行双精度计算,即asinh()和log1p().

我的主要目标是最小化ulp错误,次要目标是最小化错误舍入结果的数量,在改进代码最多比下面发布的版本最低的约束下.任何提高准确度的改进,比如0.2 ulp,都是值得欢迎的.添加几个FMA(融合乘法 – 加法)会很好,另一方面我希望有人能够找到一个采用快速rsqrtf()(倒数平方根)的解决方案.

生成的C99代码应该适用于矢量化,可能是通过一些简单的直接转换.所有中间计算必须以函数参数和结果的精度发生,因为任何切换到更高精度可能会产生严重的负面性能影响.代码必须在IEEE-754非正常支持和FTZ(刷新到零)模式下正常工作.

到目前为止,我已经确定了以下两个候选实现.请注意,可以通过单次调用log1pf()轻松地将代码转换为无分支可向量化版本,但在此阶段我还没有这样做,以避免不必要的混淆.

/* for a >= 0,asinh(a) = log (a + sqrt (a*a+1))                        = log1p (a + (sqrt (a*a+1) - 1))                        = log1p (a + sqrt1pm1 (a*a))                        = log1p (a + (a*a / (1 + sqrt(a*a + 1))))                        = log1p (a + a * (a / (1 + sqrt(a*a + 1))))                        = log1p (fma (a / (1 + sqrt(a*a + 1)),a,a)                        = log1p (fma (1 / (1/a + sqrt(1/a*a + 1)),a)*/float my_asinhf (float a){    float fa,t;    fa = fabsf (a);#if !USE_RECIPROCAL    if (fa >= 0x1.0p64f) { // prevent overflow in intermediate computation        t = log1pf (fa) + 0x1.62e430p-1f; // log(2)    } else {        t = fmaf (fa / (1.0f + sqrtf (fmaf (fa,fa,1.0f))),fa);        t = log1pf (t);    }#else // USE_RECIPROCAL    if (fa > 0x1.0p126f) { // prevent underflow in intermediate computation        t = log1pf (fa) + 0x1.62e430p-1f; // log(2)    } else {        t = 1.0f / fa;        t = fmaf (1.0f / (t + sqrtf (fmaf (t,t,fa);        t = log1pf (t);    }#endif // USE_RECIPROCAL    return copysignf (t,a); // restore sign}

使用特定的log1pf()实现,该实现精确到< 0.6 ulps,我在所有232个可能的IEEE-754单精度输入上进行详尽测试时,我观察到以下错误统计数据.当USE_RECIPROCAL = 0时,最大错误为1.49486 ulp,并且有353,587,822个错误的舍入结果. USE_RECIPROCAL = 1时,最大误差为1.50805 ulp,并且只有77,569,390个错误的舍入结果. 在性能方面,如果倒数和完全除法占用大致相同的时间量,则变体USE_RECIPROCAL = 0将更快,但如果可获得非常快的互惠支持,则变体USE_RECIPROCAL = 1可能更快. 答案可以假设所有基本算术,包括FMA(融合乘法 – 加法)都是根据IEEE-754舍入到最接近或偶数模式正确舍入的.此外,可以使用更快,几乎正确舍入的版本的倒数和rsqrtf(),其中“几乎正确舍入”意味着最大的ulp误差将限制为0.53 ulps以及绝大多数结果,例如> 95%,正确圆润.可以使用定向舍入的基本算术,而无需额外的性能成本.

解决方法 首先,您可能需要研究log1pf函数的准确性和速度:这些函数在libms之间可能会有所不同(我发现OS X数学函数要快,glibc函数要慢,但通常是正确舍入的).

Openlibm基于BSD libm,而后者又基于Sun的fdlibm,按范围使用多种方法,但主要位是the relation:

t = x*x;w = log1pf(fabsf(x)+t/(one+sqrtf(one+t)));

您可能还想尝试使用-fno-math-errno选项进行编译,该选项会禁用sqrt的旧System V错误代码(IEEE-754异常仍然有效).

总结

以上是内存溢出为你收集整理的从log1pf()计算asinhf()的最准确方法是什么?全部内容,希望文章能够帮你解决从log1pf()计算asinhf()的最准确方法是什么?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1240391.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存