c++ 中用于数值积分的局部函数的解决方法
workaround to local functions in c++ for numerical integration
对于与物理相关的计算,我需要对一个四维积分进行数值计算,该积分取决于需要改变的几个参数;这样它们就不能被全局定义。我正在使用提供以下功能的 Cuba 包:
Cuhre(NDIM, NCOMP, Integrand , USERDATA, NVEC,EPSREL, EPSABS, VERBOSE | LAST,MINEVAL,
MAXEVAL, KEY,STATEFILE, SPIN,&nregions, &neval, &fail, integral, error, prob);
参数 "Integrand" 是一个预期按以下方式定义的函数:
int Integrand(const int *ndim, const cubareal xx[],const int *ncomp,
cubareal ff[], void *userdata) ;
我的问题是我想集成一个函数,该函数依赖于我想在程序中改变的连续参数。我的意思是我的被积函数取决于几个额外的参数,比如 a、b、c。
然后我想在本地定义类似于 Integrand 函数的东西,即在参数 a、b 和 c 固定的范围内,以便它具有正确的形式作为参数传递给 Cuhre功能。
然后我想我也许可以将所有内容都放入 class 例如:
class integrate{
private: // parameters
public:
//constructor
int Integrand(...){
// calculation involving the parameters
}
};
并将函数定义为 class 的方法。
然而,这不起作用,因为我不能将非静态对象方法传递给函数,而且,使方法静态化也会迫使我将参数设置为静态,这意味着我将无法在程序中初始化它们。
有什么解决方法吗?
如果我理解正确,如果你不想使用userdata
,你可以使用闭包:
// local parameter variables
T1 param1 = ...;
T2 param2 = ...;
T3 param3 = ...;
// capture params in a lambda expression
auto myIntegrand = [param1, param2, param3](const int *ndim, const cubareal xx[], const int *ncomp, cubareal ff[], void *userdata) {
stuff(param1);
stuff(param2);
stuff(param3);
};
// can now pass around myIntegrand
这只是创建一个 class 的快捷方式,它将这些参数作为成员变量,并将指针传递给 class 实例的方法。
小心你是想按值(可能是昂贵的复制)还是按引用(可能变得无效并炸毁你的程序)来捕获。
[编辑:因为你误解了 userdata 指针,正如我从评论中看到的,让我告诉你如何使用它:]
struct Parameters
{
int a, b, c; // TODO: appropriate defaults
};
int integrand
(
const int* ndim, const cubareal xx[],
const int* ncomp, cubareal ff[],
void* userdata
)
{
Parameters* p = reinterpret_cast<Parameters*>(userdata);
/* calculations using p->a, p->b, p->c */
}
int main(int argc, char* argv[])
{
Parameters p;
/* fill in parameters appropriately, e. g. parsing command line parameters */
Cuhre(/* other parameters */, &integrand, &p, /* remaining parameters */);
}
我以前的解决方案仍然是替代方案...
.cpp 文件:
namespace
{
int g_a = 0; // appropriate default values...
int g_b = 0;
int g_c = 0;
};
void setIntegrationParameters (int a, int b, int c)
{
g_a = a;
g_b = b;
g_c = c;
}
int integrand
(
const int* ndim, const cubareal xx[],
const int* ncomp, cubareal ff[],
void* userdata
)
{
/* calculations using g_a, g_b, g_c */
}
.h 文件:
void setIntegrationParameters (int a, int b, int c);
int integrand
(
const int* ndim, const cubareal xx[],
const int* ncomp, cubareal ff[],
void* userdata
);
并且在您的主程序中,您可以 e. G。解析命令行参数计算a、b、c并通过setIntegrationParameters将它们设置为集成参数。
(您可以对 C 代码执行完全相同的操作,当然然后使用 C-Casts 和静态全局变量而不是匿名名称空间...)
对于与物理相关的计算,我需要对一个四维积分进行数值计算,该积分取决于需要改变的几个参数;这样它们就不能被全局定义。我正在使用提供以下功能的 Cuba 包:
Cuhre(NDIM, NCOMP, Integrand , USERDATA, NVEC,EPSREL, EPSABS, VERBOSE | LAST,MINEVAL,
MAXEVAL, KEY,STATEFILE, SPIN,&nregions, &neval, &fail, integral, error, prob);
参数 "Integrand" 是一个预期按以下方式定义的函数:
int Integrand(const int *ndim, const cubareal xx[],const int *ncomp,
cubareal ff[], void *userdata) ;
我的问题是我想集成一个函数,该函数依赖于我想在程序中改变的连续参数。我的意思是我的被积函数取决于几个额外的参数,比如 a、b、c。
然后我想在本地定义类似于 Integrand 函数的东西,即在参数 a、b 和 c 固定的范围内,以便它具有正确的形式作为参数传递给 Cuhre功能。
然后我想我也许可以将所有内容都放入 class 例如:
class integrate{
private: // parameters
public:
//constructor
int Integrand(...){
// calculation involving the parameters
}
};
并将函数定义为 class 的方法。 然而,这不起作用,因为我不能将非静态对象方法传递给函数,而且,使方法静态化也会迫使我将参数设置为静态,这意味着我将无法在程序中初始化它们。
有什么解决方法吗?
如果我理解正确,如果你不想使用userdata
,你可以使用闭包:
// local parameter variables
T1 param1 = ...;
T2 param2 = ...;
T3 param3 = ...;
// capture params in a lambda expression
auto myIntegrand = [param1, param2, param3](const int *ndim, const cubareal xx[], const int *ncomp, cubareal ff[], void *userdata) {
stuff(param1);
stuff(param2);
stuff(param3);
};
// can now pass around myIntegrand
这只是创建一个 class 的快捷方式,它将这些参数作为成员变量,并将指针传递给 class 实例的方法。
小心你是想按值(可能是昂贵的复制)还是按引用(可能变得无效并炸毁你的程序)来捕获。
[编辑:因为你误解了 userdata 指针,正如我从评论中看到的,让我告诉你如何使用它:]
struct Parameters
{
int a, b, c; // TODO: appropriate defaults
};
int integrand
(
const int* ndim, const cubareal xx[],
const int* ncomp, cubareal ff[],
void* userdata
)
{
Parameters* p = reinterpret_cast<Parameters*>(userdata);
/* calculations using p->a, p->b, p->c */
}
int main(int argc, char* argv[])
{
Parameters p;
/* fill in parameters appropriately, e. g. parsing command line parameters */
Cuhre(/* other parameters */, &integrand, &p, /* remaining parameters */);
}
我以前的解决方案仍然是替代方案...
.cpp 文件:
namespace
{
int g_a = 0; // appropriate default values...
int g_b = 0;
int g_c = 0;
};
void setIntegrationParameters (int a, int b, int c)
{
g_a = a;
g_b = b;
g_c = c;
}
int integrand
(
const int* ndim, const cubareal xx[],
const int* ncomp, cubareal ff[],
void* userdata
)
{
/* calculations using g_a, g_b, g_c */
}
.h 文件:
void setIntegrationParameters (int a, int b, int c);
int integrand
(
const int* ndim, const cubareal xx[],
const int* ncomp, cubareal ff[],
void* userdata
);
并且在您的主程序中,您可以 e. G。解析命令行参数计算a、b、c并通过setIntegrationParameters将它们设置为集成参数。
(您可以对 C 代码执行完全相同的操作,当然然后使用 C-Casts 和静态全局变量而不是匿名名称空间...)