2013-12-09 35 views
12

我想从C++函数中的cubature包中调用C例程以执行多维集成。使用从Rcpp中的其他包的C函数

我试图重现基础研发的例子是

library(cubature) 
integrand <- function(x) sin(x) 
adaptIntegrate(integrand, 0, pi) 

我可以称之为从RCPP该R功能以下this recipe from the gallery,但会有一些性能损失,转换从C/C来回++到R.从C++直接调用C函数似乎更明智。

C例程adapt_integratecubature出口与

// R_RegisterCCallable("cubature", "adapt_integrate", (DL_FUNC) adapt_integrate); 

我不知道如何将它从C++调用然而,。这是我的跛脚尝试,

sourceCpp(code = ' 
#include <Rcpp.h> 
using namespace Rcpp; 

// [[Rcpp::export]] 
double integrand(double x){ 
return(sin(x)); 
} 

// [[Rcpp::depends(cubature)]] 
// [[Rcpp::export]] 
Rcpp::List integratecpp(double llim, double ulim) 
{ 
    Rcpp::Function p_cubature = R_GetCCallable("cubature", "adapt_integrate"); 

    Rcpp::List result = p_cubature(integrand, llim, ulim); 
    return(result); 
} 
' 
) 

integratecpp(0, pi) 

这不能编译;显然我正在做一些非常愚蠢的事情,并且错过了将R_GetCCallable的输出转换为Rcpp::Function(或直接调用它?)的一些重要步骤。我读过几篇涉及函数指针的相关文章,但还没有看到使用外部C函数的例子。

回答

6

可惜cubature不出货的头在inst/include,所以你不得不借,从他们做这样的事情在你的代码:

typedef void (*integrand) (unsigned ndim, const double *x, void *, 
      unsigned fdim, double *fval); 

int adapt_integrate(
    unsigned fdim, integrand f, void *fdata, 
    unsigned dim, const double *xmin, const double *xmax, 
    unsigned maxEval, double reqAbsError, double reqRelError, 
    double *val, double *err) 
{ 
    typedef int (*Fun)(unsigned,integrand,void*,unsigned, 
     const double*,const double*, unsigned, double, double, double*, double*) ; 
    Fun fun = (Fun) R_GetCCallable("cubature", "adapt_integrate") ;   
    return fun(fdim,f,fdata,dim,xmin,xmax,maxEval,reqAbsError, reqRelError,val,err); 
} 

这可能是与维护者negociate一个好主意cubature,他在inst/include中发送声明,以便您只需使用LinkingTo

+0

非常感谢组装这些缺失的部分。不幸的是,我将不得不重新思考这个问题,因为从我看到的'adapt_integrate'将不会轻易接受使用armadillo的数据结构定义的integrand。为了完整性,您能否添加一个最小的使用示例? – baptiste

+0

它给你的是访问'cubature'注册的函数指针。我不知道你应该怎么处理C函数...... –

+0

确实,[考虑使用示例](http://ab-initio.mit.edu/wiki/index.php/Cubature#例子)我看到麻烦了:'adapt_integrate_v'需要指向诸如'* fdata'之类的对象,被积函数期望指针如'* fval',而我真正想要传递的参数是eg 'arma :: colvec'对象。我认为我不能在两者之间架起一座桥梁。我可能必须坚持使用R级接口,或者在C++中实现我自己的2D正交。 – baptiste

2

以前没有看到这个问题,它看起来像@Romain解决它。

为了完整起见,xtsRcppXts软件包提供了一个有关各方如何操作的工作示例。在xts,我们这样做(大约十功能)在(源)文件inst/include/xtsAPI.h

SEXP attribute_hidden xtsLag(SEXP x, SEXP k, SEXP pad) {  
    static SEXP(*fun)(SEXP,SEXP,SEXP) = NULL;   
    if (fun == NULL)         
     fun = (SEXP(*)(SEXP,SEXP,SEXP)) R_GetCCallable("xts","lagXts"); 
    return fun(x, k, pad);        
} 

R_registerRoutinesR_RegisterCCallable平时的业务一起。

RcppXts此作为

function("xtsLag", 
     &xtsLag,  
     List::create(Named("x"), Named("k"), Named("pad")), 
     "Extract the coredata from xts object"); 

其工作得很好拾取(在RCPP模块)。有人谴责我写xts方更紧凑(因为if NULL是虚假的),我最终会......。

+0

感谢指针,不幸的是,这是一个情况下,两个代码段之间的适当粘合会花费我更多的时间和痛苦,而不是实际使用较慢的R实现进行计算。否则,我会考虑直接链接到原始的容量代码,而不是通过使用旧版本的R软件包。 – baptiste

0

这个问题已经三岁,但现在我要指出的是,与RCPP多维的整合可能会更容易使RcppNumerical库可: https://github.com/yixuan/RcppNumerical

计算积分的程序是基于托马斯·哈恩的古巴包并且也可在CRAN的R2Cuba库中找到,因此如果您可以接受使用Cubature的功能adaptIntegrate()的古巴例程,则可能需要此包。

+0

感谢您的指针。不过,最好将它保留为注释,因为问题不是专门关于集成,而是关于从另一个包中访问C函数的问题。尽管我很欣赏这个链接,但我最终使用了我自己的复制版本,但是这看起来像是一个值得选择的选择(尤其是如果已经使用了Eigen,但我已经习惯了Armadillo)。立方体的一个优点是能够处理向量值的被积函数。 – baptiste

相关问题