Rcpp Attributesを読む

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;
// [[Rcpp::export]]
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;
}
    • この中に、いかにもコメント行然とした
// [[Rcpp::export]]
    • がある。これは、「コメント行だけど、ルールとして、このコメント行が出たら、以下のc++の関数がRで使えるように処理しなさいよ、という命令とみなされるようにしてある(Rcppの仕様で)ので、「大事で特別なコメント行」
  • c++ソースにRのコードも入れちゃえ
    • c++を書いていて、それをRで使えるようにしたいのです…というのがこのsourceCpp()の真骨頂なわけで、だとしたら、c++を書いてコンパイルしたら、Rでそれを使って見せてしまいたい、という気になるのはみな同じ(そうでなければ、いちいちコンパイル後にRで実行しないといけない)
    • それを解消するべく、Rでの使用もc++ファイルに書いてしまえるようにしてある。ここでもまた、書式を決めたコメント行で、そのような扱いにすることにしてある
    • 以下で、c++を書いたあと、指定の書式で対応するRの関数も書いておいて、その後、c++由来の関数とRで書いた関数を実行して見せている
#include <RcppArmadilloExtensions/sample.h>

// [[Rcpp::depends(RcppArmadillo)]]

using namespace Rcpp ;

// [[Rcpp::export]]

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;
}

/*** R

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(i/2+1)*r^i
	}
	ret
}

sphere_n.R(5,2)
sphere_n(5,2)

*/
> 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>

// [[Rcpp::depends(RcppArmadillo)]]

using namespace Rcpp ;

// [[Rcpp::export]]

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;
}
// [[Rcpp::export(".sphere_n")]]

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;
}

/*** R

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(i/2+1)*r^i
	}
	ret
}

sphere_n.R(5,2)
sphere_n2(5,2)
.sphere_n(5,2)

*/
> 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>

// [[Rcpp::depends(RcppArmadillo)]]

using namespace Rcpp ;


// [[Rcpp::export]]

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;
}

// [[Rcpp::export]]

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;
}


/*** R


sphere_n2(5,2)
sphere_n_ratio(5,2)

*/
> 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