/* spouterprod.c * Bert Huang * bert@cs.columbia.edu * * This mex function provides a fast sparse outer product, which is * useful when you need sparse entries in a large, dense outer product. * The input is a sparse mask, and full matrices U and V * The output is a sparse matrix with nonzeros where the mask is nonzero, * and is equivelent to the matlab expression mask.*(U*V') * * Unfortunately matlab does not compute the above expression efficiently, * so this mex file is helpful. * * Compile by typing 'mex spouterprod.c' * * Copyright 2009, 2010 Bert Huang * Feel free to contact the author with any questions or suggestions. * * * Updates: * * 5/27/10 - updated to support 64-bit matlab. Compile with -largeArrayDims * * Known Issues: * * - Code does not take advantage of multithreading * - Does not support sparse U and V * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "mex.h" void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { mwSize *ir, *jc, *ir_out, *jc_out; int nnz=0, M, N, D, i, j, row, column; double *U, *V, *out, *data; mxArray *Ut, *Vt, *RHS[1], *LHS[1]; if (nrhs != 3) mexErrMsgTxt("Input error: Expected sparse mask, U, V, 1 output"); if (!mxIsSparse(prhs[0])) mexErrMsgTxt("Error: Mask must be sparse\n"); if (mxIsSparse(prhs[1]) || mxIsSparse(prhs[2])) mexErrMsgTxt("Error: sparse U or V is not implemented yet"); //load input ir = mxGetIr(prhs[0]); jc = mxGetJc(prhs[0]); M = mxGetM(prhs[0]); N = mxGetN(prhs[0]); nnz = jc[N]; if (mxGetM(prhs[1]) == M && mxGetM(prhs[2]) == N) { //transpose U and V for faster memory access RHS[0] = prhs[1]; mexCallMATLAB(1, LHS, 1, RHS, "transpose"); Ut = LHS[0]; RHS[0] = prhs[2]; mexCallMATLAB(1, LHS, 1, RHS, "transpose"); Vt = LHS[0]; U = mxGetData(Ut); V = mxGetData(Vt); D = mxGetN(prhs[1]); } else if (mxGetN(prhs[1])==M && mxGetN(prhs[2])==N) { D = mxGetM(prhs[1]); U = mxGetPr(prhs[1]); V = mxGetPr(prhs[2]); } else mexErrMsgTxt("Error: Matrix sizes are incorrect"); //open output plhs[0] = mxCreateSparse(M, N, nnz, 0); out = mxGetPr(plhs[0]); ir_out = mxGetIr(plhs[0]); jc_out = mxGetJc(plhs[0]); column=0; jc_out[0] = jc[0]; for (i=0; i=jc[column+1]) { column++; } //printf("Nonzero at %d, %d\n", row,column); out[i] = 0; for (j=0; j1e128) out[i] = 1e128; } for (i=0; i