[Rcpp-devel] How to modifying the elements of a list in the global environment?

Giovanni Petris gpetris at uark.edu
Fri Oct 19 00:13:13 CEST 2012


Hello!

I am very new to Rcpp and C++, although I have some experience with the C/R interface, so please bear with me...

In the context of a Gibbs sampler for a multivariate normal mixture model, I need to center all the observations by the mean of each component of the mixture. In pure R I have a function similar to the one below.

> ### Small reproducible example
> K <- 2; N <- 5; M <- 3
> x <- matrix(rnorm(N * M), N, M)
> mu <- matrix(rnorm(M * K, mean = 1 : K), M, K, TRUE)
> 
> ### What I would do in R
> f_R <- function() {
+     ## center observations in 'x' using columns of 'mu'
+     w <- lapply(1L:K, function(i) x - rep(mu[, i], each = N))
+     ## eventually more stuff here...
+     w
+ }

I am trying to transport the code to Rcpp. However, since K, M, and N may be large and I am running a possibly large number of iterations of a Gibbs sampler, I want to use a list in the global environment as working space so as to avoid creating and destroying large matrices at every Gibbs sampler iteration. So I do the following

> ### For the Rcpp part, set aside working space in the global environment
> workspace <- lapply(1:K, function(k) matrix(0.0, N, M))

Then I try to access the matrices in the 'workspace' list and modify them, but so far I have had no success. The first attemp, bolow, does not compile...

> code_f <- '
+     Rcpp::NumericMatrix cpp_x(x);
+     Rcpp::NumericMatrix cpp_mu(mu); 
+     int K = cpp_mu.ncol();
+     int M = cpp_mu.nrow();
+     int N = cpp_x.nrow();
+     Environment glob = Environment::global_env(); 
+     List cpp_work(glob.get("workspace"));
+ 
+     for (int k=0; k < K; k++) {
+         cpp_work[k] = clone(cpp_x);
+         for (int i=0; i < M; i++) 
+             cpp_work(_, i) = cpp_work(_, i) - cpp_mu(i, k);
+     }
+ 
+     return R_NilValue;
+ '
> ## the following does not compile
> library(Rcpp); library(inline)
> f_cpp <- cxxfunction(signature(x = "numeric", mu = "numeric"), code_f, plugin = "Rcpp")
file70363a0a2d30.cpp: In function ‘SEXPREC* file70363a0a2d30(SEXP, SEXP)’:
file70363a0a2d30.cpp:42:26: error: invalid conversion from ‘SEXP’ to ‘size_t {aka unsigned int}’ [-fpermissive]
/usr/local/lib/R/site-library/Rcpp/include/Rcpp/vector/Vector.h:403:18: error:   initializing argument 1 of ‘Rcpp::Vector<RTYPE>::Proxy Rcpp::Vector<RTYPE>::operator()(const size_t&, const size_t&) [with int RTYPE = 19, Rcpp::Vector<RTYPE>::Proxy = Rcpp::internal::generic_proxy<19>, size_t = unsigned int]’ [-fpermissive]
file70363a0a2d30.cpp:42:43: error: invalid conversion from ‘SEXP’ to ‘size_t {aka unsigned int}’ [-fpermissive]
/usr/local/lib/R/site-library/Rcpp/include/Rcpp/vector/Vector.h:403:18: error:   initializing argument 1 of ‘Rcpp::Vector<RTYPE>::Proxy Rcpp::Vector<RTYPE>::operator()(const size_t&, const size_t&) [with int RTYPE = 19, Rcpp::Vector<RTYPE>::Proxy = Rcpp::internal::generic_proxy<19>, size_t = unsigned int]’ [-fpermissive]
make: *** [file70363a0a2d30.o] Error 1

ERROR(s) during compilation: source code errors or compiler configuration errors!

