使用提供的R函数使用gsl_function

时间:2014-04-28 04:19:21

标签: c++ r rcpp gsl

我目前正在尝试使用.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 = &params;
  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;)。

我查找了类似的问题,但无法找到任何列出的内容......任何提示都将不胜感激!

非常感谢

3 个答案:

答案 0 :(得分:2)

我创建了一个工作示例(并针对C计时),您可以在其中将任意用户定义的R函数传递给GSL函数QAWF。您应该能够将其概括为其他gsl函数。

请参阅此处的示例:https://sites.google.com/site/andrassali/computing/user-supplied-functions-in-rcppgsl

如上所述,竞争C实现要快得多。

答案 1 :(得分:1)

快速评论:

  1. 你写道:我的C代码调用保存在全局环境中的用户定义的R函数(下面的代码中的SomeRFunction)。所以你的C代码仍然会减慢 a由于调用R的成本和R的较慢速度,在每个函数评估中都有很多

  2. 我的RcppDE包(也用于验证),例如使用外部指针(Rcpp::XPtr)将用户定义的C函数传递给优化器。灵活性相同。更好的速度。

  3. 你的编译错误正好在那个交叉点 - 你不能只是通过&#34;一个Rcpp对象到一个void指针。 Rcpp::XPtr可以帮助您,但您也需要知道自己在做什么,以便工作示例可能会有所帮助。

  4. 这实际上是一个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 = &params;

使用一些C ++ 11可变参数模板和元组,您可以将其概括为任何内容而不是(doubleint)对,但它更有效。