我正在尝试从c ++函数中的cubature包调用C例程来执行多维集成。
我正在尝试重现的基本R示例是
library(cubature)
integrand <- function(x) sin(x)
adaptIntegrate(integrand, 0, pi)
我可以在this recipe from the gallery之后从Rcpp调用这个R函数,但是从c / c ++到R来回切换会有一些性能损失。从C ++直接调用C函数似乎更合理。
C例程adapt_integrate
从cubature
导出
// 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函数的示例。
答案 0 :(得分: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);
}
与cubature
的维护人员进行交谈可能是个好主意,因为他在inst/include
中发布了声明,因此您只需要使用LinkingTo
。
答案 1 :(得分:4)
之前没有看过这个问题,看起来@Romain解决了这个问题。
为了完整起见,xts
和RcppXts
包提供了各方玩耍时如何执行此操作的工作示例。在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_registerRoutines
和R_RegisterCCallable
的常规业务。
在RcppXts
中,这个(在Rcpp模块中)被选为
function("xtsLag",
&xtsLag,
List::create(Named("x"), Named("k"), Named("pad")),
"Extract the coredata from xts object");
效果很好。有人谴责我更紧凑地写xts
方面(因为if NULL
是虚假的),我最终将会...... {/ p>
答案 2 :(得分:1)
这个问题现在已经有三年了,但我想指出,现在RcppNumerical库可用,与Rcpp的多维集成可能更容易: https://github.com/yixuan/RcppNumerical
计算积分的例程基于Thomas Hahn的古巴包,也可以在CRAN上的R2Cuba库中找到,所以如果你可以接受古巴例程而不是Cubature函数adaptIntegrate()
,那么这个包可能是感兴趣的。