[Rcpp-devel] ivec and imat don't pass by reference

Serguei Sokol serguei.sokol at gmail.com
Tue Sep 15 14:09:14 CEST 2015


Le 15/09/2015 13:53, Dirk Eddelbuettel a écrit :
>
> On 15 September 2015 at 12:16, Serguei Sokol wrote:
> | Hi,
> |
> | If we declare the following toy function where a numeric matrix is passed by reference,
> | it works as expected, the matrix m is modified "in place":
> |
> | cppFunction('
> | mat m2(mat& m) {
> |     m=m*2;
> |     return(m);
> | }', depends="RcppArmadillo", inc="using namespace arma;")
> | m=matrix(1:4, 2)+pi
> | m2(m)
> |            [,1]     [,2]
> | [1,]  8.283185 12.28319
> | [2,] 10.283185 14.28319
> | m
> |            [,1]     [,2]
> | [1,]  8.283185 12.28319
> | [2,] 10.283185 14.28319
> |
> | But if we pass to imat type, the call by reference is no more functionning:
> | cppFunction('
> | imat im2(imat& m) {
> |     m=m*2;
> |     return(m);
> | }', depends="RcppArmadillo", inc="using namespace arma;")
> | im=matrix(1:4, 2)
> | im2(im)
> |       [,1] [,2]
> | [1,]    2    6
> | [2,]    4    8
> | im
> |       [,1] [,2]
> | [1,]    1    3
> | [2,]    2    4
> |
> | The original matrix im remains as it was.
> | You can easyly verify that the same is true for ivec type.
> | Is it intended behaviour?
>
> It is something else, which is a slight trick:  your 'm' is not an integer
> matrix, so you are forcing a copy, which breaks the reference semantics.
>
> See here using your code:
>
> R> library(Rcpp)
> R> cppFunction('imat im2(imat& m) { m=m*2; return(m); }', depends="RcppArmadillo", inc="using namespace arma;")
> R> m <- matrix(c(1L,2L,3L,4L), 2)
> R> m
>       [,1] [,2]
> [1,]    1    3
> [2,]    2    4
> R> storage.mode(m)
> [1] "integer"
> R> im2(m)
>       [,1] [,2]
> [1,]    2    6
> [2,]    4    8
> R> m
>       [,1] [,2]
> [1,]    2    6
> [2,]    4    8
> R>
>
> So if we pass an integer matrix down, it gets changed as a side effect.
Not on my side, where m stays unchanged.
Even for the first way of defining m as
m=matrix(1:4, 2)
I have too
storage.mode(m)
[1] "integer"

Before the original post, I've checked that the matrix was in appropriate storage
with
 > .Internal(inspect(m))
@7fc288508340 13 INTSXP g0c2 [MARK,NAM(2),ATT] (len=4, tl=0) 1,2,3,4
ATTRIB:
   @2538848 02 LISTSXP g0c0 [MARK]
     TAG: @6ce018 01 SYMSXP g1c0 [MARK,LCK,gp=0x4000] "dim" (has value)
     @7fc2884be728 13 INTSXP g0c1 [MARK,NAM(2)] (len=2, tl=0) 2,2

giving well INTSXP but pass by reference was not working.

So, what have I to check in my installation to find the origin of
an unwanted copy?

Serguei.



More information about the Rcpp-devel mailing list