2013-12-09 11 views
12

多次元統合を実行するためにC++関数のcubatureパッケージからCルーチンを呼び出そうとしています。Rcpp内の他のパッケージのC関数を使用

私が再現しようとしている基本的なRの例は、

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

である私はちょうどthis recipe from the gallery次RcppからこのR関数を呼び出すことができますが、C/Cから前後に切り替えるにはいくつかのパフォーマンスのペナルティが存在することになる++ C++からC関数を直接呼び出す方が合理的です。

adapt_integrateルーチンCは、私はしかし、C++からそれを呼び出す方法を理解していない

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

cubatureからエクスポートされます。ここで私の不自由な試みは、

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

残念ながらcubatureinst/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するのは良い考えかもしれませんcubatureinst/includeに宣言が含まれているので、LinkingToを使用するだけです。

+0

これらの不足している部分を組み立てていただきありがとうございます。残念ながら、私は 'adapt_integrate'がarmadilloのデータ構造を使って定義した被積分関数を簡単に受け入れることができないため、問題を再考する必要があります。完全性のために、最小限の使用例を追加できますか? – baptiste

+0

これは、 'cubature'が登録されている関数ポインタへのアクセスです。私は、あなたがC言語の関数を使って何をすべきかわからない... –

+0

確かに、[使用の例を考えて](http://ab-initio.mit.edu/wiki/index.php/Cubature#例)私は問題を先読みしています: 'adapt_integrate_v'は' * fdata'のようなオブジェクトへのポインタを期待していますが、integrandは '* fval'のようなポインタを期待しています。 'arma :: colvec'オブジェクトです。私は両者の間に橋渡しをすることはできないだろうと思う。私は、Rレベルのインターフェイスに固執するか、またはC++で私自身の2D直交を実装する必要があります。 – baptiste

2

この質問は先に表示されていませんでした。@Romainが解決したようです。

完全性のために、すべての当事者が一緒に遊んでいるときにこれを行う方法の実例は、xtsおよびRcppXtsパッケージによって提供されています。 xtsでは、我々はこれを行う(ソース)中(約10機能のための)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

ポインタのおかげで、残念なことに、これは2つのコードの間に適切な接着剤を開発することは、より遅いRの実装で実際に計算を行うよりも時間と苦しみが増えてしまうケースです。そうでなければ、古いバージョンを使用しているRパッケージではなく、元のキューブコードに直接リンクすることを検討します。 – baptiste

0

この質問は今3歳ですが、私はRcppNumericalライブラリが利用可能であることを今Rcppと多次元統合が容易になることを指摘したい: https://github.com/yixuan/RcppNumerical

積分を計算するためのルーチンはトーマス・ハーンのキューバに基づいていますCRANのR2Cubaライブラリにもありますので、Cubatureの関数adaptIntegrate()でキューバのルーチンを使用することができれば、このパッケージに興味があります。

+0

ポインタのおかげで。しかし、おそらくそれはコメントとして保管することが最善の方法です。なぜなら、質問は統合に関するものではなく、別のパッケージからC関数にアクセスすることだからです。私はリンクを感謝します、私は自分のキューブのコピーを使用して終了しましたが、これは価値ある選択肢のように見えます(特に、すでにEigenを使用している場合は特にですが、Armadilloに慣れています)。キューレットの利点の1つは、ベクトル値の被積分関数を処理する能力です。 – baptiste

関連する問題