我对C ++比较陌生,但我有一些(稀缺的)编码和数字经验。
我知道这个问题时不时会被发布,你如何整合数组。在MATLAB中你可以强制你的数组成为一个函数(我忘了怎么做,但我知道我以前做过)并将它发送给内置的集成器,所以我的问题是你是如何用C ++完成的。
我有这个积分:
I = integral(A(z)*sin(qz)*dz)
q只是双const,z是积分变量,但A(z)是一个数组(我将从现在开始称之为实函数),它在我的代码中与z轴具有相同的点数。积分边界是z [0]和z [nz-1]。
我使用梯形法则计算了这个积分,对于5000点的z轴,这需要0.06秒。我的问题是这个计算大约发生了300 * 30 * 20次(我有3个循环),这个0.06秒非常快地增长到模拟的3个小时。我的代码的整个瓶颈就是这种集成(我显然可以通过减少z加速,但这不是重点。)
我知道库函数通常比用户编写的函数要好得多。我也知道我不能使用更简单的东西作为辛普森的规则,因为被积函数是高度振荡的,我想避免自己实现一些复杂的数值算法。
GSL需要一种形式的功能:
F = f(double x,void * params)
我可以使用gsl的QAWO自适应集成,但是如何将我的函数转换为函数?
我在想的是:
F(double z, void *params)
{
std::valarray<double> actualfunction = *(std::valarray<double> *) params;
double dz = *(double *) params; // Pretty sure this is wrong
unsigned int actual_index = z / dz; // crazy assumption (my z[0] was 0)
return actualfunction[actual_index];
}
这样的事情可能吗?我怀疑数值算法会使用与实际函数相同的空间差异,我是否应该以某种方式对实际函数进行插值?
还有比gsl更好的东西吗?
答案 0 :(得分:0)
template<class F>
struct func_ptr_helper {
F f;
void* pvoid(){ return std::addressof(f); }
template<class R, class...Args>
using before_ptr=R(*)(void*,Args...);
template<class R, class...Args>
using after_ptr=R(*)(Args...,void*);
template<class R, class...Args>
static before_ptr<R,Args...> before_func() {
return [](void* p, Args...args)->R{
return (*static_cast<F*>(p))(std::forward<Args>(args)...);
};
}
template<class R, class...Args>
static after_ptr<R,Args...> after_func() {
return [](Args...args, void* p)->R{
return (*static_cast<F*>(p))(std::forward<Args>(args)...);
};
}
};
template<class F>
func_ptr_helper<F> lambda_to_pfunc( F f ){ return {std::move(f)}; }
使用:
auto f = lambda_to_pfunc([&actualfunction, &dz](double z){
unsigned int actual_index = z / dz; // crazy assumption (my z[0] was 0)
return actualfunction[actual_index];
});
然后
void* pvoid - f.pvoid();
void(*pfun)(double, void*) = f.after_func();
您可以通过pfun
和pvoid
。
为任何拼写错误道歉。
我们的想法是编写一个符合我们想要的lambda。然后lambda_to_pfunc
将它包装起来,这样我们就可以将它作为void*
和函数指针传递给C风格的API。