From simon.urbanek at r-project.org  Thu Jun  7 02:15:57 2012
From: simon.urbanek at r-project.org (Simon Urbanek)
Date: Wed, 6 Jun 2012 20:15:57 -0400
Subject: [Rd] suggest that as.double( something double ) not make a copy
In-Reply-To: <CAAWNEwaLpwLxT58B6PAXm7r=S9fnSjKUB3xT1XrrFMwQgYzDMw@mail.gmail.com>
References: <CAAWNEwaLpwLxT58B6PAXm7r=S9fnSjKUB3xT1XrrFMwQgYzDMw@mail.gmail.com>
Message-ID: <DCA9D331-15A1-44E8-BA2E-C964097DEAC5@r-project.org>

On Jun 6, 2012, at 6:53 PM, Tim Hesterberg wrote:

> I've been playing with passing arguments to .C(), and found that replacing
>    as.double(x)
> with
>    if(is.double(x)) x else as.double(x)
> saves time and avoids one copy, in the case that x is already double.
> 

No, it doesn't:

> x=rnorm(10)
> tracemem(x)
[1] "<0x100c59cb0>"
> invisible(.C("foo",x))
tracemem[0x100c59cb0 -> 0x100c59c30]: .C 
tracemem[0x100c59c30 -> 0x100ca4298]: .C 
> x=rnorm(10)
> tracemem(x)
[1] "<0x100ca41f0>"
> invisible(.C("foo",as.double(x)))
tracemem[0x100ca41f0 -> 0x102cdc980]: .C 
tracemem[0x102cdc980 -> 0x102cdca00]: .C 

or rather more easily:

> x=rnorm(10)
> tracemem(x)
[1] "<0x102ae0ff0>"
> as.double(x)
 [1] -0.1027767  0.4018732 -1.3412045  0.8153615  1.8245356 -0.2147280
 [7]  1.1298404  1.1026897 -1.1340612 -0.2346464


as.double(x) is not stupid and doesn't copy if not needed.

However, it is a very common mistake to forget about the fact that as.double() has to strip attributes, so if you pass a matrix, you are always forcing a copy:

> x=matrix(0,2,2)
> tracemem(x)
[1] "<0x100b0f098>"
> as.double(x)
tracemem[0x100b0f098 -> 0x1008b52c8]: 
[1] 0 0 0 0

That is not the fault of as.double() but rather of the user since you don't really need to strip attributes when calling .C as it doesn't care.

As usual, I can only say don't use .C() ... ;)

Cheers,
Simon


> I suggest modifying as.double to avoid the extra copy and just
> return x, when x is already double. Similarly for as.integer, etc.



[Rd] suggest that as.double( something double ) not make a copy
Simon Urbanek