From murdoch.duncan at gmail.com  Fri Dec  6 15:38:51 2013
From: murdoch.duncan at gmail.com (Duncan Murdoch)
Date: Fri, 06 Dec 2013 09:38:51 -0500
Subject: [Rd] Matrix memory layout R vs. C
In-Reply-To: <52A1CF46.7070408@googlemail.com>
References: <52A1CF46.7070408@googlemail.com>
Message-ID: <52A1E17B.8090200@gmail.com>

On 06/12/2013 8:21 AM, Larissa Hauer wrote:
> Hi everybody,
>
> I'm trying to pass a matrix from R to C, where some computation is done
> for performance reasons, and back to R for evaluation. But I've run into
> the problem that R and C seem to have different ways of representing the
> matrix in main memory. The C representation of a 2D matrix in linear
> memory is concatenation of the rows whereas in R, it's a concatenation
> of the columns.  That leads to the problem. that an R-matrix, for example
> 123
> 456
> 789
> is seen by C as
> 147
> 258
> 369
> and vice versa.
>
> Here's an example of C code that simply prints the matrix it gets from R:
>
> #include <stdlib.h>
> #include "R.h"
>
> void printMatrix(int *mPtr, int *m, int *n) {
>     int (*matrix)[*n] = mPtr;
>
>     int j,k;
>
>     for(j = 0; j < *m; j++){
>       for(k = 0; k < *n; k++) {
>         printf("%d", matrix[j][k]);
>       }
>     printf("\n");
>     }
> }
>
> And here's what happens when I call the function in R:
>
> > m <- 3; n <- 3
> > mat <- matrix(c(1:9), nrow=m, ncol=n, byrow=TRUE)
> > mat
>        [,1] [,2] [,3]
> [1,]    1    2    3
> [2,]    4    5    6
> [3,]    7    8    9
> > mat <- .C("printMatrix", mat, as.integer(m), as.integer(n))[[1]]
> 147
> 258
> 369
>
>
> No matter if you create the matrix with byrow=TRUE or FALSE, C always
> interprets it the other way round. Is there a way to avoid this? I've
> read previous posts on passing a matrix from R to C, but the essence of
> the answers was that "a matrix in R is just a vector with attributes",
> but I don't see how this helps. Maybe someone can clarify.

I would not assume that a 2D matrix in C doesn't have gaps in it between 
the rows.  Let C treat it as a vector, and write a little macro that 
does the indexing.  For example,

#define INDEX(i,j) (i) + rows*(j)

Then mPtr[INDEX(i,j)] will do R-style indexing (except it will be 
0-based, not 1-based.  You could fix that too if you wanted.)

Duncan Murdoch
>
> Thanks a lot in advance!
>
> Cheers
> Larissa
>
> Here's the C main function showing that the C code itself is correct:
>
> #include <stdlib.h>
>
> void printMatrix(int *mPtr, int *m, int *n);
>
> int main(void) {
>     int m, n, i;
>     int *mPtr, *nPtr;
>     m = 3;
>     n = 3;
>     mPtr = &m;
>     nPtr = &n;
>
>     int *M = malloc(m * n * sizeof(int));
>
>     for (i = 0; i < m * n; i++){
>     M[i] = i + 1;
>     }
>
>     printMatrix(M, mPtr, nPtr);
>
>     return EXIT_SUCCESS;
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel



[Rd] Matrix memory layout R vs. C
Duncan Murdoch