1 /* ========================================================================== */
2 /* === csymamd mexFunction ================================================== */
3 /* ========================================================================== */
4
5 /* ----------------------------------------------------------------------------
6 * CCOLAMD, Copyright (C), Univ. of Florida. Authors: Timothy A. Davis,
7 * Sivasankaran Rajamanickam, and Stefan Larimore
8 * -------------------------------------------------------------------------- */
9
10 /*
11 * Usage:
12 * p = csymamd (A) ;
13 * [p stats] = csymamd (A, knobs, cmember) ;
14 *
15 * See csymamd.m for a description.
16 */
17
18 /* ========================================================================== */
19 /* === Include files ======================================================== */
20 /* ========================================================================== */
21
22 #include "ccolamd.h"
23 #include "mex.h"
24 #include "matrix.h"
25 #include <stdlib.h>
26 #define Long SuiteSparse_long
27
28 /* ========================================================================== */
29 /* === csymamd mexFunction ================================================== */
30 /* ========================================================================== */
31
mexFunction(int nargout,mxArray * pargout[],int nargin,const mxArray * pargin[])32 void mexFunction
33 (
34 /* === Parameters ======================================================= */
35
36 int nargout,
37 mxArray *pargout [ ],
38 int nargin,
39 const mxArray *pargin [ ]
40 )
41 {
42 /* === Local variables ================================================== */
43
44 Long *A ; /* row indices of input matrix A */
45 Long *perm ; /* column ordering of M and ordering of A */
46 Long *cmember ; /* csymamd's copy of the constraint set */
47 double *in_cmember ; /* input constraint set */
48 Long *p ; /* column pointers of input matrix A */
49 Long cslen ; /* size of constraint set */
50 Long n_col ; /* number of columns of A */
51 Long n_row ; /* number of rows of A */
52 Long full ; /* TRUE if input matrix full, FALSE if sparse */
53 double knobs [CCOLAMD_KNOBS] ; /* csymamd user-controllable parameters */
54 double *out_perm ; /* output permutation vector */
55 double *out_stats ; /* output stats vector */
56 double *in_knobs ; /* input knobs vector */
57 Long i ; /* loop counter */
58 mxArray *Ainput ; /* input matrix handle */
59 Long spumoni ; /* verbosity variable */
60 Long stats [CCOLAMD_STATS] ;/* stats for symamd */
61
62 /* === Check inputs ===================================================== */
63
64 if (nargin < 1 || nargin > 3 || nargout < 0 || nargout > 2)
65 {
66 mexErrMsgTxt ("Usage: [p stats] = csymamd (S, knobs, cmember)") ;
67 }
68
69 /* === Get cmember ====================================================== */
70
71 cmember = NULL ;
72 cslen = 0 ;
73 if (nargin > 2)
74 {
75 in_cmember = mxGetPr (pargin [2]) ;
76 cslen = mxGetNumberOfElements (pargin [2]) ;
77 if (cslen != 0)
78 {
79 cmember = (Long *) mxCalloc (cslen, sizeof (Long)) ;
80 for (i = 0 ; i < cslen ; i++)
81 {
82 /* convert cmember from 1-based to 0-based */
83 cmember[i] = ((Long) in_cmember [i] - 1) ;
84 }
85 }
86 }
87
88 /* === Get knobs ======================================================== */
89
90 ccolamd_l_set_defaults (knobs) ;
91 spumoni = 0 ;
92
93 /* check for user-passed knobs */
94 i = 0 ;
95 if (nargin > 1)
96 {
97 in_knobs = mxGetPr (pargin [1]) ;
98 i = mxGetNumberOfElements (pargin [1]) ;
99 if (i > 0) knobs [CCOLAMD_DENSE_ROW] = in_knobs [0] ;
100 if (i > 1) knobs [CCOLAMD_AGGRESSIVE] = in_knobs [1] ;
101 if (i > 2) spumoni = (in_knobs [2] != 0) ;
102 }
103
104 /* print knob settings if spumoni is set */
105 if (spumoni)
106 {
107 mexPrintf ("\ncsymamd version %d.%d, %s:\n",
108 CCOLAMD_MAIN_VERSION, CCOLAMD_SUB_VERSION, CCOLAMD_DATE) ;
109 if (knobs [CCOLAMD_DENSE_ROW] >= 0)
110 {
111 mexPrintf ("knobs(1): %g, rows/cols with > "
112 "max(16,%g*sqrt(size(A,2))) entries removed\n",
113 in_knobs [0], knobs [CCOLAMD_DENSE_ROW]) ;
114 }
115 else
116 {
117 mexPrintf ("knobs(1): %g, no dense rows removed\n",
118 in_knobs [0]) ;
119 }
120 mexPrintf ("knobs(2): %g, aggressive absorption: %s\n",
121 in_knobs [1], (knobs [CCOLAMD_AGGRESSIVE] != 0) ? "yes" : "no") ;
122 mexPrintf ("knobs(3): %g, statistics and knobs printed\n",
123 in_knobs [2]) ;
124 }
125
126 /* === If A is full, convert to a sparse matrix ========================= */
127
128 Ainput = (mxArray *) pargin [0] ;
129 if (mxGetNumberOfDimensions (Ainput) != 2)
130 {
131 mexErrMsgTxt ("csymamd: input matrix must be 2-dimensional.") ;
132 }
133 full = !mxIsSparse (Ainput) ;
134 if (full)
135 {
136 mexCallMATLAB (1, &Ainput, 1, (mxArray **) pargin, "sparse") ;
137 }
138
139 /* === Allocate workspace for csymamd =================================== */
140
141 /* get size of matrix */
142 n_row = mxGetM (Ainput) ;
143 n_col = mxGetN (Ainput) ;
144 if (n_col != n_row)
145 {
146 mexErrMsgTxt ("csymamd: matrix must be square.") ;
147 }
148
149 if (cmember != NULL && cslen != n_col)
150 {
151 mexErrMsgTxt ("csymamd: cmember must be of length equal to #cols of A");
152 }
153
154 A = (Long *) mxGetIr (Ainput) ;
155 p = (Long *) mxGetJc (Ainput) ;
156 perm = (Long *) mxCalloc (n_col+1, sizeof (Long)) ;
157
158 /* === Order the rows and columns of A (does not destroy A) ============= */
159
160 if (!csymamd_l (n_col, A, p, perm, knobs, stats, &mxCalloc, &mxFree,
161 cmember, -1))
162 {
163 csymamd_l_report (stats) ;
164 mexErrMsgTxt ("csymamd error!") ;
165 }
166
167 if (full)
168 {
169 mxDestroyArray (Ainput) ;
170 }
171
172 /* === Return the permutation vector ==================================== */
173
174 pargout [0] = mxCreateDoubleMatrix (1, n_col, mxREAL) ;
175 out_perm = mxGetPr (pargout [0]) ;
176 for (i = 0 ; i < n_col ; i++)
177 {
178 /* symamd is 0-based, but MATLAB expects this to be 1-based */
179 out_perm [i] = perm [i] + 1 ;
180 }
181 mxFree (perm) ;
182 mxFree (cmember) ;
183
184 /* === Return the stats vector ========================================== */
185
186 /* print stats if spumoni is set */
187 if (spumoni)
188 {
189 csymamd_l_report (stats) ;
190 }
191
192 if (nargout == 2)
193 {
194 pargout [1] = mxCreateDoubleMatrix (1, CCOLAMD_STATS, mxREAL) ;
195 out_stats = mxGetPr (pargout [1]) ;
196 for (i = 0 ; i < CCOLAMD_STATS ; i++)
197 {
198 out_stats [i] = stats [i] ;
199 }
200
201 /* fix stats (5) and (6), for 1-based information on jumbled matrix. */
202 /* note that this correction doesn't occur if symamd returns FALSE */
203 out_stats [CCOLAMD_INFO1] ++ ;
204 out_stats [CCOLAMD_INFO2] ++ ;
205 }
206 }
207