Skip to content

DUP=FALSE

7 messages · Thomas Lumley, Paul Gilbert, Brian Ripley

#
Last week Paul Gilbert asked about DUP=FALSE and whether parent
environments can be affected.  I have experimented and they can.
Consider the R functions
function(x){ .C("badidea",x,DUP=FALSE)}
function(y) f(y)
function(z){
        z<-as.integer(z)
        g(z)
        z
}

and the C function
	void badidea(int *x){
	    *x=7;
	}

This gives
[1] 7

so the modification of x in f() reaches up past g() to modify z in h().
The conclusion is that one should not pass a formal parameter of a
function using DUP=FALSE if it might be modified.  Assigning the parameter
seems to be sufficient to prevent the problem: replacing g by

 g<-function(y) {
	w<-y
	f(w)
 }
gives
[1] 4
as expected.


	-thomas

Thomas Lumley			Asst. Professor, Biostatistics
tlumley@u.washington.edu	University of Washington, Seattle

-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-devel mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-devel-request@stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._
#
Thomas

Thanks for verifying that this actually does work the way you thought it
did. In the example I asked about  (qr.qty ) I am fairly sure that it
does not modify the y argument. Unfortunately this seems relatively
difficult to trace for certain, and experimenting works but may not hit
all cases.

Another thing I find I do not understand is how many copies of an
argument are made. For example, in a call to a function like

f <- function(x){ .C("goodidea", y=double(1),  x, DUP=TRUE)[[y]] }

there is the original x and the duplicated x in the argument to .C, but
is there a third in the list returned by .C, or is that somehow the same
one as in the argument to .C.  My problem is that my x is very big.

Thanks,
Paul Gilbert



-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-devel mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-devel-request@stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._
#
On Mon, 26 Mar 2001, Paul Gilbert wrote:

            
There's a third one. In dotcode.c the following happens

a) x is copied to a C array at the top of the R heap
b) the C function is called
c) the C array is copied into a newly created R object
d) this new R object is returned.

You only have three copies for a very short time, since the C array is
freed as soon as the new R object is returned.

A more selective version of DUP would be nice, but the only real way to do
it at the moment is to write a wrapper using .Call or .External and do any
necessary copying yourself.

I don't know why you are getting slightly different results with
DUP=FALSE. I can't think of any good explanation.

	-thomas

-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-devel mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-devel-request@stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._
#
Thomas
but
same
It seems like there is an unnecessary extra copy here, unless of course
the array in the R object cannot be the C array (but your example of
messing up things in the parent environment suggests it can be). If
DUP=TRUE then there should be no harm in the result being just a pointer
to the copy which is the argument, and if DUP=FALSE then the result is
already in the copy as illustrated in the example circulated by Martin
Schlather on Martin Maechler suggestion a few days ago, so again there
is no harm. I won't pretend to understand the internals of R but I know
I am getting clobbered by a big array in an argument.
I'll try to track this down sometime. If you think of anything please
let me know.

Paul Gilbert

-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-devel mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-devel-request@stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._
#
On Mon, 26 Mar 2001, Paul Gilbert wrote:

            
Well, in current R internals there is no simple way to create an R array
out of data held in a C array.  (It can be done, but is messy AFAIK.)
Also, with DUP=TRUE, you need protection.  The C routine might have cached
that address and use it next time it was called, thereby working with part
of the `newly created R object'.
Why are you using .C not .Call anyway?  These things are much easier to
control with .Call.
Linux? If so I think this is probably due to forced stores or not.  gcc on
Linux is getting notorious with me for not doing IEEE-compatible
arithmetic, and so getting inconsistent results. Compiling with
-fforce-store seems to solve this (at some performance expense).

Brian
#
ok, I think I'll avoid this for now. On the wish list:  it would be nice to have a
call which distinguished items to return and only built an R object of those rather
than the complete list of arguments in the call  (for me with .Fortran especially).
Actually, I am using .Fortran, I just happened to grab Thomas example. I understand
the documentation to mean that .Call and .External are only alternatives to .C and
not to .Fortran. If I'm wrong on that please let me know.
Solaris.  fforce-store does not seem to be an option in my version of gcc (2.8.1) but
my man pages may be older.

Thanks,
Paul Gilbert

-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-devel mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-devel-request@stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._
#
On Tue, 27 Mar 2001, Paul Gilbert wrote:

            
You can write a C wrapper and .Call that, of course.
It's not a Solaris issue, but 2.8.1 is rather old: I use 2.95.2 on Solaris.
There may be order-of-evaluation issue though.  Does the difference persist
with optimization turned off?

Brian