2013-12-09 60 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

相關問題