简体   繁体   中英

Creating a MATLAB mex function for matrix cross product

I created the following .c file to compute the cross product of each row of the mx 3 matrices A and B . When I run mex crossprod.c it builds fine, but when I try to run the function I get a MATLAB System Error which says that MATLAB has encountered an internal problem and needs to close. Any suggestions?

Here's the code I wrote:

// [C] = crossprod(A,B)
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
size_t m;
double **A, **B;
double **C;
int i;
m = mxGetM(prhs[0]);
A = mxGetData(prhs[0]);
B = mxGetData(prhs[1]);
plhs[0] = mxCreateDoubleMatrix((int) m, 3, mxREAL);
C = mxGetPr(plhs[0]);
for(i = 0; i<m; i++)
C[i][0] = A[i][1]*B[i][2] - A[i][2]*B[i][1];
C[i][1] = A[i][0]*B[i][2] - A[i][2]*B[i][0];
C[i][2] = A[i][0]*B[i][1] - A[i][1]*B[i][0];
}

Two fundamental errors, and one slight error:

  1. You're using a double pointer to a pointer for accessing memory that is passed to your MEX wrapper from MATLAB, as well as using this to write data to the output. In MEX when you allocate memory for arrays and matrices, or when you're accessing data that MATLAB passes to the MEX wrapper, it's just a single pointer. To access data in MEX where it's higher than 1 dimension, MATLAB actually interleaves all of the data into a single 1D array, so you need to use the right indexing to get the data you want. You also need to access the elements using column-major order. Therefore, you can't use 2D indexing. I would also use mxGetPr instead of mxGetData as your data consists of all real numbers.

  2. Your for loop has a slight typo. You forgot to enclose all of the statements inside the for loop with braces. Without it, you are only running the first statement, and the other two statements only run once.... when the loop finishes.

  3. The second line of your cross product calculation, when compute the y value of your 3D vector is slightly incorrect. You need to reverse the terms. Specifically, you must do this:

     C[i][1] = A[i][2]*B[i][0] - A[i][0]*B[i][2]; 

However, the above method of accessing is incorrect, and we'll fix that soon.


Therefore, you need to change your MEX file to:

// [C] = crossprod(A,B)
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    size_t m;
    double *A, *B; // Change
    double *C;
    int i;
    m = mxGetM(prhs[0]);
    A = mxGetPr(prhs[0]); // Change
    B = mxGetPr(prhs[1]); // Change

    plhs[0] = mxCreateDoubleMatrix((int) m, 3, mxREAL);
    C = mxGetPr(plhs[0]);

    // Major change - Using column major indexing
    for(i = 0; i < m; i++) {
        C[i] = A[i + m]*B[i + 2*m] - A[i + 2*m]*B[i + m];
        C[i + m] = A[i + 2*m]*B[i] - A[i]*B[i + 2*m]; // Change here too
        C[i + 2*m] = A[i]*B[i + m] - A[i + m]*B[i];
    }
}

Everything is simple enough except for the for loop. When accessing 2D arrays in MATLAB, we use a pointer to point to the memory, but the memory is 1D interleaved. You access the memory in column-major format. As such, for a row i and column j , you would access a 2D matrix A at this location like so:

A[i + j*m]

m would be the total number of rows. Therefore, A[i][0] would simply be A[i] , A[i][1] would be A[i + m] and finally A[i][2] would be A[i + 2*m] . I used this to translate your code above.


To show this working, I decided to compile this on my machine, and run it through a sample A and B matrix:

>> A = [1 2 3; 4 5 6; 7 8 9]
>> B = [7 8 9; 5 6 2; 5 5 6]
>> C = crossprod(A, B)

C =

    -6    12    -6
   -26    22    -1
     3     3    -5

Comparing with MATLAB's cross command, we can do this by operating over the columns where each row is considered a 3D vector:

>> C2 = cross(A, B, 2)

C2 =

    -6    12    -6
   -26    22    -1
     3     3    -5

As you can see, both the MEX code and MATLAB's cross function match.


Good luck!

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