mxCreateNumericMatrix and sparse matrix in C/Matlab hybrid programming
Show older comments
Hi,
I was doing C/Matlab hybrid programming. Basically I need to load into Matlab a sparse matrix with entries in M and indeices in MI and MJ.
Below is what I have, and the error message I received is:
Undefined function 'sparse' for input arguments of type 'int16'
I am not sure whether I create the matrices MI and MJ wrongly, or Matlab does not support sparse operation in this manner.
Thanks!
Paul
------------------
M_matlab = mxCreateDoubleMatrix(1, nzero, mxREAL);
MI_matlab = mxCreateNumericMatrix(1, nzero, mxINT16_CLASS, mxREAL);
MJ_matlab = mxCreateNumericMatrix(1, nzero, mxINT16_CLASS, mxREAL);
memcpy((void *)mxGetPr(M_matlab), (void *)M, sizeof(M));
memcpy((void *)mxGetPr(MI_matlab), (void *)MI, sizeof(MI));
memcpy((void *)mxGetPr(MJ_matlab), (void *)MJ, sizeof(MJ));
engPutVariable(ep, "M", M_matlab);
engPutVariable(ep, "MI", MI_matlab);
engPutVariable(ep, "MJ", MJ_matlab);
engEvalString(ep, "MS=sparse(MI,MJ,M);");
Accepted Answer
More Answers (1)
James Tursa
on 18 Jul 2020
Edited: James Tursa
on 19 Jul 2020
Convert the index arrays to double either inside the C code or on the Engine side. E.g.,
engEvalString(ep, "MS=sparse(double(MI),double(MJ),M);");
P.S. Your memcpy stuff will only work if M and MI and MJ are arrays. It won't work if M and MI and MJ are pointers because the sizeof(etc) will not give you the number of bytes to copy ... they will only give you the size of the pointers. You would need an expression involving nzero instead if M and MI and MJ are pointers. E.g.,
memcpy(mxGetData(M_matlab), M, nzero*sizeof(*M));
memcpy(mxGetData(MI_matlab), MI, nzero*sizeof(*MI));
memcpy(mxGetData(MJ_matlab), MJ, nzero*sizeof(*MJ));
or
mwSize i;
double *mi, *mj;
MI_matlab = mxCreateDoubleMatrix(1, nzero, mxREAL);
MJ_matlab = mxCreateDoubleMatrix(1, nzero, mxREAL);
mi = (double *) mxGetData(MI_matlab);
mj = (double *) mxGetData(MJ_matlab);
for( i=0; i<nzero; i++ ) {
mi[i] = MI[i];
mj[i] = MJ[i];
}
SIDE NOTE: Note that your method has four deep copies of the data floating around in memory at the same time:
1) The original data inside your C code
2) A copy of the data in your C code in your mxArray variables
3) A copy of the data when you put the mxArray variables into the Engine via engPutVariable
4) A copy of the data when you called the sparse( ) function in the Engine
What are you doing with that sparse matrix downstream in your code? Maybe some of this data duplication can be eliminated by changing things.
5 Comments
Paul Zhou
on 4 Aug 2020
James Tursa
on 4 Aug 2020
Edited: James Tursa
on 4 Aug 2020
Any suggestions would depend on where this sparse data is originally coming from. Generated by your C/C++ code, or read from a file, or ...?
Once you solve the linear system, do you pull the solution back into your C/C++ code?
Are you open to using a mex routine instead of an Engine application?
Paul Zhou
on 5 Aug 2020
Bruno Luong
on 5 Aug 2020
Migh I suggest - if not already done- that you break the mex in two parts
- generating the sparse matrix
- Processing of solution of sparse matrix
in between MATLAB will get the sparse matrix as LHS of the first mex and call "\" or whatever operator to compute the solution the feed the solution as RHS of the second mex.
It seems more natural and more clealy architectured like that than making a big C-mex code with usage of engEvalString, mxCallMatlab to perform the MATLAB task in betwenn as you seem to intend to carry out the task.
Rylan
on 9 Jan 2022
Hi, @Paul Zhou, how about creating the sparse matrix in C and processing of the solution in C, i.e. we don't transfer the sparse matrix back to matlab. If so, maybe this process can be much faster. Is this possible?
Categories
Find more on Resizing and Reshaping Matrices 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!