Web pages of Lars Relund Nielsen

Accessing an array created in R from C++

Assume that you have created a 3-dim array in R containing vectors of various size:

> a<-array(list(),c(2,2,2))   # array where each element contain a numeric vector
> a[[1,1,1]]<-rnorm(1)
> a[[1,1,2]]<-rnorm(3)
> a[[2,1,1]]<-rnorm(2)
> a[[2,1,2]]<-rnorm(3)
> a[[1,2,1]]<-rnorm(4)
> a[[1,2,2]]<-rnorm(3)
> a[[2,2,1]]<-rnorm(5)
> a[[2,2,2]]<-rnorm(1)
> d = dim(a)
> d
[1] 2 2 2
> i<-1; j<-1; k<-2
> q<-i + j*d[1] + k*(d[1]*d[2]) - (d[1] + d[1]*d[2])
> a[[i,j,k]]      # access an element
[1] -0.2370040 -0.6009635  3.0550405
> a[[q]]          # access the same element using a single index
[1] -0.2370040 -0.6009635  3.0550405

Note you can access the array in two ways. Next you want to copy the array to a vector on the C++ side. For instance in a package you may need to do some operations in C++ to speed up time.

On the C++ side you can create a function:

SEXP test(SEXP ary) {
    SEXP dim;
    int q,l,i,j,k,r;
    flt *p;
    PROTECT(dim = GET_DIM(ary));
    int * pDim = INTEGER_POINTER(AS_INTEGER(dim));
    vector< vector< vector< vector<flt> > > > v;
    v.resize(pDim[0]);
    for (i=0;i<pDim[0];i++){
        v[i].resize(pDim[1]);
        for (j=0;j<pDim[1];j++) v[i][j].resize(pDim[2]);
    }
    Rprintf("Array dim: %d %d %d\n",pDim[0],pDim[1],pDim[2]);
    for(k=0;k<pDim[2];++k) {
        for(j=0;j<pDim[1];++j) {
            for(i=0;i<pDim[0];++i) {
                q = i + j*pDim[0] + k*(pDim[0]*pDim[1]);
                l = GET_LENGTH(VECTOR_ELT(ary, q));
                p = NUMERIC_POINTER(VECTOR_ELT(ary, q));
                Rprintf("q: %d ",q);Rprintf("lth: %d v = ",l);
                v[i][j][k].resize(l);
                for (r=0;r<l;++r) {
                    v[i][j][k][r] = p[r];
                    Rprintf("%f ",p[r]);
                }
                Rprintf("\n");
            }
        }
    }
    UNPROTECT(1);
    return R_NilValue;
}

Now after creating the library file and loading the library in R (see the R extensions manual) you can call the function from R:

> .Call("test", as.list(a))
Array dim: 2 2 2
q: 0 lth: 1 v = -0.820440
q: 1 lth: 2 v = 1.055376 0.950510
q: 2 lth: 4 v = -0.322194 0.498610 -1.080668 0.303776
q: 3 lth: 5 v = 1.564691 1.227725 1.083513 -0.251326 0.172497
q: 4 lth: 3 v = -0.237004 -0.600963 3.055041
q: 5 lth: 3 v = 0.922136 -0.647184 0.396896
q: 6 lth: 3 v = -0.576292 0.195012 -0.103251
q: 7 lth: 1 v = 0.248173
NULL
SEXP DAIRY_PrintValue(SEXP ary) {
SEXP dim;
int q,l,i,j,k,r;
flt *p;
PROTECT(dim = GET_DIM(ary));
int * pDim = INTEGER_POINTER(AS_INTEGER(dim));
vector< vector< vector< vector<flt> > > > v;
v.resize(pDim[0]);
for (i=0;i<pDim[0];i++){
v[i].resize(pDim[1]);
for (j=0;j<pDim[1];j++) v[i][j].resize(pDim[2]);
}
Rprintf(“prM : Dim %d %d %d\n”,pDim[0],pDim[1],pDim[2]);
for(k=0;k<pDim[2];++k) {
for(j=0;j<pDim[1];++j) {
for(i=0;i<pDim[0];++i) {
q = i + j*pDim[0] + k*(pDim[0]*pDim[1]);
l = GET_LENGTH(VECTOR_ELT(ary, q));
p = NUMERIC_POINTER(VECTOR_ELT(ary, q));
Rprintf(“q: %d “,q);Rprintf(“lth: %d v = “,l);
v[i][j][k].resize(l);
for (r=0;r<l;++r) {
v[i][j][k][r] = p[r];
Rprintf(“%f “,p[r]);
}
Rprintf(“\n”);
}
}
}
UNPROTECT(1);
return R_NilValue;
}

Leave a Reply