How to get a pointer to 2D array when writing a C source Mex file?

Hi, I'm trying to write a highly simple C source .mex file (function) that takes a 1 x n vector and n x n matrix, and yields their matrix product, again a 1 x n vector (all the arrays are of binary and I'm doing computations for binary case). My concern is how to get a pointer to 2D array,(e.g the line arr = mxGetDoubles(prhs[1]);) I tried mxGetDoubles as it works for 1xn arrays, but I came across with the warning ": assignment from incompatible pointer type [-Wincompatible-pointer-types]". I then tried mxGetData; it did not give any warnings yet when I called the function from the command window, MATLAB crashed and was forced to close.
I would be highly appreciated if anyone can help me out. Thanks and here is the whole .c code:
/*==========================================================
* arrayMultiplier.c
*
* Multiplies a 1xN matrix with a N X N matrix
* and outputs a 1xN matrix
*
* The calling syntax is:
* outMatrix = arrayProduct(vector, array)
*========================================================*/
#include "mex.h"
/* The computational routine */
void arrayMultiplier( double *vec, double **arr, mwSize n ,double *z){
for (mwSize i=0; i<n; i++) {
for(mwSize j=0; j<n; j++) {
z[i] += vec[j]*arr[j][i];
}
z[i] = (double)((int)z[i] % 2);
}
}
/* The gateway function */
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[]) {
double *vec;
double **arr;
mwSize nr;
double *outMatrix;
nr = mxGetN(prhs[0]); /*The "n" parameter of the 1 x n output matrix*/
vec = mxGetDoubles(prhs[0]);
arr = mxGetData(prhs[1]); /* This is where the warning appears */
/* creating the output matrix */
plhs[0] = mxCreateDoubleMatrix(1,nr,mxREAL);
/* get a pointer to the real data in the output matrix */
outMatrix = mxGetDoubles(plhs[0]);
/* call the computational routine */
arrayMultiplier(vec,arr,nr,outMatrix);
}

 Accepted Answer

You can't use the [j][i] indexing syntax with the pointer returned by mxGetDoubles. You would need to set up a separate pointer array in order to use this syntax (never worth it IMO), or just do the indexing calculations manually (my preference).
E.g., make these changes in mexFunction:
double *arr; // **arr changed to *arr
:
arr = mxGetDoubles(prhs[1]);
And make these changes in arrayMultiplier:
void arrayMultiplier( double *vec, double *arr, mwSize n ,double *z){ // **arr changed to *arr
:
z[i] += vec[j] * (*arr++);
Since the 2D matrix is stored column-wise and the vector is on the left of the multiply, you can access the 2D matrix in a simple linear fashion with the *arr++ syntax. A functionally equivalent version using explicit indexing would have been this (but with extra unneeded indexing calculations for this particular case):
z[i] += vec[j] * arr[j+i*n]; // Manually calculate the equivalent linear index

3 Comments

I know you say this isn't worth it, but how would you set up a separate pointer array to use the [i][j] syntax? My code uses that syntax way more then the original poster, and I'm trying to figure out how to get it to work correctly. I'm getting the same incompatible error.
I don't have MATLAB or C handy at the moment, but an outline for a 2d matrix is something like this:
#define ARR(i,j) arr[j][i]
double **arr;
mwSize i, j, m, n;
:
m = mxGetM(prhs[1]);
n = mxGetN(prhs[1]);
arr = (double **) mxMalloc( n * sizeof(*arr) );
arr[0] = mxGetDoubles(prhs[1]);
for( j=1; j<n; j++ ) {
arr[j] = arr[j-1] + m; // The column pointers
}
:
// Then use arr[j][i] in your code, i is row and j is column, 0-based
// Or use ARR(i,j) in your code, i is row and j is column, 0-based
:
mxFree(arr);
Note that when using arr[j][i] syntax the j comes first, since MATLAB array memory is column ordered. But when using the macro ARR(i,j) the i comes first since that is how I have defined the macro to work.
If you really want to use the syntax arr[i][j] with i (row) first and j (column) second, you would have to copy all of the 2D matrix values to new memory (essentially transposing it). This, IMO, is too high a price to pay and I don't include that code here.

Sign in to comment.

More Answers (1)

mxGetDoubles will always be pointer to double, with the pointer being to the column-major linear storage of the data. To use this as a 2D array at the C level, you need to cast it to the appropriate double vec[m,n] declaration.

2 Comments

I am trying to do something similar to original poster, how do you cast it as the appropriate double declaration? I am knew to C and 2D arrays and pointers all all new to me.
In my c code, I use a lot of arr[i][j] indexing syntax.

Sign in to comment.

Categories

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!