Hi All,

i have a problem in understanding what the assignment operator '<-'  really is 
doing.
If i create two numeric arrays in R and copy one into the other with '<-' and
afterwards change one array by calling a C function, both arrays are changed!

The problem I am facing can easily be seen in the following example:
(The following R code and the C function is attached and the C function can be 
compiled with R CMD SHLIB test.c.)

First include the c function:
    dyn.load("test.so")

Let's start with 2 arrays:
    a  <- rep(0, 5)
    b  <- rep(1, 5)

Now print the memory addresses:
    print(sprintf("a: %s    b: %s", tracemem(a), tracemem(b) ))
    [1] "a: <0x29d34e0>    b: <0x29946e0>"

oky, they are different! Now copy a into b and print again the addresses:
    b <- a
    print(sprintf("a: %s    b: %s", tracemem(a), tracemem(b) ))
    [1] "a: <0x29d34e0>    b: <0x29d34e0>"

Ugh they are the same. If I now call my C function, which writes 0,1,2,3,4 into 
an array of 5 doubles,
of course 'both' arrays are changed:
    .Call("test", b)
    print( cbind(a,b) )
         a b
    [1,] 0 0
    [2,] 1 1
    [3,] 2 2
    [4,] 3 3
    [5,] 4 4


If i just change one element of b instead of calling the c function, then a 
full copy of b is made:
    a <- rep(0, 5)
    b <- rep(1, 5)
    print(sprintf("a: %s    b: %s", tracemem(a), tracemem(b) ))
    [1] "a: <0x2994b58>    b: <0x2912ff8>"

    b <- a
    print(sprintf("a: %s    b: %s", tracemem(a), tracemem(b) ))
    [1] "a: <0x2994b58>    b: <0x2994b58>"

    b[1] <- 5
    print(sprintf("a: %s    b: %s", tracemem(a), tracemem(b) ))
    "a: <0x2994b58>    b: <0x29134d8>"

    print( cbind(a,b) )
         a b
    [1,] 0 5
    [2,] 0 0
    [3,] 0 0
    [4,] 0 0
    [5,] 0 0


So what is happening here? What is the 'right' way to ensure a deep copy before 
using Call?
I am currently using a for loop and copy every single element.

Thanks!

// Compile with
// R CMD SHLIB test.c -Wall -Wextra

#include<R.h>
#include<Rdefines.h>

SEXP test( SEXP c )
{
    PROTECT( c = AS_NUMERIC(c) );
    double* _c = REAL(c);

    int i;
    for(i=0; i<5; i++)
        _c[i] = (double)i;

    UNPROTECT(1);
    return R_NilValue;
}
______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to