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. 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;
Larissa, So is the problem "in the matrix reference is mat[col][row] whereas in R it is mar[row, col]?" The solution is just recognizing the difference in references. Dave On Fri, Dec 6, 2013 at 7:21 AM, Larissa Hauer <larissahauer@googlemail.com>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. > > 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@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel >[[alternative HTML version deleted]]
Hi Larissa,> 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.<snip> R uses column-major order [1] because that's the order used by FORTRAN and R uses many libraries with a FORTRAN interface (most important: BLAS and LAPACK for numerical linear algebra.) That's the situation with many other languages / libraries that use similar interfaces, such as MATLAB, Octave, Julia, and Scilab [1]. So, there's no way around it and you just have to get used to referencing matrix entries in col-major order. [1] http://en.wikipedia.org/wiki/Row-major_order> Here's an example of C code that simply prints the matrix it gets from R:<snip> Try this instead: #include <stdlib.h> #include "R.h" void printMatrix(int *mPtr, int m, int n) { int j,k; for(j = 0; j < m; j++){ for(k = 0; k < n; k++) { printf("%d\t", mPtr[j + m * k]); } printf("\n"); } }> 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.Specifying byrow=TRUE only changes how the matrix is *read*, not how it's stored. A matrix -- and, more generally, an array -- is in fact just a vector with (dimension) attributes, but that just specifies the memory layout of the matrix, and not its representation (that is, it doesn't help.) Unfortunately, there's no way to avoid this, but it shouldn't be too bad to get used to it. :) Cheers, Luis -- Computers are useless. They can only give you answers. -- Pablo Picasso -- Luis Carvalho (Kozure) lua -e 'print((("lexcarvalho at NO.gmail.SPAM.com"):gsub("(%u+%.)","")))'
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