On 19 October 2012 at 02:28, Giovanni Petris wrote: | Thanks Dirk! | | By the way, I just figured out a working solution for what I wanted to achieve - 'code_f' below.
Cool. In return, a "repaired" version without globals that receives the list, and returns the modified list. That is much more "functional" and in the spirit of R, and if you have a moment to run rbenchmark or microbenchmark over it will presumably be about as fast (or so I conjecture :) R> code_f <- ' + Rcpp::NumericMatrix cpp_x(x); + Rcpp::NumericMatrix cpp_mu(mu); + Rcpp::List cpp_work(ls); // pass list in + int K = cpp_mu.ncol(); + int M = cpp_mu.nrow(); + NumericMatrix tmpMatrix; + + for (int k=0; k < K; k++) { + tmpMatrix = Rcpp::as<Rcpp::NumericMatrix>(cpp_work[k]); + for (int i=0; i < M; i++) + tmpMatrix(_, i) = cpp_x(_, i) - cpp_mu(i, k); + cpp_work[k] = tmpMatrix; + } + return cpp_work; + ' R> f <- rcpp(signature(x = "numeric", mu = "numeric", ls = "list"), code_f) R> ws2 <- lapply(1:K, function(k) matrix(0.0, N, M)) R> ws2 <- f(x, mu, ws2) R> all.equal(workspace, ws2) [1] TRUE R> Dirk PS You forgot a set.seed(someVal) to make it really reproducible. | Best, | Giovanni | ===== | | ### 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 | } | | ### For the Rcpp part, set aside working space in the global environment | workspace <- lapply(1:K, function(k) matrix(0.0, N, M)) | | 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")); | NumericMatrix tmpMatrix; | | for (int k=0; k < K; k++) { | tmpMatrix = as<SEXP>(cpp_work[k]); | for (int i=0; i < M; i++) | tmpMatrix(_, i) = cpp_x(_, i) - cpp_mu(i, k); | } | | return R_NilValue; | ' | ## library(Rcpp); library(inline) | f_cpp <- cxxfunction(signature(x = "numeric", mu = "numeric"), code_f, plugin = "Rcpp") | | ## try it | f_cpp(x, mu) | all.equal(workspace, f_R()) | | | ________________________________________ | From: Dirk Eddelbuettel [e...@debian.org] | Sent: Thursday, October 18, 2012 9:15 PM | To: Giovanni Petris | Cc: Dirk Eddelbuettel; rcpp-devel@lists.r-forge.r-project.org | Subject: RE: [Rcpp-devel] How to modifying the elements of a list in the global environment? | | On 19 October 2012 at 01:32, Giovanni Petris wrote: | | Hi Dirk, | | | | Thank you for the quick reply. I will look for more examples on the net. | | | | About your suggestion of allocating scrap space inside the C++ routine, am I wrong to think that when the matrices are large and the function is called repeatedly within a Gibbs sampler loop, this is not a very efficient approach? | | Yes, if you want to use it several times you can pass it around for reuse. | As I mentioned, a reference is just a pointer and hence unrelated to the size | of the object. | | Dirk | | | Thanks again! | | | | Best, | | Giovanni | | | | ________________________________________ | | From: Dirk Eddelbuettel [e...@debian.org] | | Sent: Thursday, October 18, 2012 8:06 PM | | To: Dirk Eddelbuettel | | Cc: Giovanni Petris; rcpp-devel@lists.r-forge.r-project.org | | Subject: Re: [Rcpp-devel] How to modifying the elements of a list in the global environment? | | | | Giovanni, | | | | On 18 October 2012 at 17:46, Dirk Eddelbuettel wrote: | | | | > 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); | | | | That can't work. You have the types confused. | | | | You could just pass the list object down, and then pick from it. Working | | examples for that are in the list archives, in the RcppExamples package, and | | in other places on the net. | | | | Or, as I suggested, just allocate the scrap space inside the C++ routine. | | | | Hth, Dirk | | | | -- | | Dirk Eddelbuettel | e...@debian.org | http://dirk.eddelbuettel.com | | -- | Dirk Eddelbuettel | e...@debian.org | http://dirk.eddelbuettel.com -- Dirk Eddelbuettel | e...@debian.org | http://dirk.eddelbuettel.com _______________________________________________ Rcpp-devel mailing list Rcpp-devel@lists.r-forge.r-project.org https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel