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

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


Le 15/09/2015 14:09, Serguei Sokol a écrit :
> 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?
>
It was not installation it was just a corrupted session.
With a new virgin session, it works like a charm.
Sorry for a false alert.

Serguei.




More information about the Rcpp-devel mailing list