External Interfaces  Manipulating Multidimensional Numerical Arrays

You can manipulate multidimensional numerical arrays by using `mxGetData` and `mxGetImagData` to return pointers to the real and imaginary parts of the data stored in the original multidimensional array. This example takes an N-dimensional array of doubles and returns the indices for the nonzero elements in the array.

• ```/*
* =============================================================
* findnz.c
* Example for illustrating how to handle N-dimensional arrays in
* a MEX-file. NOTE: MATLAB uses 1-based indexing, C uses 0-based
* indexing.
*
* Takes an N-dimensional array of doubles and returns the indices
* for the non-zero elements in the array. findnz works
* differently than the FIND command in MATLAB in that it returns
* all the indices in one output variable, where the column
* element contains the index for that dimension.
*
*
* This is a MEX-file for MATLAB.
* Copyright (c) 1984-2000 by The MathWorks, Inc.
* =============================================================
*/

/* \$Revision: 1.5 \$ */

#include "mex.h"

/* If you are using a compiler that equates NaN to zero, you must
* compile this example using the flag -DNAN_EQUALS_ZERO. For
* example:
*
*     mex -DNAN_EQUALS_ZERO findnz.c
*
* This will correctly define the IsNonZero macro for your
compiler. */

#if NAN_EQUALS_ZERO
#define IsNonZero(d) ((d) != 0.0 || mxIsNaN(d))
#else
#define IsNonZero(d) ((d) != 0.0)
#endif

void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
/* Declare variables. */
int elements, j, number_of_dims, cmplx;
int nnz = 0, count = 0;
double *pr, *pi, *pind;
const int  *dim_array;

/* Check for proper number of input and output arguments. */
if (nrhs != 1) {
mexErrMsgTxt("One input argument required.");
}
if (nlhs > 1) {
mexErrMsgTxt("Too many output arguments.");
}

/* Check data type of input argument. */
if (!(mxIsDouble(prhs))) {
mexErrMsgTxt("Input array must be of type double.");
}

/* Get the number of elements in the input argument. */
elements = mxGetNumberOfElements(prhs);

/* Get the data. */
pr = (double *)mxGetPr(prhs);
pi = (double *)mxGetPi(prhs);
cmplx = ((pi == NULL) ? 0 : 1);

/* Count the number of non-zero elements to be able to allocate
the correct size for output variable. */
for (j = 0; j < elements; j++) {
if (IsNonZero(pr[j]) || (cmplx && IsNonZero(pi[j]))) {
nnz++;
}
}

/* Get the number of dimensions in the input argument.
Allocate the space for the return argument */
number_of_dims = mxGetNumberOfDimensions(prhs);
plhs = mxCreateDoubleMatrix(nnz, number_of_dims, mxREAL);
pind = mxGetPr(plhs);

/* Get the number of dimensions in the input argument. */
dim_array = mxGetDimensions(prhs);

/* Fill in the indices to return to MATLAB. This loops through
* the elements and checks for non-zero values. If it finds a
* non-zero value, it then calculates the corresponding MATLAB
* indices and assigns them into the output array. The 1 is
added
* to the calculated index because MATLAB is 1-based and C is
* 0-based. */
for (j = 0; j < elements; j++) {
if (IsNonZero(pr[j]) || (cmplx && IsNonZero(pi[j]))) {
int temp = j;
int k;
for (k = 0; k < number_of_dims; k++) {
pind[nnz*k+count] = ((temp % (dim_array[k])) + 1);
temp /= dim_array[k];
}
count++;
}
}
}
```

Entering a sample matrix at the MATLAB prompt gives

• ```matrix = [ 3 0 9 0; 0 8 2 4; 0 9 2 4; 3 0 9 3; 9 9 2 0]
matrix =
3     0     9     0
0     8     2     4
0     9     2     4
3     0     9     3
9     9     2     0
```

This example determines the position of all nonzero elements in the matrix. Running the MEX-file on this matrix produces

• ```nz = findnz(matrix)
nz =
1     1
4     1
5     1
2     2
3     2
5     2
1     3
2     3
3     3
4     3
5     3
2     4
3     4
4     4
``` Handling 8-,16-, and 32-Bit Data Handling Sparse Arrays © 1994-2005 The MathWorks, Inc.