我目前正在尝试使用.cpp文件通过RcppGSL从GSL库中使用gsl_function并使用sourceCpp()调用它。我们的想法是与GSL的gsl_integration_qags进行数值集成。我的C代码调用保存到全局环境中的用户定义的R函数(下面的代码中的SomeRFunction)。代码是:
#include <RcppGSL.h>
#include <stdio.h>
#include <math.h>
#include <gsl/gsl_integration.h>
#include <gsl/gsl_vector.h>
// [[Rcpp::depends(RcppGSL)]]
// [[Rcpp::export]]
double integfn1(double ub, double lb, double abserr, double Rsq, int pA){
double result, abserror;
Rcpp::Environment global = Rcpp::Environment::global_env();
Rcpp::Function f1 = global["SomeRFunction"];
struct my_f_params { double Rsq; int pA; };
struct my_f_params params = { Rsq, pA };
gsl_function F;
F.function = & f1;
F.params = ¶ms;
double lb1 = lb;
double ub1 = ub;
gsl_integration_workspace * w = gsl_integration_workspace_alloc (1000);
gsl_integration_qags (&F, lb1, ub1, 1e-8, 1e-8, 1000, w, &result, &abserror);
printf ("result = % .18f\n", result);
printf ("estimated error = % .18f\n", abserror);
gsl_integration_workspace_free (w);
return result;
}
出现以下错误:
"cannot convert 'Rcpp::Function* {aka Rcpp::Function_Impl<Rcpp::PreserveStorage>*}' to 'double (*)(double, void*)' "
问题在于我声明要集成的功能是什么(即&#34; F.function = & f1;
&#34;)。
我查找了类似的问题,但无法找到任何列出的内容......任何提示都将不胜感激!
非常感谢
答案 0 :(得分:2)
我创建了一个工作示例(并针对C计时),您可以在其中将任意用户定义的R函数传递给GSL函数QAWF。您应该能够将其概括为其他gsl函数。
请参阅此处的示例:https://sites.google.com/site/andrassali/computing/user-supplied-functions-in-rcppgsl
如上所述,竞争C实现要快得多。
答案 1 :(得分:1)
快速评论:
你写道:我的C代码调用保存在全局环境中的用户定义的R函数(下面的代码中的SomeRFunction)。所以你的C代码仍然会减慢 a由于调用R的成本和R的较慢速度,在每个函数评估中都有很多
我的RcppDE包(也用于验证),例如使用外部指针(Rcpp::XPtr
)将用户定义的C函数传递给优化器。灵活性相同。更好的速度。
你的编译错误正好在那个交叉点 - 你不能只是通过&#34;一个Rcpp对象到一个void指针。 Rcpp::XPtr
可以帮助您,但您也需要知道自己在做什么,以便工作示例可能会有所帮助。
这实际上是一个Rcpp问题,但你没有添加标签,所以我就这么做了。
答案 2 :(得分:1)
F.function
需要此签名double (*) (double x, void * params)
的功能,因此该功能需要double
,然后是void*
。如果你想要飞行,你需要帮助Rcpp::Function
。
这是典型的C
apis剥离类型。因此,您需要提供function
的内容是了解您拥有params
的内容并且能够使用正确的参数调用R函数并转换为double。这样做的简单方法是将R函数视为数据,因此增加struct
使其成为这样:
struct my_f_params { double Rsq; int pA; Function& rfun };
这样,您作为function
传递的函数可以是这样的:
double proxy_fun( double x, void* params ){
my_f_params* data = reinterpret_cast<my_f_params*>(params) ;
return as<double>( data->rfun(x, data->Rsq, data->pA ) ) ;
} ;
所以你可以建立你的gsl_function
这样的东西:
my_f_params params = { Rsq, pA, f1 };
gsl_function F ;
F.function = &proxy_fun ;
F.params = ¶ms;
使用一些C ++ 11可变参数模板和元组,您可以将其概括为任何内容而不是(double
,int
)对,但它更有效。