Hi, I'm having some trouble with a bit of combined C & R code. I'm trying to write a C function to handle the for loops in a function I'm working on to calculate a similarity matrix. Jari Oksanen has kindly added the necessary changes to the vegan package so that I can use the vegdist function, so this isn't absolutely necessary. However, I'm stubborn and want to know why Jari's code works and mine doesn't! Other than, of course, the obvious - one of us knows what their doing and the other doesn't. I would appreciate any help. What I've done is: pass a matrix x to my C function, as a double: .C("gowsim", as.double(mat), as.integer(nrow(mat)), as.integer(ncol(mat))) Then I try and reconstruct the matrix, in the form of a C array: #include <R.h> #include <Rmath.h> #include <math.h> void gowsim ( double *mat, int *OBJ, int *MATDESC) { double x [*MATDESC][*OBJ]; int i, j, nrow, ncol; nrow = *OBJ; ncol = *MATDESC; /* Rebuild Matrix */ for (j=0; j < ncol; j++) { for (i=0; i < nrow; i++) { x[i][j] = *mat; Rprintf("row %d col %d value %f\n", i, j, x[i][j]); mat++; } } for (i=0; i< nrow; i++) { Rprintf("%f %f %f %f\n", x[i][0], x[i][1], x[i][2], x[i][3]); } } The Rprintf statements display what's going on at each step. It looks for all the world as if the assignments are working properly, but when I try and print the matrix I get very strange results. If mat is 3x3 or 4x4 everything seems ok. But if mat is not symetrical the resulting x matrix is very strange. In the case of a 5x4 mat only the first column works out, and for 3x4 mat the second and third positions in the first column are replaced by the first and second positions of the last column. I'm guessing that I've messed up something in my use of pointers, or perhaps the for loop, but I can't for the life of me figure out what!! Once I sort this out I'll be calculating the differences between rows in the x array en route to producing a similarity matrix. I looked at the vegdist code, which is fancier than this, and manages to avoid rebuilding the matrix entirely, but it's a bit beyond me. I'm using WindowsXP, R 2.1.0 (2005-04-18), and the MinGW compiler. Thanks for your continued patience, Tyler -- Tyler Smith PhD Candidate Department of Plant Science McGill University 21,111 Lakeshore Road Ste. Anne de Bellevue, Quebec H9X 3V9 CANADA Tel: 514 398-7851 ext. 8726 Fax: 514 398-7897 tyler.smith at mail.mcgill.ca
You have the dimensions switched, in double x [*MATDESC][*OBJ]; so when the dimensions aren't equal you do get odd things. You might be better off defining functions to index into mat with a pair of subscripts directly (.C() copies the argument anyway). Come to think of it, there might be macros/functions for this in Rinternals.h. Then you don't need to worry about row-major vs column-major order and related issues. Finally, as this is a C programming question, it should go to R-devel. Reid Huntsinger -----Original Message----- From: r-help-bounces@stat.math.ethz.ch [mailto:r-help-bounces@stat.math.ethz.ch] On Behalf Of Tyler Smith Sent: Tuesday, April 26, 2005 11:02 AM To: R-Help Subject: [R] Advice for calling a C function Hi, I'm having some trouble with a bit of combined C & R code. I'm trying to write a C function to handle the for loops in a function I'm working on to calculate a similarity matrix. Jari Oksanen has kindly added the necessary changes to the vegan package so that I can use the vegdist function, so this isn't absolutely necessary. However, I'm stubborn and want to know why Jari's code works and mine doesn't! Other than, of course, the obvious - one of us knows what their doing and the other doesn't. I would appreciate any help. What I've done is: pass a matrix x to my C function, as a double: .C("gowsim", as.double(mat), as.integer(nrow(mat)), as.integer(ncol(mat))) Then I try and reconstruct the matrix, in the form of a C array: #include <R.h> #include <Rmath.h> #include <math.h> void gowsim ( double *mat, int *OBJ, int *MATDESC) { double x [*MATDESC][*OBJ]; int i, j, nrow, ncol; nrow = *OBJ; ncol = *MATDESC; /* Rebuild Matrix */ for (j=0; j < ncol; j++) { for (i=0; i < nrow; i++) { x[i][j] = *mat; Rprintf("row %d col %d value %f\n", i, j, x[i][j]); mat++; } } for (i=0; i< nrow; i++) { Rprintf("%f %f %f %f\n", x[i][0], x[i][1], x[i][2], x[i][3]); } } The Rprintf statements display what's going on at each step. It looks for all the world as if the assignments are working properly, but when I try and print the matrix I get very strange results. If mat is 3x3 or 4x4 everything seems ok. But if mat is not symetrical the resulting x matrix is very strange. In the case of a 5x4 mat only the first column works out, and for 3x4 mat the second and third positions in the first column are replaced by the first and second positions of the last column. I'm guessing that I've messed up something in my use of pointers, or perhaps the for loop, but I can't for the life of me figure out what!! Once I sort this out I'll be calculating the differences between rows in the x array en route to producing a similarity matrix. I looked at the vegdist code, which is fancier than this, and manages to avoid rebuilding the matrix entirely, but it's a bit beyond me. I'm using WindowsXP, R 2.1.0 (2005-04-18), and the MinGW compiler. Thanks for your continued patience, Tyler -- Tyler Smith PhD Candidate Department of Plant Science McGill University 21,111 Lakeshore Road Ste. Anne de Bellevue, Quebec H9X 3V9 CANADA Tel: 514 398-7851 ext. 8726 Fax: 514 398-7897 tyler.smith@mail.mcgill.ca ______________________________________________ R-help@stat.math.ethz.ch mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html
Thank you. I can't believe how much time I spent going over that short bit of code without noticing that I had switched the dimensions. I was sure there was some arcane bit of pointer-lore that was eluding me. Patrick Burns pointed out an alternative approach to me, leaving the data in the form of a double vector. The index in the double vector corresponding to the matrix location can be calculated from: Rmatrix [row,col] is equivalent to: Cvector [(row-1) + (col-1)*nrows(Rmatrix)] This is easily inserted inside a for loop, sidestepping the whole issue of rebuilding a matrix. This has the added bonus that I don't have to break the matrix back down into a vector to pass it back to R. Thank you all for your very helpful advice. Since most of this discussion has been in the R-help list, that's where I sent this post. In future I'll direct my C questions to the devel list. Hopefully, any further questions I have won't involve anything so silly as switching indexes. Cheers, Tyler Tyler Smith PhD Candidate Department of Plant Science McGill University 21,111 Lakeshore Road Ste. Anne de Bellevue, Quebec H9X 3V9 CANADA Tel: 514 398-7851 ext. 8726 Fax: 514 398-7897 tyler.smith at mail.mcgill.ca Huntsinger, Reid wrote:>You have the dimensions switched, in > > double x [*MATDESC][*OBJ]; > >so when the dimensions aren't equal you do get odd things. > >You might be better off defining functions to index into mat with a pair of >subscripts directly (.C() copies the argument anyway). Come to think of it, >there might be macros/functions for this in Rinternals.h. Then you don't >need to worry about row-major vs column-major order and related issues. > >Finally, as this is a C programming question, it should go to R-devel. > >Reid Huntsinger > >-----Original Message----- >From: r-help-bounces at stat.math.ethz.ch >[mailto:r-help-bounces at stat.math.ethz.ch] On Behalf Of Tyler Smith >Sent: Tuesday, April 26, 2005 11:02 AM >To: R-Help >Subject: [R] Advice for calling a C function > > >Hi, > >I'm having some trouble with a bit of combined C & R code. I'm trying to >write a C function to handle the for loops in a function I'm working on >to calculate a similarity matrix. Jari Oksanen has kindly added the >necessary changes to the vegan package so that I can use the vegdist >function, so this isn't absolutely necessary. However, I'm stubborn and >want to know why Jari's code works and mine doesn't! Other than, of >course, the obvious - one of us knows what their doing and the other >doesn't. I would appreciate any help. What I've done is: > >pass a matrix x to my C function, as a double: > >.C("gowsim", as.double(mat), as.integer(nrow(mat)), as.integer(ncol(mat))) > > Then I try and reconstruct the matrix, in the form of a C array: > >#include <R.h> >#include <Rmath.h> >#include <math.h> > >void gowsim ( double *mat, int *OBJ, int *MATDESC) > { > double x [*MATDESC][*OBJ]; > int i, j, nrow, ncol; > nrow = *OBJ; > ncol = *MATDESC; > > /* Rebuild Matrix */ > for (j=0; j < ncol; j++) { > for (i=0; i < nrow; i++) { > x[i][j] = *mat; > Rprintf("row %d col %d value %f\n", i, j, x[i][j]); > mat++; > } > } > for (i=0; i< nrow; i++) { > Rprintf("%f %f %f %f\n", x[i][0], x[i][1], x[i][2], x[i][3]); > } >} > >The Rprintf statements display what's going on at each step. It looks >for all the world as if the assignments are working properly, but when I >try and print the matrix I get very strange results. If mat is 3x3 or >4x4 everything seems ok. But if mat is not symetrical the resulting x >matrix is very strange. In the case of a 5x4 mat only the first column >works out, and for 3x4 mat the second and third positions in the first >column are replaced by the first and second positions of the last >column. I'm guessing that I've messed up something in my use of >pointers, or perhaps the for loop, but I can't for the life of me figure >out what!! Once I sort this out I'll be calculating the differences >between rows in the x array en route to producing a similarity matrix. I >looked at the vegdist code, which is fancier than this, and manages to >avoid rebuilding the matrix entirely, but it's a bit beyond me. > >I'm using WindowsXP, R 2.1.0 (2005-04-18), and the MinGW compiler. > >Thanks for your continued patience, > >Tyler > > >