core/matlab/examples/refbook/fulltosparse.c

00001 /*=================================================================
00002 * fulltosparse.c
00003 * This example demonstrates how to populate a sparse
00004 * matrix.  For the purpose of this example, you must pass in a
00005 * non-sparse 2-dimensional argument of type double.
00006 
00007 * Comment: You might want to modify this MEX-file so that you can use
00008 * it to read large sparse data sets into MATLAB.
00009 *
00010 * This is a MEX-file for MATLAB.  
00011 * Copyright 1984-2006 The MathWorks, Inc.
00012 * All rights reserved.
00013 *=================================================================*/
00014 
00015 /* $Revision: 1.1 $ */
00016 
00017 #include <math.h> /* Needed for the ceil() prototype */
00018 #include "mex.h"
00019 
00020 /* If you are using a compiler that equates NaN to be zero, you must
00021  * compile this example using the flag  -DNAN_EQUALS_ZERO. For example:
00022  *
00023  *     mex -DNAN_EQUALS_ZERO fulltosparse.c
00024  *
00025  * This will correctly define the IsNonZero macro for your C compiler.
00026  */
00027 
00028 #if defined(NAN_EQUALS_ZERO)
00029 #define IsNonZero(d) ((d)!=0.0 || mxIsNaN(d))
00030 #else
00031 #define IsNonZero(d) ((d)!=0.0)
00032 #endif
00033 
00034 void mexFunction(
00035          int nlhs,       mxArray *plhs[],
00036          int nrhs, const mxArray *prhs[]
00037          )
00038 {
00039     /* Declare variable */
00040     mwSize m,n;
00041     mwSize nzmax;
00042     mwIndex *irs,*jcs,j,k;
00043     int cmplx,isfull;
00044     double *pr,*pi,*si,*sr;
00045     double percent_sparse;
00046     
00047     /* Check for proper number of input and output arguments */    
00048     if (nrhs != 1) {
00049     mexErrMsgTxt("One input argument required.");
00050     } 
00051     if(nlhs > 1){
00052     mexErrMsgTxt("Too many output arguments.");
00053     }
00054     
00055     /* Check data type of input argument  */
00056     if (!(mxIsDouble(prhs[0]))){
00057     mexErrMsgTxt("Input argument must be of type double.");
00058     }   
00059     
00060     if (mxGetNumberOfDimensions(prhs[0]) != 2){
00061     mexErrMsgTxt("Input argument must be two dimensional\n");
00062     }
00063 
00064     /* Get the size and pointers to input data */
00065     m  = mxGetM(prhs[0]);
00066     n  = mxGetN(prhs[0]);
00067     pr = mxGetPr(prhs[0]);
00068     pi = mxGetPi(prhs[0]);
00069     cmplx = (pi==NULL ? 0 : 1);
00070     
00071     /* Allocate space for sparse matrix 
00072      * NOTE:  Assume at most 20% of the data is sparse.  Use ceil
00073      * to cause it to round up. 
00074      */
00075 
00076     percent_sparse = 0.2;
00077     nzmax=(mwSize)ceil((double)m*(double)n*percent_sparse);
00078 
00079     plhs[0] = mxCreateSparse(m,n,nzmax,cmplx);
00080     sr  = mxGetPr(plhs[0]);
00081     si  = mxGetPi(plhs[0]);
00082     irs = mxGetIr(plhs[0]);
00083     jcs = mxGetJc(plhs[0]);
00084     
00085     /* Copy nonzeros */
00086     k = 0; 
00087     isfull=0;
00088     for (j=0; (j<n); j++) {
00089       mwSize i;
00090       jcs[j] = k;
00091       for (i=0; (i<m ); i++) {
00092     if (IsNonZero(pr[i]) || (cmplx && IsNonZero(pi[i]))) {
00093 
00094       /* Check to see if non-zero element will fit in 
00095        * allocated output array.  If not, increase percent_sparse 
00096        * by 10%, recalculate nzmax, and augment the sparse array
00097        */
00098       if (k>=nzmax){
00099         mwSize oldnzmax = nzmax;
00100         percent_sparse += 0.1;
00101         nzmax = (mwSize)ceil((double)m*(double)n*percent_sparse);
00102 
00103         /* make sure nzmax increases atleast by 1 */
00104         if (oldnzmax == nzmax) 
00105           nzmax++;
00106 
00107         mxSetNzmax(plhs[0], nzmax); 
00108         mxSetPr(plhs[0], mxRealloc(sr, nzmax*sizeof(double)));
00109         if(si != NULL)
00110           mxSetPi(plhs[0], mxRealloc(si, nzmax*sizeof(double)));
00111         mxSetIr(plhs[0], mxRealloc(irs, nzmax*sizeof(mwIndex)));
00112        
00113         sr  = mxGetPr(plhs[0]);
00114         si  = mxGetPi(plhs[0]);
00115         irs = mxGetIr(plhs[0]);
00116       }
00117       sr[k] = pr[i];
00118       if (cmplx){
00119         si[k]=pi[i];
00120       }
00121       irs[k] = i;
00122       k++;
00123         }    
00124       }
00125       pr += m;
00126       pi += m;
00127     }
00128     jcs[n] = k;
00129 }
00130  

GridLAB-DTM Version 1.0
An open-source project initiated by the US Department of Energy