This Creating sparse matrix in MEX has a good example on mxCreateSparse
. But this function return a double
sparse matrix instead of single
. If I want to return a single sparse matrix, what should I do ? Thanks !
Asked
Active
Viewed 2,751 times
2
-
Apparently you can't. See [this](http://www.mathworks.com/matlabcentral/newsreader/view_thread/246332) – Autonomous Dec 12 '13 at 19:32
-
Interesting question. Matlab's `sparse` function annoyingly only supports the double type, so it may a library-level limitation. E.g., `sparse(single(eye(3)))` returns "Undefined function 'sparse' for input arguments of type 'single'." – horchler Dec 12 '13 at 19:33
-
You might look into if the [SuiteSparse](http://www.cise.ufl.edu/research/sparse/SuiteSparse/) library itself supports single precision. – horchler Dec 12 '13 at 19:38
-
1Since Matlab doesn't understand what a single sparse matrix is, even if you could "return" one, it would fall flat. You need to re-think why you want to do that - and maybe not rely on Matlab at all (do everything in mex, leveraging other libraries as needed for your sparse math). I assume you are running into a memory issue... can you do this in smaller chunks (not all rows of the matrix at once)? – Floris Dec 12 '13 at 20:54
-
1Depending on your Matlab version you might try the undocumented `mxCreateSparseNumericMatrix` function ([see here](http://undocumentedmatlab.com/blog/undocumented-matlab-mex-api/)). I tried in R2013a on OS X and I'm not sure if it's still available there any more though so I can't say what it does. – horchler Dec 12 '13 at 20:55
1 Answers
3
As @horchler suggested, you could use the undocumented function mxCreateSparseNumericMatrix
. Example:
singlesparse.c
#include "mex.h"
#include <string.h> /* memcpy */
/* undocumented function prototype */
EXTERN_C mxArray *mxCreateSparseNumericMatrix(mwSize m, mwSize n,
mwSize nzmax, mxClassID classid, mxComplexity ComplexFlag);
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
const float pr[] = {1.0, 7.0, 5.0, 3.0, 4.0, 2.0, 6.0};
const mwIndex ir[] = {0, 2, 4, 2, 3, 0, 4};
const mwIndex jc[] = {0, 3, 5, 5, 7};
const mwSize nzmax = 10;
const mwSize m = 5;
const mwSize n = 4;
plhs[0] = mxCreateSparseNumericMatrix(m, n, nzmax, mxSINGLE_CLASS, mxREAL);
memcpy((void*)mxGetPr(plhs[0]), (const void*)pr, sizeof(pr));
memcpy((void*)mxGetIr(plhs[0]), (const void*)ir, sizeof(ir));
memcpy((void*)mxGetJc(plhs[0]), (const void*)jc, sizeof(jc));
}
Usage:
>> mex -largeArrayDims singlesparse.c
>> s = singlesparse()
s =
(1,1) 1
(3,1) 7
(5,1) 5
(3,2) 3
(4,2) 4
(1,4) 2
(5,4) 6
>> ss = double(s);
>> whos s ss
Name Size Bytes Class Attributes
s 5x4 160 single sparse
ss 5x4 152 double sparse
>> f = full(s)
One or more output arguments not assigned during call to "full".
>> f = full(ss)
f =
1 0 0 2
0 0 0 0
7 3 0 0
0 4 0 0
5 0 0 6
>> s + s;
Undefined function 'plus' for input arguments of type 'single' and attributes 'sparse 2d real'.
>> ss + ss;
>> 2 * s;
Error using *
Undefined function 'times' for input arguments of type 'single' and attributes 'sparse 2d real'.
>> 2 * ss;
>> s * s';
Error using *
MTIMES is not supported for one sparse input and one single input.
>> ss * ss';
>> nnz(s)
ans =
7
>> nzmax(s)
ans =
10
>> dmperm(s)
Undefined function 'dmperm' for input arguments of type 'single'.
>> dmperm(ss)
ans =
1 3 0 5
>> svds(s)
Error using horzcat
The following error occurred converting from double to single:
Error using single
Attempt to convert to unimplemented sparse type
Error in svds (line 64)
B = [sparse(m,m) A; A' sparse(n,n)];
>> svds(ss)
ans =
9.9249
5.5807
3.2176
0.0000
>> % abs(s), cos(s), sin(s), s.^2, s.*s, etc.. all give errors
As you can see, the sparse single array was created successfully, however many functions expect the array to be of type double
, so there is a lot of missing functionality...
Another restriction is that you cannot create multi-dimensional sparse arrays in MATLAB, they have to be 2D matrices..
Bottom line is: stick with double sparse 2D matrices in MATLAB!