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 !
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!
Related
A (hopefully efficiently) conversion from a binary number b into a decimal number d is
d = sum(b.*2.^(numel(b)-1:-1:0)) + 1
How would I efficiently (read: not using a for-loop) convert a vector of binary numbers bvec, e.g. the three binary numbers in bvec = logical([0 1;1 0;1 1]) into a vector of decimal numbers?
Use bin2dec.
>> str = reshape('0001011100110001', 8, [])'
str =
2×8 char array
'00010111'
'00110001'
>> bin2dec(str)
ans =
23
49
N.B. - Matlab is column-major, so reshaping a string can lead to unexpected results if not done carefully:
>> abc = 'abcdefghijklmnop';
>> reshape(abc, [], 8) % does not maintain original order
ans =
2×8 char array
'acegikmo'
'bdfhjlnp'
>> reshape(abc, 8, [])' % maintains original order
ans =
2×8 char array
'abcdefgh'
'ijklmnop'
I am writing a MEX code in which I need to use pinv function. I am trying to find a way to pass the array of type double to pinv using mexCallMATLAB in the most efficient way. Let's for the sake of example say the array is named G and its size is 100.
double *G = (double*) mxMalloc( 100 * sizeof(double) );
where
G[0] = G11; G[1] = G12;
G[2] = G21; G[3] = G22;
Which means every four consecutive elements of G is a 2×2 matrix. G stores 25 different values of this 2×2 matrix.
I should note that these 2×2 matrices are not well-conditioned and they may contain all zero in their element. How can I use pinv function to calculate the pseudoinverse in the elements of G? For example, how can I pass the array to mexCallMATLAB in order to calculate the pseudoinverse of the first 2×2 matrix in G?
I thought of the following approach:
mxArray *G_PINV_input = mxCreateDoubleMatrix(2, 2, mxREAL);
mxArray *G_PINV_output = mxCreateDoubleMatrix(2, 2, mxREAL);
double *G_PINV_input_ptr = mxGetPr(G_PINV_input);
memcpy( G_PINV_input_ptr, &G[0], 4 * sizeof(double));
mexCallMATLAB(1, G_PINV_output, 1, G_PINV_input, "pinv");
I am not sure how good this approach is. Copying the values is not economical at all because the total number of elements in G in my actual application is large. Is there anyway to skip this copying?
Here is my implementation of the MEX-function:
my_pinv.cpp
#include "mex.h"
void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
{
// validate arguments
if (nrhs!=1 || nlhs>1)
mexErrMsgIdAndTxt("mex:error", "Wrong number of arguments");
if (!mxIsDouble(prhs[0]) || mxIsComplex(prhs[0]) || mxIsSparse(prhs[0]))
mexErrMsgIdAndTxt("mex:error", "Input isnt real dense double array");
if (mxGetNumberOfElements(prhs[0]) != 100)
mexErrMsgIdAndTxt("mex:error", "numel() != 100");
// create necessary arrays
mxArray *rhs[1], *lhs[1];
plhs[0] = mxCreateDoubleMatrix(100, 1, mxREAL);
rhs[0] = mxCreateDoubleMatrix(2, 2, mxREAL);
double *in = mxGetPr(prhs[0]);
double *out = mxGetPr(plhs[0]);
double *x = mxGetPr(rhs[0]), *y;
// for each 2x2 matrix
for (mwIndex i=0; i<100; i+=4) {
// copy 2x2 matrix into rhs
x[0] = in[i+0];
x[2] = in[i+1];
x[1] = in[i+2];
x[3] = in[i+3];
// lhs = pinv(rhs)
mexCallMATLAB(1, lhs, 1, rhs, "pinv");
// copy 2x2 matrix from lhs
y = mxGetPr(lhs[0]);
out[i+0] = y[0];
out[i+1] = y[1];
out[i+2] = y[2];
out[i+3] = y[3];
// free array
mxDestroyArray(lhs[0]);
}
// cleanup
mxDestroyArray(rhs[0]);
}
Here is a baseline implementation in MATLAB so that we can verify the results are correct:
my_pinv0.m
function y = my_pinv0(x)
y = zeros(size(x));
for i=1:4:numel(x)
y(i:i+3) = pinv(x([0 1; 2 3]+i));
end
end
Now we test the MEX-function:
% some vector
x = randn(100,1);
% MEX vs. MATLAB function
y = my_pinv0(x);
yy = my_pinv(x);
% compare
assert(isequal(y,yy))
EDIT:
Here is an another implementation:
my_pinv2.cpp
#include "mex.h"
inline void call_pinv(const double &a, const double &b, const double &c,
const double &d, double *out)
{
mxArray *rhs[1], *lhs[1];
// create input matrix [a b; c d]
rhs[0] = mxCreateDoubleMatrix(2, 2, mxREAL);
double *x = mxGetPr(rhs[0]);
x[0] = a;
x[1] = c;
x[2] = b;
x[3] = d;
// lhs = pinv(rhs)
mexCallMATLAB(1, lhs, 1, rhs, "pinv");
// get values from output matrix
const double *y = mxGetPr(lhs[0]);
out[0] = y[0];
out[1] = y[1];
out[2] = y[2];
out[3] = y[3];
// cleanup
mxDestroyArray(lhs[0]);
mxDestroyArray(rhs[0]);
}
void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
{
// validate arguments
if (nrhs!=1 || nlhs>1)
mexErrMsgIdAndTxt("mex:error", "Wrong number of arguments");
if (!mxIsDouble(prhs[0]) || mxIsComplex(prhs[0]) || mxIsSparse(prhs[0]))
mexErrMsgIdAndTxt("mex:error", "Input isnt real dense double array");
if (mxGetNumberOfElements(prhs[0]) != 100)
mexErrMsgIdAndTxt("mex:error", "numel() != 100");
// allocate output
plhs[0] = mxCreateDoubleMatrix(100, 1, mxREAL);
double *out = mxGetPr(plhs[0]);
const double *in = mxGetPr(prhs[0]);
// for each 2x2 matrix
for (mwIndex i=0; i<100; i+=4) {
// 2x2 input matrix [a b; c d], and its determinant
const double a = in[i+0];
const double b = in[i+1];
const double c = in[i+2];
const double d = in[i+3];
const double det = (a*d - b*c);
if (det != 0) {
// inverse of 2x2 matrix [d -b; -c a]/det
out[i+0] = d/det;
out[i+1] = -c/det;
out[i+2] = -b/det;
out[i+3] = a/det;
}
else {
// singular matrix, fallback to pseudo-inverse
call_pinv(a, b, c, d, &out[i]);
}
}
}
This time we compute the determinant of the 2x2 matrix, if is non-zero, we calculate the inverse ourselves according to:
Otherwise we fallback to invoking PINV from MATLAB for the pseudo-inverse.
Here is quick benchmark:
% 100x1 vector
x = randn(100,1); % average case, with normal 2x2 matrices
% running time
funcs = {#my_pinv0, #my_pinv1, #my_pinv2};
t = cellfun(#(f) timeit(#() f(x)), funcs, 'Uniform',true);
% compare results
y = cellfun(#(f) f(x), funcs, 'Uniform',false);
assert(isequal(y{1},y{2}))
I get the following timings:
>> fprintf('%.6f\n', t);
0.002111 % MATLAB function
0.001498 % first MEX-file with mexCallMATLAB
0.000010 % second MEX-file with "unrolled" matrix inverse (+ PINV as fallback)
The error is acceptable and within machine precision:
>> norm(y{1}-y{3})
ans =
2.1198e-14
You could also test the worst case, when many of the 2x2 matrices are singular:
x = randi([0 1], [100 1]);
You don't need to allocate the output. Just make the pointer and let pinv create the mxArray automatically.
mxArray *lhs;
Then just use & like,
mexCallMATLAB(1, &lhs, 1, &rhs, "pinv");
I have a mex function that accepts double matrices as the input, but I just realized that the code this function is used for, can have single precision matrices as well. Is it possible to allow the function to accept either?
Or if not, what is an alternative way to fix this issue?
The simple solution would be to convert the inputs in MATLAB to a consistent type (presumably double), but if you would like to have your MEX function handle multiple types, here is one way.
Check the input type with mxIsSingle and mxIsDouble (or mxIsClass) and handle it accordingly. You might have an ifstatement in mexFunction that sets up the inputs and outputs and then calls a template function. See the example below, which thresholds all the values in an array using the C++ standard library function template std::min<T> without requiring any data conversion.
flexibleFunction.cpp
#include "mex.h"
#include <algorithm> // std::min
template <typename T>
void threshArrayLT(T *out, const T *arr, mwSize n, T c)
{ // you allocate out
for (mwSize i = 0; i < n; ++i)
out[i] = std::min<T>(arr[i], c);
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
if (nlhs > 1 || nrhs != 2)
mexErrMsgTxt("Syntax:\n\tH = flexibleFunction(arr,c)");
if (!mxIsDouble(prhs[0]) && !mxIsSingle(prhs[0]))
mexErrMsgTxt("Array must be double or single.");
if ((mxIsDouble(prhs[0]) && !mxIsDouble(prhs[1])) ||
(mxIsSingle(prhs[0]) && !mxIsSingle(prhs[1])))
mexErrMsgTxt("Arguments must have same type.");
const mwSize* dims = mxGetDimensions(prhs[0]);
int ndims = static_cast<int>(mxGetNumberOfDimensions(prhs[0]));
size_t numel = mxGetNumberOfElements(prhs[0]);
if (mxIsDouble(prhs[0])) {
double *arr = mxGetPr(prhs[0]);
double c = mxGetScalar(prhs[1]);
plhs[0] = mxCreateNumericArray(ndims,dims,mxDOUBLE_CLASS,mxREAL);
threshArrayLT(mxGetPr(plhs[0]),arr,numel,c);
// In reality, if it's this simple, use std::transform with lambda or bind:
//std::transform(arr, arr+numel, mxGetPr(plhs[0]),
// [&](double s){ return std::min(s,c); });
} else if (mxIsSingle(prhs[0])) {
float *arr = (float*)mxGetData(prhs[0]);
float c = static_cast<float>(mxGetScalar(prhs[1]));
plhs[0] = mxCreateNumericArray(ndims,dims,mxSINGLE_CLASS,mxREAL);
threshArrayLT((float*)mxGetData(plhs[0]),arr,numel,c);
}
}
You can also use function overloading in C++ (same name, different argument types).
Example
>> v = rand(1,8); c = 0.5;
>> whos v c
Name Size Bytes Class Attributes
c 1x1 8 double
v 1x8 64 double
>> flexibleFunction(v,c)
ans =
0.2760 0.5000 0.5000 0.1626 0.1190 0.4984 0.5000 0.3404
>> flexibleFunction(single(v),single(c))
ans =
0.2760 0.5000 0.5000 0.1626 0.1190 0.4984 0.5000 0.3404
Most answers only address the already-answered question about Hamming weights but ignore the point about find and dealing with the sparsity. Apparently the answer by Shai here addresses the point about find -- but I am not yet able to verify it. My answer here does not utilise the ingenuity of other answers such as the bitshifting but good enough example answer.
Input
>> mlf=sparse([],[],[],2^31+1,1);mlf(1)=10;mlf(10)=111;mlf(77)=1010;
>> transpose(dec2bin(find(mlf)))
ans =
001
000
000
011
001
010
101
Goal
1
0
0
2
1
1
2
Fast calculation for the amount of ones in binary numbers with the sparse structure?
You can do this in tons of ways. The simplest I think would be
% Example data
F = [268469248 285213696 536904704 553649152];
% Solution 1
sum(dec2bin(F)-'0',2)
And the fastest (as found here):
% Solution 2
w = uint32(F');
p1 = uint32(1431655765);
p2 = uint32(858993459);
p3 = uint32(252645135);
p4 = uint32(16711935);
p5 = uint32(65535);
w = bitand(bitshift(w, -1), p1) + bitand(w, p1);
w = bitand(bitshift(w, -2), p2) + bitand(w, p2);
w = bitand(bitshift(w, -4), p3) + bitand(w, p3);
w = bitand(bitshift(w, -8), p4) + bitand(w, p4);
w = bitand(bitshift(w,-16), p5) + bitand(w, p5);
According to your comments, you convert a vector of numbers to binary string representations using dec2bin. Then you can achieve what you want as follows, where I'm using vector [10 11 12] as an example:
>> sum(dec2bin([10 11 12])=='1',2)
ans =
2
3
2
Or equivalently,
>> sum(dec2bin([10 11 12])-'0',2)
For speed, you could avoid dec2bin like this (uses modulo-2 operations, inspired in dec2bin code):
>> sum(rem(floor(bsxfun(#times, [10 11 12].', pow2(1-N:0))),2),2)
ans =
2
3
2
where N is the maximum number of binary digits you expect.
If you really want fast, I think a look-up-table would be handy. You can simply map, for 0..255 how many ones they have. Do this once, and then you only need to decompose an int to its bytes look the sum up in the table and add the results - no need to go to strings...
An example:
>> LUT = sum(dec2bin(0:255)-'0',2); % construct the look up table (only once)
>> ii = uint32( find( mlf ) ); % get the numbers
>> vals = LUT( mod( ii, 256 ) + 1 ) + ... % lower bytes
LUT( mod( ii/256, 256 ) + 1 ) + ...
LUT( mod( ii/65536, 256 ) + 1 ) + ...
LUT( mod( ii/16777216, 256 ) + 1 );
Using typecast (as suggested by Amro):
>> vals = sum( reshape(LUT(double(typecast(ii,'uint8'))+1), 4, [] ), 1 )';
Run time comparison
>> ii = uint32(randi(intmax('uint32'),100000,1));
>> tic; vals1 = sum( reshape(LUT(typecast(ii,'uint8')+1), 4, [] ), 1 )'; toc, %//'
>> tic; vals2 = sum(dec2bin(ii)-'0',2); toc
>> dii = double(ii); % type issues
>> tic; vals3 = sum(rem(floor(bsxfun(#times, dii, pow2(1-32:0))),2),2); toc
Results:
Elapsed time is 0.006144 seconds. <-- this answer
Elapsed time is 0.120216 seconds. <-- using dec2bin
Elapsed time is 0.118009 seconds. <-- using rem and bsxfun
Here is an example to show #Shai's idea of using a lookup table:
% build lookup table for 8-bit integers
lut = sum(dec2bin(0:255)-'0', 2);
% get indices
idx = find(mlf);
% break indices into 8-bit integers and apply LUT
nbits = lut(double(typecast(uint32(idx),'uint8')) + 1);
% sum number of bits in each
s = sum(reshape(nbits,4,[]))
you might have to switch to uint64 instead if you have really large sparse arrays with large indices outside the 32-bit range..
EDIT:
Here is another solution for you using Java:
idx = find(mlf);
s = arrayfun(#java.lang.Integer.bitCount, idx);
EDIT#2:
Here is yet another solution implemented as C++ MEX function. It relies on std::bitset::count:
bitset_count.cpp
#include "mex.h"
#include <bitset>
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
// validate input/output arguments
if (nrhs != 1) {
mexErrMsgTxt("One input argument required.");
}
if (!mxIsUint32(prhs[0]) || mxIsComplex(prhs[0]) || mxIsSparse(prhs[0])) {
mexErrMsgTxt("Input must be a 32-bit integer dense matrix.");
}
if (nlhs > 1) {
mexErrMsgTxt("Too many output arguments.");
}
// create output array
mwSize N = mxGetNumberOfElements(prhs[0]);
plhs[0] = mxCreateDoubleMatrix(N, 1, mxREAL);
// get pointers to data
double *counts = mxGetPr(plhs[0]);
uint32_T *idx = reinterpret_cast<uint32_T*>(mxGetData(prhs[0]));
// count bits set for each 32-bit integer number
for(mwSize i=0; i<N; i++) {
std::bitset<32> bs(idx[i]);
counts[i] = bs.count();
}
}
Compile the above function as mex -largeArrayDims bitset_count.cpp, then run it as usual:
idx = find(mlf);
s = bitset_count(uint32(idx))
I decided to compare all the solutions mentioned so far:
function [t,v] = testBitsetCount()
% random data (uint32 vector)
x = randi(intmax('uint32'), [1e5,1], 'uint32');
% build lookup table (done once)
LUT = sum(dec2bin(0:255,8)-'0', 2);
% functions to compare
f = {
#() bit_twiddling(x) % bit twiddling method
#() lookup_table(x,LUT); % lookup table method
#() bitset_count(x); % MEX-function (std::bitset::count)
#() dec_to_bin(x); % dec2bin
#() java_bitcount(x); % Java Integer.bitCount
};
% compare timings and check results are valid
t = cellfun(#timeit, f, 'UniformOutput',true);
v = cellfun(#feval, f, 'UniformOutput',false);
assert(isequal(v{:}));
end
function s = lookup_table(x,LUT)
s = sum(reshape(LUT(double(typecast(x,'uint8'))+1),4,[]))';
end
function s = dec_to_bin(x)
s = sum(dec2bin(x,32)-'0', 2);
end
function s = java_bitcount(x)
s = arrayfun(#java.lang.Integer.bitCount, x);
end
function s = bit_twiddling(x)
p1 = uint32(1431655765);
p2 = uint32(858993459);
p3 = uint32(252645135);
p4 = uint32(16711935);
p5 = uint32(65535);
s = x;
s = bitand(bitshift(s, -1), p1) + bitand(s, p1);
s = bitand(bitshift(s, -2), p2) + bitand(s, p2);
s = bitand(bitshift(s, -4), p3) + bitand(s, p3);
s = bitand(bitshift(s, -8), p4) + bitand(s, p4);
s = bitand(bitshift(s,-16), p5) + bitand(s, p5);
end
The times elapsed in seconds:
t =
0.0009 % bit twiddling method
0.0087 % lookup table method
0.0134 % C++ std::bitset::count
0.1946 % MATLAB dec2bin
0.2343 % Java Integer.bitCount
This gives you the rowsums of the binary numbers from the sparse structure.
>> mlf=sparse([],[],[],2^31+1,1);mlf(1)=10;mlf(10)=111;mlf(77)=1010;
>> transpose(dec2bin(find(mlf)))
ans =
001
000
000
011
001
010
101
>> sum(ismember(transpose(dec2bin(find(mlf))),'1'),2)
ans =
1
0
0
2
1
1
2
Hope someone able to find faster rowsummation!
Mex it!
Save this code as countTransBits.cpp:
#include "mex.h"
void mexFunction( int nout, mxArray* pout[], int nin, mxArray* pin[] ) {
mxAssert( nin == 1 && mxIsSparse(pin[0]) && mxGetN( pin[0] ) == 1,
"expecting single sparse column vector input" );
mxAssert( nout == 1, "expecting single output" );
// set output, assuming 32 bits, set to 64 if needed
pout[0] = mxCreateNumericMatrix( 32, 1, mxUINT32_CLASS, mxREAL );
unsigned int* counter = (unsigned int*)mxGetData( pout[0] );
for ( int i = 0; i < 32; i++ ) {
counter[i] = 0;
}
// start working
mwIndex *pIr = mxGetIr( pin[0] );
mwIndex* pJc = mxGetJc( pin[0] );
double* pr = mxGetPr( pin[0] );
for ( mwSize i = pJc[0]; i < pJc[1]; i++ ) {
if ( pr[i] != 0 ) {// make sure entry is non-zero
unsigned int entry = pIr[i] + 1; // cast to unsigned int and add 1 for 1-based indexing in Matlab
int bit = 0;
while ( entry != 0 && bit < 32 ) {
counter[bit] += ( entry & 0x1 ); // count the lsb
bit++;
entry >>= 1; // shift right
}
}
}
}
Compile it in Matlab
>> mex -largeArrayDims -O countTransBits.cpp
Run the code
>> countTransBits( mlf )
Note that the output count in 32 bins lsb to msb.
The bitcount FEX contribution offers a solution based on the lookup table approach, but is better optimized. It runs more than twice as fast as the bit twiddling method (i.e. the fastest pure-MATLAB method reported by Amro) over a 1 million uint32 vector, using R2015a on my old laptop.
I understand that all the returned values of a mex function are stored in plhs array of type mxArray*. I want to return a value of type float. How can I do it?
Some code examples on returning it from the mex function and retrieving it from the m-file is much appreciated.
The MATLAB class name for float type data is "single".
In the MEX-file you could write:
void mexFunction(int nlhs, mxArray * plhs[], int nrhs, const mxArray * prhs[])
{
// Create a 2-by-3 real float
plhs[0] = mxCreateNumericMatrix(2, 3, mxSINGLE_CLASS, mxREAL);
// fill in plhs[0] to contain the same as single([1 2 3; 4 5 6]);
float * data = (float *) mxGetData(plhs[0]);
data[0] = 1; data[1] = 4; data[2] = 2;
data[3] = 5; data[4] = 3; data[5] = 6;
}
Retrieving it from the M-file is pretty much like calling any other function. If you named the MEX-function foo, you'd call it like this:
>> x = foo;
Now x would contain the single-precision value equivalent to single([1 2 3; 4 5 6]) that was stored in plhs[0].