Search code examples
cmatlabmex

mex runtime error: 64-bit mex files using sparse matrices must be rebuilt with the "-largeArrayDims" option


My c-code is supposed to convert Matlab sparse format to TAUCS format which is also a column major format.

Of course I am generating Matlab sparse format in Matlab itself and then transferring it to mex file.

Code compiles fine. But, when I try to run Matlab, I get the following runtime error:

Error using MatSparse_2_TAUCS
Function "mxGetJc_700" is obsolete.
(64-bit mex files using sparse matrices must be rebuilt with the "-largeArrayDims" option.  See the R2006b release notes for more details.)

Error in Matlab_mex_Testing (line 18)
    z = MatSparse_2_TAUCS(x, spMat);

I think that I already have used "-largeArrayDims" option in my make file.

Here is my Matlab code:

Dir  = '/home/dkumar/Mex_Codes_DKU/MexCode_Working/Mex_CPP_N_ARMADILLO_Codes_DKU_makefile_Working';

%Create a simple sparse matrix
spMat = speye(100, 100);
%Set few more elements to be non-zero
spMat(5, 8)   = 1.500;
spMat(5, 100) = 3.500;
spMat(19, 100) = 3.500;
spMat(59, 89)   = 1.500;

% MEX
cd(Dir);
x = 5.0;
z = MatSparse_2_TAUCS(x, spMat);

Here is my C-code:

    #include "mex.h"
#include <math.h>
#include <stdio.h>

#include "/home/dkumar/libtsnnls-2.3.3/tsnnls/taucs_basic/taucs.h"

extern void _main();

const int numInputArgs  = 2;
const int numOutputArgs = 1;

// Function declarations.
// -----------------------------------------------------------------

int TestingLibraries() ;   // declared and defined in In Include_4_TSNNLS.c and Include_4_TSNNLS.h


// Function definitions.
// -----------------------------------------------------------------
void mexFunction (int nlhs, mxArray *plhs[],
          int nrhs, const mxArray *prhs[]) {

    double *y, *z, x;

    /* Declare variable */
    mwSize mrows,ncols;
    int status;
    mwSize nzmax;
    mwIndex *irs,*jcs,j,k;

    /*  Check for proper number of arguments. */
    if (nrhs != 2) 
        mexErrMsgTxt("Two inputs required.");
    if (nlhs != 1) 
        mexErrMsgTxt("One output required.");

    /* Check to make sure the first input argument is a scalar. */
    if (!mxIsDouble(prhs[0]) ||     mxIsComplex(prhs[0]) || mxGetN(prhs[0])*mxGetM(prhs[0]) != 1) {
        mexErrMsgTxt("Input x must be a scalar.");
    }

    /* Get the scalar input x. */
    x = mxGetScalar(prhs[0]);

    /* Create a pointer to the input matrix y. */
    y = mxGetPr(prhs[1]);


     /* Check data type dimensions of the matrix input y. */
    if (!(mxIsDouble(prhs[1]))){
        mexErrMsgIdAndTxt( "MATLAB:DKU", "Input argument must be of type double.");
    }

    if (mxGetNumberOfDimensions(prhs[1]) != 2){
        mexErrMsgIdAndTxt( "MATLAB:DKU", "Input argument must be two dimensional\n");
    }

     /* Get the size and pointers to input data */
    mrows =mxGetM(prhs[1]);
    ncols = mxGetN(prhs[1]);

    // Declaring the matrix in TAUCS
    taucs_ccs_matrix *A;

    // Verify the matrix y is infact sparse
    if (!(mxIsSparse(prhs[1]))){
        mexErrMsgIdAndTxt( "MATLAB: DKU", "Input matrix is not sparse\n");
    }else{
        //Work with irs and jcs directly instead of row-column pairs that are less compact.  
        double* sr      = mxGetPr(prhs[1]);   
        jcs         = mxGetJc(prhs[1]);     
        irs         = mxGetIr(prhs[1]);

    // Now converting sparse matrix to TAUCS format
        A       = (taucs_ccs_matrix*)malloc(sizeof(taucs_ccs_matrix));
        A->n        = ncols;
        A->m        = mrows;   
        A->flags    = TAUCS_DOUBLE;

        // Allocating spaces
        int nnz     = jcs[ncols]; 
        A->colptr       = (int*)mxMalloc(sizeof(int)*(A->n+1));
        A->rowind       = (int*)mxMalloc(sizeof(int)*nnz);
        A->values.d     = (double*)mxMalloc(sizeof(taucs_double)*nnz);  

        int icolOffset = 0;  // both matlab "SPARSE" indices and TAUCS  "SPARSE" indices start with 0 

    A->colptr   = jcs-icolOffset;
        A->rowind   = irs-icolOffset;
        A->values.d     = sr;
    }


    /* Create a C pointer to a copy of the output matrix. */
     //memcpy(mxGetPr(plhs[0]), &A, sizeof(A)); 

    //Freeing spaces
    mxFree(A->colptr);
    mxFree(A->rowind);
    mxFree(A->values.d);  

    //Creating plhs: just some fake value
   mwSize sz[2];
   sz[0] = mrows  ; // Matlab is row first
   sz[1] = ncols  ;
   plhs[0] = mxCreateNumericArray(2, sz, mxDOUBLE_CLASS, mxREAL);
   //Get a pointer to pOUT
   double* p2 = (double*)mxGetData(plhs[0]);
   // just copying input matrix
   int i1;

   for (i1 =0; i1 < mrows*ncols; i1++)
   {
    *p2 = *y;
         p2++; y++;
   }

}

