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