[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