library(Rcpp)
vignette("Rcpp-attributes")
- とすることで"Rcpp Attributes.pdf"という文書が読める
- Rcppはいくつかの解説文書を持つが、この"Rcpp Attributes.pdf"は比較的新しい方の文書で、sourceCpp()関数によるseamless between c++ and Rの機能の追加に関する(ことが多い)記事になっている
- Rcpp::export
- sourceCpp()を使うことでRからc++製の関数が使えるようにする仕組み
#include <Rcpp.h>
using namespace Rcpp;
NumericVector convolveCpp(NumericVector a, NumericVector b) {
int na = a.size(), nb = b.size();
int nab = na + nb - 1;
NumericVector xab(nab);
for (int i = 0; i < na; i++)
for (int j = 0; j < nb; j++)
xab[i + j] += a[i] * b[j];
return xab;
}
-
- がある。これは、「コメント行だけど、ルールとして、このコメント行が出たら、以下のc++の関数がRで使えるように処理しなさいよ、という命令とみなされるようにしてある(Rcppの仕様で)ので、「大事で特別なコメント行」
- c++ソースにRのコードも入れちゃえ
- c++を書いていて、それをRで使えるようにしたいのです…というのがこのsourceCpp()の真骨頂なわけで、だとしたら、c++を書いてコンパイルしたら、Rでそれを使って見せてしまいたい、という気になるのはみな同じ(そうでなければ、いちいちコンパイル後にRで実行しないといけない)
- それを解消するべく、Rでの使用もc++ファイルに書いてしまえるようにしてある。ここでもまた、書式を決めたコメント行で、そのような扱いにすることにしてある
- 以下で、c++を書いたあと、指定の書式で対応するRの関数も書いておいて、その後、c++由来の関数とRで書いた関数を実行して見せている
#include <RcppArmadilloExtensions/sample.h>
using namespace Rcpp ;
NumericMatrix sphere_n2(int n,double r) {
NumericMatrix x(n,2);
for(int i=0;i<n;++i){
x(i,0) = 2*pow(M_PI,(i+1.0)/2)/exp(lgamma((i+1.0)/2))*pow(r,i);
x(i,1) = pow(M_PI,(i+1.0)/2)/exp(lgamma((i+1.0)/2+1))*pow(r,i+1);
}
return x;
}
> sourceCpp("sphere_n2.cpp")
> sphere_n.R <- function(n,r){
+ ret <- matrix(0,n,2)
+ for(i in 1:n){
+ ret[i,1] <- 2*pi^(i/2)/gamma(i/2)*r^(i-1)
+ ret[i,2] <- pi^(i/2)/gamma( .... [TRUNCATED]
> sphere_n.R(5,2)
[,1] [,2]
[1,] 2.00000 4.00000
[2,] 12.56637 12.56637
[3,] 50.26548 33.51032
[4,] 157.91367 78.95684
[5,] 421.10312 168.44125
> sphere_n(5,2)
[,1] [,2]
[1,] 2.00000 4.00000
[2,] 12.56637 12.56637
[3,] 50.26548 33.51032
[4,] 157.91367 78.95684
[5,] 421.10312 168.44125
- // Rcpp::export は直後のc++関数に対応づく
- 複数の関数を作りたければ、この行を関数の前に「つどつど」つける
- また、この行を少し変えれば、Rでの関数名を指定することもできる
- ただし、c++関数的には異なる関数名にしておかないと、namespace的にバッティングする。Rの方も(多分、そう)
#include <RcppArmadilloExtensions/sample.h>
using namespace Rcpp ;
NumericMatrix sphere_n2(int n,double r) {
NumericMatrix x(n,2);
for(int i=0;i<n;++i){
x(i,0) = 2*pow(M_PI,(i+1.0)/2)/exp(lgamma((i+1.0)/2))*pow(r,i);
x(i,1) = pow(M_PI,(i+1.0)/2)/exp(lgamma((i+1.0)/2+1))*pow(r,i+1);
}
return x;
}
NumericMatrix sphere_n_(int n,double r) {
NumericMatrix x(n,2);
for(int i=0;i<n;++i){
x(i,0) = 2*pow(M_PI,(i+1.0)/2)/exp(lgamma((i+1.0)/2))*pow(r,i);
x(i,1) = pow(M_PI,(i+1.0)/2)/exp(lgamma((i+1.0)/2+1))*pow(r,i+1);
}
return x;
}
> sourceCpp("sphere_n2.cpp")
> sphere_n.R <- function(n,r){
+ ret <- matrix(0,n,2)
+ for(i in 1:n){
+ ret[i,1] <- 2*pi^(i/2)/gamma(i/2)*r^(i-1)
+ ret[i,2] <- pi^(i/2)/gamma( .... [TRUNCATED]
> sphere_n.R(5,2)
[,1] [,2]
[1,] 2.00000 4.00000
[2,] 12.56637 12.56637
[3,] 50.26548 33.51032
[4,] 157.91367 78.95684
[5,] 421.10312 168.44125
> sphere_n2(5,2)
[,1] [,2]
[1,] 2.00000 4.00000
[2,] 12.56637 12.56637
[3,] 50.26548 33.51032
[4,] 157.91367 78.95684
[5,] 421.10312 168.44125
> .sphere_n(5,2)
[,1] [,2]
[1,] 2.00000 4.00000
[2,] 12.56637 12.56637
[3,] 50.26548 33.51032
[4,] 157.91367 78.95684
[5,] 421.10312 168.44125
- ひとつのc++ファイルに書いてその中で作成した関数をもう一つのc++ファイル内関数で使う
- それぞれの関数に// Rcpp::exportが付ける必要がある
- 引用する関数と引用される関数の順番は問題となる
- 順序を問題としないようにするには、ヘッダーファイルを作る??
#include <RcppArmadilloExtensions/sample.h>
using namespace Rcpp ;
NumericMatrix sphere_n2(int n,double r) {
NumericMatrix x(n,2);
for(int i=0;i<n;++i){
x(i,0) = 2*pow(M_PI,(i+1.0)/2)/exp(lgamma((i+1.0)/2))*pow(r,i);
x(i,1) = pow(M_PI,(i+1.0)/2)/exp(lgamma((i+1.0)/2+1))*pow(r,i+1);
}
return x;
}
NumericVector sphere_n_ratio(int n,double r) {
NumericMatrix x = sphere_n2(n,r);
NumericVector y(n);
for(int i=0;i<n;++i){
y[i] = x(i,0)/x(i,1);
}
return y;
}
> sourceCpp("multi_inter_use.cpp")
> sphere_n2(5,2)
[,1] [,2]
[1,] 2.00000 4.00000
[2,] 12.56637 12.56637
[3,] 50.26548 33.51032
[4,] 157.91367 78.95684
[5,] 421.10312 168.44125
> sphere_n_ratio(5,2)
[1] 0.5 1.0 1.5 2.0 2.5