exp()函数的数值计算中的系数

时间:2016-07-24 09:42:05

标签: c++ c avx2

我正在努力了解来自http://gruntthepeon.free.fr/ssemath/sse_mathfun.hexp_ps()或来自http://software-lisc.fbk.eu/avx_mathfun/avx_mathfun.hexp256_ps()的{​​{1}}的实施情况。
除了确定常量cephes_exp_C2之外,我几乎了解计算中的所有内容。它似乎提高了计算的准确性。如果将其从计算中移除,则结果函数明显更快且稍微不那么精确(对于+/- 10左右的值,相对误差仍然低于1%)。我在其他数值库中找到了这样的系数,但没有更详细的解释。

1 个答案:

答案 0 :(得分:2)

在对Cephes来源进行一些搜索后,我认为这是Pommier翻译中的一个错误。这不是我第一次看到Pommier代码中的错误。我建议在Gromacs中使用数学库。

来自Cephe的exp.c

static double C1 = 6.93145751953125E-1;
static double C2 = 1.42860682030941723212E-6;
....
px = floor( LOG2E * x + 0.5 );
n = px;
x -= px * C1;
x -= px * C2;

来自Pommier,

_PS_CONST(cephes_exp_C1, 0.693359375);
_PS_CONST(cephes_exp_C2, -2.12194440e-4);  <-- Wrong value
....

//
//  fx = LOG2E * x + 0.5
//
fx = _mm_mul_ps(x, *(v4sf*)_ps_cephes_LOG2EF);
fx = _mm_add_ps(fx, *(v4sf*)_ps_0p5);

//
//  fx = floor(fx)
//
emm0 = _mm_cvttps_epi32(fx);
tmp  = _mm_cvtepi32_ps(emm0);
v4sf mask = _mm_cmpgt_ps(tmp, fx);    
mask = _mm_and_ps(mask, one);
fx = _mm_sub_ps(tmp, mask);

//
//  x -= fx * C1;
//  x -= fx * C2;  (Using z allows for better ILP in this step)
//
tmp = _mm_mul_ps(fx, *(v4sf*)_ps_cephes_exp_C1);
v4sf z = _mm_mul_ps(fx, *(v4sf*)_ps_cephes_exp_C2);
x = _mm_sub_ps(x, tmp);
x = _mm_sub_ps(x, z);