Samuel Shamiri
Samuel Shamiri

Reputation: 137

converting loop from R to C++ using Rcpp

I want to improve the speed of some of my R code using Rcpp. However, my knowledge of C++ is very little. So, I checked the documentation provided with Rcpp, and other documents provided at Dirk Eddelbuttel’s site. After reading all the stuff, I tried to execute a simple loop that I wrote in R. unfortunately, I was unable to do it. Here is the R function:

Inverse Wishart

beta = matrix(rnorm(15),ncol=3)

a = rnorm(3) 

InW = function(beta,a) {

    n = nrow(beta)
    p = ncol(beta)
    I = diag(rep(1,times = p))
    H = matrix(0,nrow=p,ncol=p)
    for(i in 1:n){
    subBi = beta[i,]
          H = H + tcrossprod(a - subBi)
        }
    H = H + p * I

    T = t(chol(chol2inv(chol(H))))
    S = 0
    for(i in 1:(n+p)){
        u <- rnorm(p)
        S = S + tcrossprod(T %*% u)
        }
    D = chol2inv(chol((S)))
    ans = list(Dinv = S,D=D)
}

I truly, appreciate if someone can help me as it will serve as starting point in learning Rcpp.

Upvotes: 0

Views: 3448

Answers (2)

Samuel Shamiri
Samuel Shamiri

Reputation: 137

an answer to my first question is shown below. It may be not the efficient way but the Rcpp code gives the same results as the R code. I appreciate the help from baptiste.

code <- '<br/>
arma::mat beta = Rcpp::as<arma::mat>(beta_);
arma::rowvec y = Rcpp::as<arma::rowvec>(y_);
int n = beta.n_rows; int p = beta.n_cols;
arma::mat Ip = arma::eye<arma::mat>( p, p );
int ii;
arma::mat H1 = beta,  d;
arma::mat H2=H1.zeros(p,p);
arma::rowvec S;
for (ii=0;ii<n;ii++){
S= beta.row(ii);
d = trans(y - S)*(y-S);
H2 = H2 + d ;
}
arma::mat H = chol(H2+p*Ip);
arma::mat Q , R;
 qr(Q,R,H);
arma::mat RR = R;
arma::mat TT = trans(chol(solve(trans(RR)*RR,Ip)));
int jj;
arma::mat SS = H1.zeros(p,p);
arma::colvec u;
arma::colvec V;
for(jj=0;jj<(n+p);jj++) {
       u = rnorm(p);
       V = TT*u;
      SS = SS + V * trans(V);
      }
arma::mat SS1 = chol(SS);
arma::mat Q1 , R1;
qr(Q1,R1,SS1);
arma::mat SS2 = R1;
arma::mat D = solve(trans(SS2)*SS2,Ip);
return Rcpp::List::create(Rcpp::Named("Dinv")=SS,Rcpp::Named("D")=D);
'
fun = cxxfunction(signature(beta_ ="matrix",y_="numeric"),code, plugin="RcppArmadillo")
m = matrix(rnorm(100),ncol=5)
vec = rnorm(5)
fun(m,vec) 

Upvotes: 1

baptiste
baptiste

Reputation: 77106

A basic example of RcppArmadillo goes like this,

require(RcppArmadillo)
require(inline)

code <- '
  arma::mat beta = Rcpp::as<arma::mat>(beta_);
  int n = beta.n_rows; int p = beta.n_cols;
  arma::mat Ip = arma::eye<arma::mat>( p, p );
  int ii;
  double S=0;
  for (ii=0; ii<(n+p); ii++) {
    S += ii; // dummy calculation
  }
  return Rcpp::wrap(S);
 '

fun <- cxxfunction(signature(beta_ ="matrix"),
                       code, plugin="RcppArmadillo")

m <- matrix(1:9,3)
fun(m)

and you can browse armadillo's doc to find the more advanced bits and pieces.

Upvotes: 5

Related Questions