[Rcpp-devel] Initializing Armadillo vec/cube from NumericVector using as conversion

Dirk Eddelbuettel edd at debian.org
Thu Sep 22 22:00:29 CEST 2016


Hi Jouni,

On 22 September 2016 at 19:39, Helske, Jouni wrote:
| Hi,
| 
| I was recently hunting down a bug in my code, and stumbled upon a slightly
| incoherent behaviour in Rcpp/RcppArmadillo. In my real application I have a
| class which data members are initialized in initialization list from the Rcpp
| List using as<arma::cube>. For example, I have a member y which I initialize by
| y(as<arma::cube>(xlist["y"])). This caused some headaches if I later modified
| data member y, as the y in the list on R side was modified as well. I then
| realized that I need to use Rcpp::clone in order to make a deep copy of xlist
| object. But, this does not need to be done when initializing arma::vec or
| arma::mat. Is this purposeful or am I missing something?

arma::vec and arma::mat went through a few iterations and now use the
'advanced constructors' (see arma docs) in what we think is the correct way.

| Simple example:
| 
| void test1(const NumericVector& x) {
|   arma::cube ycube(as<arma::cube>(x));
|   ycube(0) = 0.5;
| }
| 
| > y <- array(1:4, c(2,2,1)) #y is integer type, using automatic copy
| > test1(y)
| > y
| , , 1
| 
|      [,1] [,2]
| [1,]    1    3
| [2,]    2    4
| 
| > y <- array(as.numeric(1:4), c(2,2,1)) #y is numeric, no copy
| > test1(y)
| > y
| , , 1
| 
|      [,1] [,2]
| [1,]  0.5    3
| [2,]  2.0    4

The copy due to the casting is unavoidable.  The non-copy on numeric is on purpose.
 
| But in case of arma::vec (or arma::mat), copying is always done:
| 
| void test2(const NumericVector& x) {
|   arma::vec yvec(as<arma::vec>(x));
|   yvec(0) = 0.5;
| }

But here you force the copy by using NumericVector and using as<>. That was
an older access pattern.

Try

 void test2(const arma::vec & x) {
   x(0) = 0.5;
 }

This is now a proxy object so the 'outside value' should be changed too:

R> cppFunction("void test2(arma::vec & x) { x(0) = 0.5; }",
R> depends="RcppArmadillo")
R> v <- sqrt(9:16)
R> v
[1] 3.00000 3.16228 3.31662 3.46410 3.60555 3.74166 3.87298 4.00000
R> test2(v)
R> v
[1] 0.50000 3.16228 3.31662 3.46410 3.60555 3.74166 3.87298 4.00000
R> 
 
| > y <- as.numeric(1:8)
| > test2(y)
| > y
| [1] 1 2 3 4 5 6 7 8

You are such a long-time user that you may have stuck with as<>() for too
long here :)   We can now do better.

Hope this helps,  Dirk

-- 
http://dirk.eddelbuettel.com | @eddelbuettel | edd at debian.org


More information about the Rcpp-devel mailing list