Sparse C MEX File

1 view (last 30 days)
Chris
Chris on 21 Jul 2011
It is pretty straightforward, take in a struct with a sparse matrix (.qmat) , and try to create a copy of the sparsity pattern for the matrix in a new matrix. It appears to work the first time I run the code and then produces a segmentation fault (in the SetIr/SetJC) steps the second time I run it.
#include <stdio.h>
#include <matrix.h>
#include <mex.h>
#include <string.h>
#include <math.h>
mwSize N,J,NS, L;
const mxArray *array_q;
void mexFunction(int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[]){
const mwSize *dim_array;
mwSize elements,number_of_dims, nsubs;
mxArray *weights_pointer;
mwIndex *jc,*ir;
/* Check for proper number of arguments */
if (nrhs != 2 ) {
mexErrMsgTxt("Two input arguments required.");
} else if (nlhs > 3) {
mexErrMsgTxt("Too many output arguments.");
}
/* Check data type of input argument */
if (!(mxIsStruct(prhs[0]) )) {
mexErrMsgTxt("Input 1 must be dataset structure.");
}
if((array_q=mxGetField(prhs[0], 0, "qmat"))==NULL){
mexErrMsgTxt("Include the Q Matrix");
}
weights_pointer=mxCreateSparse(mxGetM(array_q),mxGetN(array_q),mxGetNzmax(array_q),mxREAL);
if(weights_pointer==NULL){
mexErrMsgTxt("Can't allocate memory for target");
}
mexPrintf("NZ Original: %d \t NZ New: %d \n", mxGetNzmax(array_q), mxGetNzmax(weights_pointer));
if(mxGetIr(array_q) ==NULL || mxGetJc(array_q)==NULL){
mexErrMsgTxt("Problems in Sparse Matrix");
}
mxSetIr(weights_pointer,mxGetIr(array_q));
mxSetJc(weights_pointer,mxGetJc(array_q));
}

Answers (1)

James Tursa
James Tursa on 21 Jul 2011
This is causing the seg fault:
mxSetIr(weights_pointer,mxGetIr(array_q));
mxSetJc(weights_pointer,mxGetJc(array_q));
When you created the new mxArray weights_pointer you allocated memory for its Ir and Jc sparsity pattern data. You need to copy the sparsity pattern into these memory locations. What you have done is wiped out the Ir and Jc pointers (memory leaked the underlying memory) and replaced them with other pointers that point to a different mxArray. So you have in essence shared this memory between the two mxArray variables without telling MATLAB about it. So when MATLAB clears one it also clears memory that the other one is pointing to, so this other one is pointing to invalid memory at that point and it leads to a seg fault.
The fix? Either copy the Ir and Jc data from array_q to weights_pointer, or get rid of this method entirely and just use mxDuplicateArray to create a copy with the exact sparsity pattern of the argument. It will do a bit of extra work in copying the pr and pi data but it is the simplest programming approach.
  1 Comment
James Tursa
James Tursa on 22 Jul 2011
P.S. If you go the route of copying the Ir and Jc data you would need to fill in the pr (and potentially pi) data as well. If you leave 0's in those spots you would have an invalid sparse matrix since you would have 0's in the spots reserved for nonzero data.

Sign in to comment.

Categories

Find more on Write C Functions Callable from MATLAB (MEX Files) in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!