Here is my makefile:

  MEXSUFFIX  = mexa64
  MATLABHOME = /usr/local/MATLAB/R2011b
  MEX        = /usr/local/MATLAB/R2011b/bin/mex
  CXX        = gcc
  CFLAGS     = -fPIC -pthread -DMX_COMPAT_32 \
               -DMATLAB_MEX_FILE  -largeArrayDims


  LIBS      = -lm
  INCLUDE   = -I$(MATLABHOME)/extern/include
  MEXFLAGS  = -cxx CC='$(CXX)' CXX='$(CXX)' LD='$(CXX)' -largeArrayDims

  REBUILDABLES = *.o *.mexa64     ## Anything with these extension
  TARGET = MatSparse_2_TAUCS.$(MEXSUFFIX)

  all : $(TARGET)
    echo All done

  clean : 
    rm -f $(REBUILDABLES)   
    echo Clean done

  $(TARGET): MatSparse_2_TAUCS.o
    $(MEX) $(MEXFLAGS) $(LIBS) -output MatSparse_2_TAUCS $^

  MatSparse_2_TAUCS.o: Include_4_TSNNLS.c MatSparse_2_TAUCS.c
    $(CXX) $(CFLAGS) $(INCLUDE) -c $^

Also, I get some warning about memcpy when I run my makefile:

Output of make:

$ make
gcc -fPIC -pthread -DMX_COMPAT_32 -DMATLAB_MEX_FILE  -largeArrayDims -I/usr/local/MATLAB/R2011b/extern/include -c Include_4_TSNNLS.c MatSparse_2_TAUCS.c
MatSparse_2_TAUCS.c: In function ‘mexFunction’:
MatSparse_2_TAUCS.c:98:6: warning: incompatible implicit declaration of built-in function ‘memcpy’ [enabled by default]
      memcpy(mxGetPr(plhs[0]), &A, sizeof(A)); 
      ^
/usr/local/MATLAB/R2011b/bin/mex -cxx CC='gcc' CXX='gcc' LD='gcc' -largeArrayDims -lm -output MatSparse_2_TAUCS MatSparse_2_TAUCS.o

Warning: You are using gcc version "4.8.2-19ubuntu1)".  The version
         currently supported with MEX is "4.3.4".
         For a list of currently supported compilers see: 
         http://www.mathworks.com/support/compilers/current_release/

echo All done
All done

Some help would be appreciated.

UPDATE:

Info about TAUCS or taucs_ccs_matrix page 12 of the link

updated the c-code as per suggestion of @chappjc


Solution

  • Defining MX_COMPAT_32 in CFLAGS is incompatible with the -largeArrayDims option for the mex command. In fact, it does the opposite. I made a note about how these options work near the bottom of this post. It is actually the -compatibleArrayDims option that sets MX_COMPAT_32, which you don't want.

    Also note that -largeArrayDims is an option for the mex command, so it goes on MEXFLAGS rather than CFLAGS. I'm pretty sure gcc doesn't know what to do with that switch. Just don't define MX_COMPAT_32.

    It does look like you could try to set MX_INTERNAL_730 and keep MX_COMPAT_32 if you want to stick with 32-bit indexing, but don't do that.