Program source:
  1: 
  2: // includes from the plugin
  3: 
  4: #include <Rcpp.h>
  5: 
  6: 
  7: #ifndef BEGIN_RCPP
  8: #define BEGIN_RCPP
  9: #endif
 10: 
 11: #ifndef END_RCPP
 12: #define END_RCPP
 13: #endif
 14: 
 15: using namespace Rcpp;
 16: 
 17: 
 18: // user includes
 19: 
 20: 
 21: // declarations
 22: extern "C" {
 23: SEXP file70363a0a2d30( SEXP x, SEXP mu) ;
 24: }
 25: 
 26: // definition
 27: 
 28: SEXP file70363a0a2d30( SEXP x, SEXP mu ){
 29: BEGIN_RCPP
 30: 
 31:     Rcpp::NumericMatrix cpp_x(x);
 32:     Rcpp::NumericMatrix cpp_mu(mu); 
 33:     int K = cpp_mu.ncol();
 34:     int M = cpp_mu.nrow();
 35:     int N = cpp_x.nrow();
 36:     Environment glob = Environment::global_env(); 
 37:     List cpp_work(glob.get("workspace"));
 38: 
 39:     for (int k=0; k < K; k++) {
 40:         cpp_work[k] = clone(cpp_x);
 41:         for (int i=0; i < M; i++) 
 42:             cpp_work(_, i) = cpp_work(_, i) - cpp_mu(i, k);
 43:     }
 44: 
 45:     return R_NilValue;
 46: 
 47: END_RCPP
 48: }
 49: 
 50: 
Error in compileCode(f, code, language = language, verbose = verbose) : 
  Compilation ERROR, function(s)/method(s) not created! file70363a0a2d30.cpp: In function ‘SEXPREC* file70363a0a2d30(SEXP, SEXP)’:
file70363a0a2d30.cpp:42:26: error: invalid conversion from ‘SEXP’ to ‘size_t {aka unsigned int}’ [-fpermissive]
/usr/local/lib/R/site-library/Rcpp/include/Rcpp/vector/Vector.h:403:18: error:   initializing argument 1 of ‘Rcpp::Vector<RTYPE>::Proxy Rcpp::Vector<RTYPE>::operator()(const size_t&, const size_t&) [with int RTYPE = 19, Rcpp::Vector<RTYPE>::Proxy = Rcpp::internal::generic_proxy<19>, size_t = unsigned int]’ [-fpermissive]
file70363a0a2d30.cpp:42:43: error: invalid conversion from ‘SEXP’ to ‘size_t {aka unsigned int}’ [-fpermissive]
/usr/local/lib/R/site-library/Rcpp/include/Rcpp/vector/Vector.h:403:18: error:   initializing argument 1 of ‘Rcpp::Vector<RTYPE>::Proxy Rcpp::Vector<RTYPE>::operator()(const size_t&, const size_t&) [with int RTYPE = 19, Rcpp::Vector<RTYPE>::Proxy = Rcpp::internal::generic_proxy<19>, size
In addition: Warning message:
running command '/usr/lib/R/bin/R CMD SHLIB file70363a0a2d30.cpp 2> file70363a0a2d30.cpp.err.txt' had status 1 
 
Then I tried to modify my code, which now compiles just fine, but does not give me what I wanted...

> ## try again
> code_f <- '
+     Rcpp::NumericMatrix cpp_x(x);
+     Rcpp::NumericMatrix cpp_mu(mu); 
+     int K = cpp_mu.ncol();
+     int M = cpp_mu.nrow();
+     int N = cpp_x.nrow();
+     Environment glob = Environment::global_env(); 
+     List cpp_work(glob.get("workspace"));
+ 
+     for (int k=0; k < K; k++) {
+         NumericMatrix tmpMatrix(as<SEXP>(cpp_work[k]));
+         tmpMatrix = clone(cpp_x);
+         for (int i=0; i < M; i++) 
+             tmpMatrix(_, i) = tmpMatrix(_, i) - cpp_mu(i, k);
+     }
+ 
+     return R_NilValue;
+ '
> ## this time it compiles
> f_cpp <- cxxfunction(signature(x = "numeric", mu = "numeric"), code_f, plugin = "Rcpp")
> ## but it does not have the efect I was hoping for, i.e., modifying
> ## the object 'workspace' in the global environment
> f_cpp(x, mu)
NULL
> all.equal(workspace, f_R())
[1] "Component 1: Mean absolute difference: 0.72524" "Component 2: Mean absolute difference: 1.7288" 

Can anybody help me?

Thank you in advance,
Giovanni




Giovanni Petris
Associate Professor
Department of Mathematical Sciences
University of Arkansas - Fayetteville, AR 72701
Ph: (479) 575-6324, 575-8630 (fax)
http://definetti.uark.edu/~gpetris/



More information about the Rcpp-devel mailing list