Rcpp のバックアップ(No.4) - アールメカブ

アールメカブ


Rcpp のバックアップ(No.4)


Rの備忘録

dirk.eddelbuettel Rcpp

_ DataFrame? 作成

#include "Rcpp.h"
RcppExport SEXP testDF (){

 Rcpp::IntegerVector v = Rcpp::IntegerVector::create(1,2,3);
 std::vector<std::string> str(3);
    str[0] = "A"; str[1] = "B"; str[2] = "C";
    return Rcpp::DataFrame::create(Rcpp::Named("Var1", v), 
                 Rcpp::Named ("Var2", s),
                 Rcpp::Named("stringsAsFactors", false )); 
// あるいは 
     return Rcpp::DataFrame::create(Rcpp::Named("VAR1") =  v,
                 Rcpp::Named ("VAR2") =  s,  
                 Rcpp::Named("stringsAsFactors") = false ); 	 
}

_ NumericVector?

ここ にあるマンマ

旧来の場合

SEXP sum ( SEXP x, SEXP y ){
 int i, j, nx, ny;
 double tmp, *rx = REAL(x), *ry = REAL(y), *rans;
 SEXP ans;
 nx = length(x); ny = length(y);
 PROTECT(ans = allocMatrix(REALSXP, nx, ny));
 rans = REAL(ans);
 for(i = 0; i < nx; i++) {
	tmp = rx[i];
	for(j = 0; j < ny; j++)
	  rans[i + nx*j] = tmp * ry[j];
 }
 UNPROTECT(1);
 return(ans);
}

Rcppオリジナルのインターフェイスを使う場合

SEXP sum( SEXP x_ ){
  Rcpp::NumericVector x(x_) ;
  double res = 0.0 ;
  for( int i=0; i<x.size(), i++){
     res += x[i] ;
  }
  return Rcpp::wrap( res ) ;
}

Rcpp sugar を使う

SEXP sum( SEXP x_ ){
  NumericVector x(x_) ;
  double res = sum( x ) ;
  return wrap( res ) ;
}

_ CharacterVector?

ここ にあるマンマだが,確かに手素が省ける

旧来のインターフェイスを使う場合

SEXP foobar(){
 SEXP ab;
 PROTECT(ab = allocVector(STRSXP, 2));
 SET_STRING_ELT( ab, 0, mkChar("foo") );
 SET_STRING_ELT( ab, 1, mkChar("bar") );
 UNPROTECT(1);
}

Rcppを使う.その1

SEXP foobar(){
  return Rcpp::CharacterVector::create( "foo", "bar" ) ;
}

Rcppを使う.その2

SEXP foobar(){
  Rcpp::CharacterVector res(2) ;
  res[0] = "foo" ;
  res[1] = "bar" ;
  return res ;
}
  • 以下でちょっと詰まった
RcppExport SEXP testChar (SEXP a, SEXP b){
  Rcpp::CharacterVector xa (a);
  Rcpp::CharacterVector xb (b);

ここで以下はコンパイラを通らない

std::string sxa = xa[0];

以下のようにしないと行けない

  std::string sxa;
  sxa = xa[0];
  std::string sxb;
  sxb = xb[0]; 

_ rcpp のサンプル

Windows 7(64bit) 上の R-2.12.0 環境で,Rcpp_sample.cpp を以下のMakevars を用意.

PKG_CXXFLAGS=$(shell Rscript -e "Rcpp:::CxxFlags()")
PKG_LIBS=$(shell Rscript -e "Rcpp:::LdFlags()")

してコマンドプロンプトから素直に

R CMD SHLIB Rcpp_sample.cpp
   http://cygwin.com/cygwin-ug-net/using.html#using-pathnames
g++ -shared -s -static-libgcc -o  Rcpp_sample.dll tmp.def 
  Rcpp_sample.cpp C:/Users/ishida/Documents/R/win-library/2.12/Rcpp/lib/i386/libRcpp.a
-LC:/PROGRA~1/R/R-212~1.0/bin/i386 -lR

とすると i386 が呼ばれる.確かに

Rscript -e "Rcpp:::LdFlags()
C:/Users/ishida/Documents/R/win-library/2.12/Rcpp/lib/i386/libRcpp.a

となっている.が,こっちを呼んで欲しい

Rscript --arch x64 -e "Rcpp:::LdFlags()
C:/Users/ishida/Documents/R/win-library/2.12/Rcpp/lib/x64/libRcpp.a

やむなく

PKG_LIBS = C:/Users/ishida/Documents/R/win-library/2.12/Rcpp/lib/x64/libRcpp.a 

あるいは

PKG_LIBS = -LC:/Users/ishida/Documents/R/win-library/2.12/Rcpp/lib/x64/ -lRcpp

と修正し

R --arch x64 CMD SHLIB Rcpp_sample.cpp

と実行.

dyn.load("Rcpp_sample.dll")