我正在努力了解来自http://gruntthepeon.free.fr/ssemath/sse_mathfun.h的exp_ps()
或来自http://software-lisc.fbk.eu/avx_mathfun/avx_mathfun.h的exp256_ps()
的{{1}}的实施情况。
除了确定常量cephes_exp_C2
之外,我几乎了解计算中的所有内容。它似乎提高了计算的准确性。如果将其从计算中移除,则结果函数明显更快且稍微不那么精确(对于+/- 10左右的值,相对误差仍然低于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);