简体   繁体   中英

How to read input matrix of a Matlab mex function row-wise?

I need create a Matlab mex function that will take an input matrix and return the matrix diagonal.

Input:

1 2 3
4 5 6

Expected output:

1 2 3 0 0 0
0 0 0 4 5 6

My problem is that since Matlab reads matrices column-wise instead of row-wise, my mex function gives the wrong output.

Current output:

1 4 0 0 0 0
0 0 2 5 0 0
0 0 0 0 3 6

How would you go about changing my code to read the input matrix row-wise so I can have the proper output?

My code is as follows:

#include <matrix.h>
#include <mex.h>

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
        mxArray *a_in, *b_out;
        const mwSize *dims;
        double *a, *b; 
        int rows, cols;

        // Input array:
        a_in = mxDuplicateArray(prhs[0]);

        // Get dimensions of input array:
        dims = mxGetDimensions(prhs[0]);
        rows = (int) dims[0];
        cols = (int) dims[1];

        // Output array:
        if(rows == cols){
            b_out = plhs[0] = mxCreateDoubleMatrix(rows, rows*cols, mxREAL);
        }
        else{
            b_out = plhs[0] = mxCreateDoubleMatrix(cols, rows*cols, mxREAL);
        }
        // Access the contents of the input and output arrays:
        a = mxGetPr(a_in);
        b = mxGetPr(b_out);
        

        // Compute exdiag function of the input array
        int count = 0;
        for (int i = 0; i < rows; i++) {
            for(int j = 0; j<cols;j++){
                if(rows == cols){
                    b[rows*count+count/rows] = a[j + rows * i];
                    count++;
                }
                else if(rows < cols){
                    b[cols*count+count/rows] = a[j + cols * i];
                    count++;
                }
                else if(rows>cols){
                    b[cols*count+count/rows] = a[j + cols * i];
                    count++;
                }
            }
    }
}

Inside your loops, i is the row index and j is the column index. You do a[j + rows * i] , mixing up the two indices. MATLAB stores data column-wise, so you need to do a[i + rows * j] to read the input matrix correctly.

For indexing the output, you want the row to remain i , and you want the column to be i * cols + j :

b[i + rows * (i * cols + j)] = a[i + rows * j];

Note that you don't need to do a_in = mxDuplicateArray(prhs[0]) , since you are not writing into a_in . You can directly access the prhs[0] matrix, or do a_in = prhs[0] if you want an alias.

Also, casting array sizes to int will cause trouble if the array is very large. It is best to use mwSize and mwIndex for array sizes and indices.

Finally, you should always check the type of the input array, if you are given an array that is not doubles, you will likely cause a read out of bounds error.


This is my code:

#include <matrix.h>
#include <mex.h>

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
   mwSize const* dims;
   double *a, *b;
   mwSize rows, cols;
   
   if (!mxIsDouble(prhs[0])) {
      mexErrMsgTxt("Input must be doubles");
   }
   
   // Get dimensions of input array:
   dims = mxGetDimensions(prhs[0]);
   rows = dims[0];
   cols = dims[1];
   
   // Output array:
   plhs[0] = mxCreateDoubleMatrix(rows, rows*cols, mxREAL);

   // Access the contents of the input and output arrays:
   a = mxGetPr(prhs[0]);
   b = mxGetPr(plhs[0]);
   
   // Compute exdiag function of the input array
   for (mwIndex i = 0; i < rows; i++) {
      for (mwIndex j = 0; j < cols; j++) {
         b[i + rows * (i * cols + j)] = a[i + rows * j];
      }
   }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM