在RU模式下用FPU计算RD(sqrt(x))
只要任何结果区间的上限是在上舍入时计算的,而下舍入在下舍入时,浮点边界的区间就可以用来过度逼近集合的实数。
一个推荐的技巧是实际计算下界的否定。 这可以使FPU始终保持在圆形上(例如,“浮点运算手册”,2.9.2)。
这适用于加法和乘法。 另一方面,平方根运算在加法和乘法方面不是对称的。
对我来说,为了计算sqrtRD,对于下限,尽管存在其复杂性,但下面的习惯用法在IEEE 754双精度和FLT_EVAL_METHOD
定义为0的普通平台上可能比两次更改舍入模式更快:
#include <fenv.h>
#include <math.h>
#pragma STDC FENV_ACCESS ON
…
/* assumes round-upwards */
double sqrt_rd(double l) {
feclearexcept(FE_INEXACT);
double candidate = sqrt(l);
if (fetestexcept(FE_INEXACT))
return nextafter(candidate, 0);
return candidate;
}
我想知道这是否更好,以及它是否是最快的。 作为一种可能的选择,但仍然不一定是最快的,在我看来,FMARU(候选人,候选人-l)可能并不总是确切的(因为有了定向四舍五入),但对于以下情况可能足够精确到0左右工作:
/* assumes round-upwards */
double sqrt_rd(double l) {
double candidate = sqrt(l);
if (fma(candidate, candidate, -l) != 0.0)
return nextafter(candidate, 0);
return candidate;
}
还有哪些其他便宜的方法可以检测到sqrt
是不准确的? 浮点运算的组合导致在现代FPU集合上sqrt_rd
的最快计算向上舍入?
我认为你应该可以使用:
/* assumes round-upwards */
double sqrt_rd(double l) {
double u = sqrt(l);
double w = u*u;
if (w != l)
return nextafter(u, 0);
return u;
}
这里的理由是如果u
是不精确的,那么这将是比√严格地l
,这反过来又意味着, w
> = u
2> l
(因为w
在RU模式也计算)。 如果u
是确切的,那么w
也是如此(因为我们知道它必须表示为双精度)。
fma以无限精度计算结果,然后应用舍入模式。
如果你的候选人太大,那么无限精确的结果大于0,并且因为你正在四舍五入,所以它会被取整。 即使它只比零大一点点。 为了验证这一点,首先尝试l = 1 + 2eps,其中(1 + eps)= sqrt(1 + 2eps + eps ^ 2)只是一点点太大; 然后缩小4的负幂,使eps ^ 2远远超出非规格化数的分辨率,并检查。
链接地址: http://www.djcxy.com/p/85613.html