1 /* ========================================================================== */
2 /* === symamd mexFunction =================================================== */
3 /* ========================================================================== */
4 
5 /* SYMAMD mexFunction
6 
7     Usage:
8 
9 	P = symamd2 (A) ;
10 	[ P, stats ] = symamd2 (A, knobs) ;
11 
12     See symamd.m for a description.
13 
14     Authors:
15 
16 	The authors of the code itself are Stefan I. Larimore and Timothy A.
17 	Davis (DrTimothyAldenDavis@gmail.com).  The algorithm was
18 	developed in collaboration with John Gilbert, Xerox PARC, and Esmond
19 	Ng, Oak Ridge National Laboratory.
20 
21     Acknowledgements:
22 
23 	This work was supported by the National Science Foundation, under
24 	grants DMS-9504974 and DMS-9803599.
25 
26     Notice:
27 
28 	Copyright (c) 1998-2007, Timothy A. Davis.  All Rights Reserved.
29 	See COLAMD/Doc/License.txt for the License.
30 
31     Availability:
32 
33 	The colamd/symamd library is available at http://www.suitesparse.com
34 
35 */
36 
37 /* ========================================================================== */
38 /* === Include files ======================================================== */
39 /* ========================================================================== */
40 
41 #include "colamd.h"
42 #include "mex.h"
43 #include "matrix.h"
44 #include <stdlib.h>
45 #define Long SuiteSparse_long
46 
47 /* ========================================================================== */
48 /* === symamd mexFunction =================================================== */
49 /* ========================================================================== */
50 
mexFunction(int nlhs,mxArray * plhs[],int nrhs,const mxArray * prhs[])51 void mexFunction
52 (
53     /* === Parameters ======================================================= */
54 
55     int nlhs,			/* number of left-hand sides */
56     mxArray *plhs [],		/* left-hand side matrices */
57     int nrhs,			/* number of right--hand sides */
58     const mxArray *prhs []	/* right-hand side matrices */
59 )
60 {
61     /* === Local variables ================================================== */
62 
63     Long *perm ;                /* column ordering of M and ordering of A */
64     Long *A ;                   /* row indices of input matrix A */
65     Long *p ;                   /* column pointers of input matrix A */
66     Long n_col ;                /* number of columns of A */
67     Long n_row ;                /* number of rows of A */
68     Long full ;                 /* TRUE if input matrix full, FALSE if sparse */
69     double knobs [COLAMD_KNOBS] ; /* colamd user-controllable parameters */
70     double *out_perm ;          /* output permutation vector */
71     double *out_stats ;         /* output stats vector */
72     double *in_knobs ;          /* input knobs vector */
73     Long i ;                    /* loop counter */
74     mxArray *Ainput ;           /* input matrix handle */
75     Long spumoni ;              /* verbosity variable */
76     Long stats [COLAMD_STATS] ; /* stats for symamd */
77 
78     /* === Check inputs ===================================================== */
79 
80     if (nrhs < 1 || nrhs > 2 || nlhs < 0 || nlhs > 2)
81     {
82 	mexErrMsgTxt (
83 	"symamd: incorrect number of input and/or output arguments.") ;
84     }
85 
86     /* === Get knobs ======================================================== */
87 
88     colamd_l_set_defaults (knobs) ;
89     spumoni = 0 ;
90 
91     /* check for user-passed knobs */
92     if (nrhs == 2)
93     {
94 	in_knobs = mxGetPr (prhs [1]) ;
95 	i = mxGetNumberOfElements (prhs [1]) ;
96 	if (i > 0) knobs [COLAMD_DENSE_ROW] = in_knobs [0] ;
97 	if (i > 1) spumoni = (Long) (in_knobs [1] != 0) ;
98     }
99 
100     /* print knob settings if spumoni is set */
101     if (spumoni)
102     {
103 	mexPrintf ("\nsymamd version %d.%d, %s:\n",
104 	    COLAMD_MAIN_VERSION, COLAMD_SUB_VERSION, COLAMD_DATE) ;
105 	if (knobs [COLAMD_DENSE_ROW] >= 0)
106 	{
107 	    mexPrintf ("knobs(1): %g, rows/cols with > "
108 		"max(16,%g*sqrt(size(A,2))) entries removed\n",
109 		in_knobs [0], knobs [COLAMD_DENSE_ROW]) ;
110 	}
111 	else
112 	{
113 	    mexPrintf ("knobs(1): %g, no dense rows removed\n", in_knobs [0]) ;
114 	}
115 	mexPrintf ("knobs(2): %g, statistics and knobs printed\n",
116 	    in_knobs [1]) ;
117     }
118 
119     /* === If A is full, convert to a sparse matrix ========================= */
120 
121     Ainput = (mxArray *) prhs [0] ;
122     if (mxGetNumberOfDimensions (Ainput) != 2)
123     {
124 	mexErrMsgTxt ("symamd: input matrix must be 2-dimensional.") ;
125     }
126     full = !mxIsSparse (Ainput) ;
127     if (full)
128     {
129 	mexCallMATLAB (1, &Ainput, 1, (mxArray **) prhs, "sparse") ;
130     }
131 
132     /* === Allocate workspace for symamd ==================================== */
133 
134     /* get size of matrix */
135     n_row = mxGetM (Ainput) ;
136     n_col = mxGetN (Ainput) ;
137     if (n_col != n_row)
138     {
139 	mexErrMsgTxt ("symamd: matrix must be square.") ;
140     }
141 
142     A = (Long *) mxGetIr (Ainput) ;
143     p = (Long *) mxGetJc (Ainput) ;
144     perm = (Long *) mxCalloc (n_col+1, sizeof (Long)) ;
145 
146     /* === Order the rows and columns of A (does not destroy A) ============= */
147 
148     if (!symamd_l (n_col, A, p, perm, knobs, stats, &mxCalloc, &mxFree))
149     {
150 	symamd_l_report (stats) ;
151 	mexErrMsgTxt ("symamd error!") ;
152     }
153 
154     if (full)
155     {
156 	mxDestroyArray (Ainput) ;
157     }
158 
159     /* === Return the permutation vector ==================================== */
160 
161     plhs [0] = mxCreateDoubleMatrix (1, n_col, mxREAL) ;
162     out_perm = mxGetPr (plhs [0]) ;
163     for (i = 0 ; i < n_col ; i++)
164     {
165 	/* symamd is 0-based, but MATLAB expects this to be 1-based */
166 	out_perm [i] = perm [i] + 1 ;
167     }
168     mxFree (perm) ;
169 
170     /* === Return the stats vector ========================================== */
171 
172     /* print stats if spumoni is set */
173     if (spumoni)
174     {
175 	symamd_l_report (stats) ;
176     }
177 
178     if (nlhs == 2)
179     {
180 	plhs [1] = mxCreateDoubleMatrix (1, COLAMD_STATS, mxREAL) ;
181 	out_stats = mxGetPr (plhs [1]) ;
182 	for (i = 0 ; i < COLAMD_STATS ; i++)
183 	{
184 	    out_stats [i] = stats [i] ;
185 	}
186 
187 	/* fix stats (5) and (6), for 1-based information on jumbled matrix. */
188 	/* note that this correction doesn't occur if symamd returns FALSE */
189 	out_stats [COLAMD_INFO1] ++ ;
190 	out_stats [COLAMD_INFO2] ++ ;
191     }
192 }
193