我正在尝试在项目中使用 boost 的贝塞尔函数 (cyl_bessel_j)。但是,我发现在调用该函数大约 2000 次后,它返回的结果带有错误的符号。
我已经在两台机器上对此进行了测试,一台是 CentOS 5.8 (Final) 机器,奇怪的是它能正常工作,另一台是 RHEL 6.3 (Santiago) 机器,但它失败了。
两台机器都使用 Boost 1.50.0 和 13.1.3 20130607 Intel 编译器。 CentOS机器使用gcc 4.1.2 20080704,RHEL机器使用gcc 4.4.6 20120305。
这是我的代码:
template<typename FloatType> FloatType funcT(FloatType z, FloatType phi,
int n, int m, int p)
{
using namespace boost::math;
FloatType sqrt2PiZ = sqrt((2 * M_PI)/z);
FloatType nrmLeg = normalizedLegendre(n,m,-sin(phi));
FloatType besselJ = cyl_bessel_j(p + 0.5, z);
std::cout << " " << p << "," << z << " besselJ: " << besselJ << std::endl;
return sqrt2PiZ * nrmLeg * besselJ;
}
在两台机器上运行,我发现两者之间唯一不同的术语是 besselJ 术语。对于函数的第一个 1980 调用,它们返回相同的结果,但是,在第 1981 次调用中,RHEL 机器突然切换结果。前几个失败的术语打印如下(RHEL SIDE):
...
1,7.90559 besselJ: -0.0504874
2,7.90559 besselJ: 0.264237
3,7.90559 besselJ: 0.217608
...
在 MATLAB 中使用 besselJ 函数运行引用测试,我发现对于这些输入,符号应该颠倒,而且 CentOS 机器确实与 MATLAB 一致。
我决定用 besselJ 函数编写一个简单的 hello-world 风格的例子来尝试确定失败的原因:
#include <boost/math/special_functions/bessel.hpp>
#include <iostream>
int main(int argc, char** argv)
{
double besselTerm = boost::math::cyl_bessel_j(1.5, 7.90559);
std::cout << besselTerm << std::endl;
}
此测试在两台 机器上返回预期值 0.0504874。
此时,我正竭尽全力试图确定问题的原因。这似乎是一些奇怪的编译器错误或堆栈损坏。但是,堆栈损坏如何给出除了一位之外的准确正确答案?
有没有人在使用 boost 或 Intel 编译器时遇到过这样的问题?
附加信息: 已经发现最小案例测试在 GCC 4.4.6 上使用 --fast-math 标志中断。我还能够通过使用 -std=c++11 标志(这是较大的项目使用的标志)使英特尔编译器失败的最小测试用例。
最佳答案
一个 bug 被提交到 boost 库 trac 系统。
然而,发现问题出在 std c++ 库中,并表明 GCC 4.4.7 中存在问题。
Boost 开发人员创建了一个变通补丁来解决该问题: https://github.com/boostorg/math/commit/9f8ffee4b7a3f82b1c582735d43522d7d0cde746
关于c++ - 可能的编译器错误 : Weird results using boost bessel functions with Intel compiler between two machines?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22178333/