我不是 GSL 的常客,但我认为我通过包装2F1
GSL 提供的超几何函数使其工作,它会NaN
返回x=1. 然后,数值积分将使用此信息用于其目的,并且domain error
不会被抛出。
因此,(按照 GSL 文档中提供的示例)在函数中double f
我比较了传递的参数xsing_value
在浮点意义上具有域绑定(不要判断命名)。如果它们足够接近,我返回NaN
,否则,我调用 GSL 提供的2F1
函数。
#include <stdio.h>
#include <math.h>
#include <gsl/gsl_integration.h>
#include <gsl/gsl_sf_hyperg.h>
#include <limits>
double f (double x, void * params) {
double alpha = *(double *) params;
double sing_value = 1.0;
double diff = std::abs(x-sing_value);
bool singular_point = (diff <= std::numeric_limits<double>::epsilon()*std::abs(x+sing_value)*2);
// as per Kirill's comment, the comparison
// (diff < std::numeric_limits<double>::min())
// is unnecessary for any practical sense.
if (singular_point)
return std::numeric_limits<double>::quiet_NaN();
else
return gsl_sf_hyperg_2F1(1,2,3,alpha*x);
}
int
main (void)
{
gsl_integration_cquad_workspace * wcquad = gsl_integration_cquad_workspace_alloc (10000);
double result, error;
size_t nevals;
double expected = log(16);
double alpha = 1.0;
gsl_function F;
F.function = &f;
F.params = α
gsl_integration_cquad (&F, -1.0, 1.0, 0, 1e-14, wcquad, &result, &error,&nevals);
printf ("result = % .18f\n", result);
printf ("exact result = % .18f\n", expected);
printf ("estimated error = % .18f\n", error);
printf ("actual error = % .18f\n", result - expected);
printf ("# evaluations = %zu\n", nevals);
gsl_integration_cquad_workspace_free (wcquad);
return 0;
}
根据 Wolfram Alpha 的说法,
∫1−12F1(1,2,3,x)dx=ln16
这似乎已被代码确认
result = 2.772588722239701653
exact result = 2.772588722239781145
estimated error = 0.000000000000023683
actual error = -0.000000000000079492
# evaluations = 2553
该代码没有在容差、细分方面进行优化,尤其是,它无缘无故地混合了 C/C++。
在 gcc 6.4 和 GSL 2.4.2 上测试