我正在尝试用GSL数值计算一些棘手的积分,我希望该实现方案能够从GSL实施方案中分离出被积分数,以使我的代码更具可读性(和可调试性)。这些是实际评估我的模型的函数,它们中的内容并不重要:
double Integrand1(double *k, size_t dim, void *params) {
double result = k[0]*k[1]*k[2];
return result;
}
double Integrand2(double *k, size_t dim, void *params) {
double result = k[0]-k[1]-k[2];
return result;
}
这就是我遇到麻烦的地方,试图抽象对GSL的调用。注意gsl_monte_function G
的类型约束:
void EvalIntegral(double &func, int_info ¶ms,double *xl,double *xu,size_t dim,
double &result,double &error){
const gsl_rng_type *T;
gsl_rng *r;
gsl_monte_function G;
G.f = &func; //This must be double (*)(double *,size_t,void *)
G.dim = dim; //This must be size_t
G.params = ¶ms; //This is a struct holding some variables
size_t calls = 5e5;
gsl_rng_env_setup();
T = gsl_rng_default;
r = gsl_rng_alloc(T);
gsl_monte_vegas_state *s = gsl_monte_vegas_alloc(dim);
gsl_monte_vegas_integrate(&G,xl,xu,dim,1e5,r,s, &result,&error);
gsl_monte_vegas_free (s);
gsl_rng_free (r);
}
我设置了上述功能,以减少其他功能的混乱:
void Evaluate(double x, double y){
int_info params;
params.x = x;
params.y = y;
//Lower limits to the variables
double xl[3] = {0.,-100.,0.};
//Upper limits to the variables
double xu[3] = {100.,100.,1.};
double result1, result2, error1, error2;
EvalIntegral(&Integrand1,¶ms,xl,xu,3,&result1,&error1);
EvalIntegral(&Integrand2,¶ms,xl,xu,3,&result2,&error2);
}
但是,当我编译时,它似乎拒绝我传递被积函数:
error: cannot convert ‘double*’ to ‘double (*)(double*, size_t, void*)’ {aka ‘double (*)(double*, long unsigned int, void*)’} in assignment
G.f = &func;
^~~~
我有点困惑,当我将EvalIntegral
的内容复制到Evaluate
两次并将func
替换为Integrand1
和Integrand2
时,所有这些工作正常。如何使编译器确信func
是具有正确原型的函数?
编译器为您提供答案:您需要一个函数指针类型来代替double&
:
void EvalIntegral(double (*func)(double*, std::size_t, void*), ...)