Mercurial > octave-nkf
comparison src/DLD-FUNCTIONS/colamd.cc @ 5440:b73d469ef0c9
[project @ 2005-09-04 12:31:45 by dbateman]
ChangeLog
author | dbateman |
---|---|
date | Sun, 04 Sep 2005 12:31:45 +0000 |
parents | 4c8a2e4e0717 |
children | ed08548b9054 |
comparison
equal
deleted
inserted
replaced
5439:ca7ebff13a16 | 5440:b73d469ef0c9 |
---|---|
38 #include "ov-re-mat.h" | 38 #include "ov-re-mat.h" |
39 | 39 |
40 #include "ov-re-sparse.h" | 40 #include "ov-re-sparse.h" |
41 #include "ov-cx-sparse.h" | 41 #include "ov-cx-sparse.h" |
42 | 42 |
43 #if SIZEOF_INT == SIZEOF_OCTAVE_IDX_TYPE | |
44 | |
45 // External COLAMD functions in C | 43 // External COLAMD functions in C |
46 extern "C" { | 44 extern "C" { |
47 #include "COLAMD/colamd.h" | 45 #include "COLAMD/colamd.h" |
48 } | 46 } |
49 | 47 |
48 #ifdef IDX_TYPE_LONG | |
49 #define COLAMD_NAME(name) colamd_l ## name | |
50 #define SYMAMD_NAME(name) symamd_l ## name | |
51 #else | |
52 #define COLAMD_NAME(name) colamd ## name | |
53 #define SYMAMD_NAME(name) symamd ## name | |
54 #endif | |
55 | |
50 // The symmetric column elimination tree code take from the Davis LDL code. | 56 // The symmetric column elimination tree code take from the Davis LDL code. |
51 // Copyright given elsewhere in this file. | 57 // Copyright given elsewhere in this file. |
52 static | 58 static |
53 void symetree (const int *ridx, const int *cidx, int *Parent, int *P, int n) | 59 void symetree (const octave_idx_type *ridx, const octave_idx_type *cidx, |
54 { | 60 octave_idx_type *Parent, octave_idx_type *P, octave_idx_type n) |
55 OCTAVE_LOCAL_BUFFER (int, Flag, n); | 61 { |
56 OCTAVE_LOCAL_BUFFER (int, Pinv, (P ? n : 0)); | 62 OCTAVE_LOCAL_BUFFER (octave_idx_type, Flag, n); |
63 OCTAVE_LOCAL_BUFFER (octave_idx_type, Pinv, (P ? n : 0)); | |
57 if (P) | 64 if (P) |
58 // If P is present then compute Pinv, the inverse of P | 65 // If P is present then compute Pinv, the inverse of P |
59 for (int k = 0 ; k < n ; k++) | 66 for (octave_idx_type k = 0 ; k < n ; k++) |
60 Pinv [P [k]] = k ; | 67 Pinv [P [k]] = k ; |
61 | 68 |
62 for (int k = 0 ; k < n ; k++) | 69 for (octave_idx_type k = 0 ; k < n ; k++) |
63 { | 70 { |
64 // L(k,:) pattern: all nodes reachable in etree from nz in A(0:k-1,k) | 71 // L(k,:) pattern: all nodes reachable in etree from nz in A(0:k-1,k) |
65 Parent [k] = n ; // parent of k is not yet known | 72 Parent [k] = n ; // parent of k is not yet known |
66 Flag [k] = k ; // mark node k as visited | 73 Flag [k] = k ; // mark node k as visited |
67 int kk = (P) ? (P [k]) : (k) ; // kth original, or permuted, column | 74 octave_idx_type kk = (P) ? (P [k]) : (k) ; // kth original, or permuted, column |
68 int p2 = cidx [kk+1] ; | 75 octave_idx_type p2 = cidx [kk+1] ; |
69 for (int p = cidx [kk] ; p < p2 ; p++) | 76 for (octave_idx_type p = cidx [kk] ; p < p2 ; p++) |
70 { | 77 { |
71 // A (i,k) is nonzero (original or permuted A) | 78 // A (i,k) is nonzero (original or permuted A) |
72 int i = (Pinv) ? (Pinv [ridx [p]]) : (ridx [p]) ; | 79 octave_idx_type i = (Pinv) ? (Pinv [ridx [p]]) : (ridx [p]) ; |
73 if (i < k) | 80 if (i < k) |
74 { | 81 { |
75 // follow path from i to root of etree, stop at flagged node | 82 // follow path from i to root of etree, stop at flagged node |
76 for ( ; Flag [i] != k ; i = Parent [i]) | 83 for ( ; Flag [i] != k ; i = Parent [i]) |
77 { | 84 { |
85 } | 92 } |
86 } | 93 } |
87 | 94 |
88 // The elimination tree post-ordering code below is taken from SuperLU | 95 // The elimination tree post-ordering code below is taken from SuperLU |
89 static inline | 96 static inline |
90 int make_set (int i, int *pp) | 97 octave_idx_type make_set (octave_idx_type i, octave_idx_type *pp) |
91 { | 98 { |
92 pp[i] = i; | 99 pp[i] = i; |
93 return i; | 100 return i; |
94 } | 101 } |
95 | 102 |
96 static inline | 103 static inline |
97 int link (int s, int t, int *pp) | 104 octave_idx_type link (octave_idx_type s, octave_idx_type t, octave_idx_type *pp) |
98 { | 105 { |
99 pp[s] = t; | 106 pp[s] = t; |
100 return t; | 107 return t; |
101 } | 108 } |
102 | 109 |
103 static inline | 110 static inline |
104 int find (int i, int *pp) | 111 octave_idx_type find (octave_idx_type i, octave_idx_type *pp) |
105 { | 112 { |
106 register int p, gp; | 113 register octave_idx_type p, gp; |
107 | 114 |
108 p = pp[i]; | 115 p = pp[i]; |
109 gp = pp[p]; | 116 gp = pp[p]; |
110 while (gp != p) { | 117 while (gp != p) { |
111 pp[i] = gp; | 118 pp[i] = gp; |
115 } | 122 } |
116 return (p); | 123 return (p); |
117 } | 124 } |
118 | 125 |
119 static | 126 static |
120 int etdfs (int v, int *first_kid, int *next_kid, int *post, int postnum) | 127 octave_idx_type etdfs (octave_idx_type v, octave_idx_type *first_kid, |
121 { | 128 octave_idx_type *next_kid, octave_idx_type *post, |
122 for (int w = first_kid[v]; w != -1; w = next_kid[w]) { | 129 octave_idx_type postnum) |
130 { | |
131 for (octave_idx_type w = first_kid[v]; w != -1; w = next_kid[w]) { | |
123 postnum = etdfs (w, first_kid, next_kid, post, postnum); | 132 postnum = etdfs (w, first_kid, next_kid, post, postnum); |
124 } | 133 } |
125 post[postnum++] = v; | 134 post[postnum++] = v; |
126 | 135 |
127 return postnum; | 136 return postnum; |
128 } | 137 } |
129 | 138 |
130 static | 139 static |
131 void TreePostorder(int n, int *parent, int *post) | 140 void TreePostorder(octave_idx_type n, octave_idx_type *parent, octave_idx_type *post) |
132 { | 141 { |
133 // Allocate storage for working arrays and results | 142 // Allocate storage for working arrays and results |
134 OCTAVE_LOCAL_BUFFER (int, first_kid, n+1); | 143 OCTAVE_LOCAL_BUFFER (octave_idx_type, first_kid, n+1); |
135 OCTAVE_LOCAL_BUFFER (int, next_kid, n+1); | 144 OCTAVE_LOCAL_BUFFER (octave_idx_type, next_kid, n+1); |
136 | 145 |
137 // Set up structure describing children | 146 // Set up structure describing children |
138 for (int v = 0; v <= n; first_kid[v++] = -1); | 147 for (octave_idx_type v = 0; v <= n; first_kid[v++] = -1); |
139 for (int v = n-1; v >= 0; v--) | 148 for (octave_idx_type v = n-1; v >= 0; v--) |
140 { | 149 { |
141 int dad = parent[v]; | 150 octave_idx_type dad = parent[v]; |
142 next_kid[v] = first_kid[dad]; | 151 next_kid[v] = first_kid[dad]; |
143 first_kid[dad] = v; | 152 first_kid[dad] = v; |
144 } | 153 } |
145 | 154 |
146 // Depth-first search from dummy root vertex #n | 155 // Depth-first search from dummy root vertex #n |
147 etdfs (n, first_kid, next_kid, post, 0); | 156 etdfs (n, first_kid, next_kid, post, 0); |
148 } | 157 } |
149 | 158 |
150 static | 159 static |
151 void coletree (const int *ridx, const int *colbeg, int *colend, | 160 void coletree (const octave_idx_type *ridx, const octave_idx_type *colbeg, |
152 int *parent, int nr, int nc) | 161 octave_idx_type *colend, octave_idx_type *parent, |
153 { | 162 octave_idx_type nr, octave_idx_type nc) |
154 OCTAVE_LOCAL_BUFFER (int, root, nc); | 163 { |
155 OCTAVE_LOCAL_BUFFER (int, pp, nc); | 164 OCTAVE_LOCAL_BUFFER (octave_idx_type, root, nc); |
156 OCTAVE_LOCAL_BUFFER (int, firstcol, nr); | 165 OCTAVE_LOCAL_BUFFER (octave_idx_type, pp, nc); |
166 OCTAVE_LOCAL_BUFFER (octave_idx_type, firstcol, nr); | |
157 | 167 |
158 // Compute firstcol[row] = first nonzero column in row | 168 // Compute firstcol[row] = first nonzero column in row |
159 for (int row = 0; row < nr; firstcol[row++] = nc); | 169 for (octave_idx_type row = 0; row < nr; firstcol[row++] = nc); |
160 for (int col = 0; col < nc; col++) | 170 for (octave_idx_type col = 0; col < nc; col++) |
161 for (int p = colbeg[col]; p < colend[col]; p++) | 171 for (octave_idx_type p = colbeg[col]; p < colend[col]; p++) |
162 { | 172 { |
163 int row = ridx[p]; | 173 octave_idx_type row = ridx[p]; |
164 if (firstcol[row] > col) | 174 if (firstcol[row] > col) |
165 firstcol[row] = col; | 175 firstcol[row] = col; |
166 } | 176 } |
167 | 177 |
168 // Compute etree by Liu's algorithm for symmetric matrices, | 178 // Compute etree by Liu's algorithm for symmetric matrices, |
169 // except use (firstcol[r],c) in place of an edge (r,c) of A. | 179 // except use (firstcol[r],c) in place of an edge (r,c) of A. |
170 // Thus each row clique in A'*A is replaced by a star | 180 // Thus each row clique in A'*A is replaced by a star |
171 // centered at its first vertex, which has the same fill. | 181 // centered at its first vertex, which has the same fill. |
172 for (int col = 0; col < nc; col++) | 182 for (octave_idx_type col = 0; col < nc; col++) |
173 { | 183 { |
174 int cset = make_set (col, pp); | 184 octave_idx_type cset = make_set (col, pp); |
175 root[cset] = col; | 185 root[cset] = col; |
176 parent[col] = nc; | 186 parent[col] = nc; |
177 for (int p = colbeg[col]; p < colend[col]; p++) | 187 for (octave_idx_type p = colbeg[col]; p < colend[col]; p++) |
178 { | 188 { |
179 int row = firstcol[ridx[p]]; | 189 octave_idx_type row = firstcol[ridx[p]]; |
180 if (row >= col) | 190 if (row >= col) |
181 continue; | 191 continue; |
182 int rset = find (row, pp); | 192 octave_idx_type rset = find (row, pp); |
183 int rroot = root[rset]; | 193 octave_idx_type rroot = root[rset]; |
184 if (rroot != col) | 194 if (rroot != col) |
185 { | 195 { |
186 parent[rroot] = col; | 196 parent[rroot] = col; |
187 cset = link (cset, rset, pp); | 197 cset = link (cset, rset, pp); |
188 root[cset] = col; | 198 root[cset] = col; |
189 } | 199 } |
190 } | 200 } |
191 } | 201 } |
192 } | 202 } |
193 | |
194 #endif | |
195 | 203 |
196 DEFUN_DLD (colamd, args, nargout, | 204 DEFUN_DLD (colamd, args, nargout, |
197 "-*- texinfo -*-\n\ | 205 "-*- texinfo -*-\n\ |
198 @deftypefn {Loadable Function} {@var{p} =} colamd (@var{s})\n\ | 206 @deftypefn {Loadable Function} {@var{p} =} colamd (@var{s})\n\ |
199 @deftypefnx {Loadable Function} {@var{p} =} colamd (@var{s}, @var{knobs})\n\ | 207 @deftypefnx {Loadable Function} {@var{p} =} colamd (@var{s}, @var{knobs})\n\ |
206 @code{@var{s} (:,@var{p})} tends to have sparser LU factors than @var{s}.\n\ | 214 @code{@var{s} (:,@var{p})} tends to have sparser LU factors than @var{s}.\n\ |
207 The Cholesky factorization of @code{@var{s} (:,@var{p})' * @var{s}\n\ | 215 The Cholesky factorization of @code{@var{s} (:,@var{p})' * @var{s}\n\ |
208 (:,@var{p})} also tends to be sparser than that of @code{@var{s}' *\n\ | 216 (:,@var{p})} also tends to be sparser than that of @code{@var{s}' *\n\ |
209 @var{s}}.\n\ | 217 @var{s}}.\n\ |
210 \n\ | 218 \n\ |
211 @var{knobs} is an optional two-element input vector. If @var{s} is\n\ | 219 @var{knobs} is an optional one- to three-element input vector. If @var{s} is\n\ |
212 m-by-n, then rows with more than @code{(@var{knobs} (1)) * @var{n}}\n\ | 220 m-by-n, then rows with more than @code{max(16,@var{knobs}(1)*sqrt(n))} entries\n\ |
213 entries are ignored. Columns with more than @code{(@var{knobs} (2)) *\n\ | 221 are ignored. Columns with more than @code{max(16,knobs(2)*sqrt(min(m,n)))}\n\ |
214 @var{m}} entries are removed prior to ordering, and ordered last in the\n\ | 222 entries are removed prior to ordering, and ordered last in the output\n\ |
215 output permutation @var{p}. If the knobs parameter is not present, then\n\ | 223 permutation @var{p}. Only completely dense rows or columns are removed\n\ |
216 0.5 is used instead, for both @code{@var{knobs} (1)} and\n\ | 224 if @code{@var{knobs} (1)} and @code{@var{knobs} (2)} are < 0, respectively.\n\ |
217 @code{@var{knobs} (2)}. @code{@var{knobs} (3)} controls the printing of\n\ | 225 If @code{@var{knobs} (3)} is nonzero, @var{stats} and @var{knobs} are\n\ |
218 statistics and error messages.\n\ | 226 printed. The default is @code{@var{knobs} = [10 10 0]}. Note that\n\ |
227 @var{knobs} differs from earlier versions of colamd\n\ | |
219 \n\ | 228 \n\ |
220 @var{stats} is an optional 20-element output vector that provides data\n\ | 229 @var{stats} is an optional 20-element output vector that provides data\n\ |
221 about the ordering and the validity of the input matrix @var{s}. Ordering\n\ | 230 about the ordering and the validity of the input matrix @var{s}. Ordering\n\ |
222 statistics are in @code{@var{stats} (1:3)}. @code{@var{stats} (1)} and\n\ | 231 statistics are in @code{@var{stats} (1:3)}. @code{@var{stats} (1)} and\n\ |
223 @code{@var{stats} (2)} are the number of dense or empty rows and columns\n\ | 232 @code{@var{stats} (2)} are the number of dense or empty rows and columns\n\ |
259 @url{http://www.cise.ufl.edu/research/sparse/colamd})\n\ | 268 @url{http://www.cise.ufl.edu/research/sparse/colamd})\n\ |
260 @end deftypefn\n\ | 269 @end deftypefn\n\ |
261 @seealso{colperm, symamd}") | 270 @seealso{colperm, symamd}") |
262 { | 271 { |
263 octave_value_list retval; | 272 octave_value_list retval; |
264 | |
265 #if SIZEOF_INT == SIZEOF_OCTAVE_IDX_TYPE | |
266 | |
267 int nargin = args.length (); | 273 int nargin = args.length (); |
268 int spumoni = 0; | 274 int spumoni = 0; |
269 | 275 |
270 if (nargout < 0 || nargout > 2 || nargin < 0 || nargin > 2) | 276 if (nargout < 0 || nargout > 2 || nargin < 0 || nargin > 2) |
271 usage ("colamd: incorrect number of input and/or output arguments"); | 277 usage ("colamd: incorrect number of input and/or output arguments"); |
272 else | 278 else |
273 { | 279 { |
274 // Get knobs | 280 // Get knobs |
275 OCTAVE_LOCAL_BUFFER (double, knobs, COLAMD_KNOBS); | 281 OCTAVE_LOCAL_BUFFER (double, knobs, COLAMD_KNOBS); |
276 colamd_set_defaults (knobs); | 282 COLAMD_NAME (_set_defaults) (knobs); |
277 | 283 |
278 // Check for user-passed knobs | 284 // Check for user-passed knobs |
279 if (nargin == 2) | 285 if (nargin == 2) |
280 { | 286 { |
281 NDArray User_knobs = args(1).array_value (); | 287 NDArray User_knobs = args(1).array_value (); |
282 int nel_User_knobs = User_knobs.length (); | 288 int nel_User_knobs = User_knobs.length (); |
283 | 289 |
284 if (nel_User_knobs > 0) | 290 if (nel_User_knobs > 0) |
285 knobs [COLAMD_DENSE_ROW] = User_knobs (COLAMD_DENSE_ROW); | 291 knobs [COLAMD_DENSE_ROW] = User_knobs (0); |
286 if (nel_User_knobs > 1) | 292 if (nel_User_knobs > 1) |
287 knobs [COLAMD_DENSE_COL] = User_knobs (COLAMD_DENSE_COL) ; | 293 knobs [COLAMD_DENSE_COL] = User_knobs (1) ; |
288 if (nel_User_knobs > 2) | 294 if (nel_User_knobs > 2) |
289 spumoni = (int) User_knobs (2); | 295 spumoni = (int) User_knobs (2); |
290 } | 296 |
291 | 297 // print knob settings if spumoni is set |
292 // print knob settings if spumoni is set | 298 if (spumoni) |
293 if (spumoni > 0) | 299 { |
294 { | 300 |
295 octave_stdout << "colamd: dense row fraction: " | 301 octave_stdout << "\ncolamd version " << COLAMD_MAIN_VERSION << "." |
296 << knobs [COLAMD_DENSE_ROW] << std::endl; | 302 << COLAMD_SUB_VERSION << ", " << COLAMD_DATE << ":\n"; |
297 octave_stdout << "colamd: dense col fraction: " | 303 |
298 << knobs [COLAMD_DENSE_COL] << std::endl; | 304 if (knobs [COLAMD_DENSE_ROW] >= 0) |
305 octave_stdout << "knobs(1): " << User_knobs (0) | |
306 << ", rows with > max(16," | |
307 << knobs [COLAMD_DENSE_ROW] << "*sqrt(size(A,2)))" | |
308 << " entries removed\n"; | |
309 else | |
310 octave_stdout << "knobs(1): " << User_knobs (0) | |
311 << ", only completely dense rows removed\n"; | |
312 | |
313 if (knobs [COLAMD_DENSE_COL] >= 0) | |
314 octave_stdout << "knobs(2): " << User_knobs (1) | |
315 << ", cols with > max(16," | |
316 << knobs [COLAMD_DENSE_COL] << "*sqrt(size(A)))" | |
317 << " entries removed\n"; | |
318 else | |
319 octave_stdout << "knobs(2): " << User_knobs (1) | |
320 << ", only completely dense columns removed\n"; | |
321 | |
322 octave_stdout << "knobs(3): " << User_knobs (2) | |
323 << ", statistics and knobs printed\n"; | |
324 | |
325 } | |
299 } | 326 } |
300 | 327 |
301 int n_row, n_col, nnz; | 328 octave_idx_type n_row, n_col, nnz; |
302 int *ridx, *cidx; | 329 octave_idx_type *ridx, *cidx; |
303 SparseComplexMatrix scm; | 330 SparseComplexMatrix scm; |
304 SparseMatrix sm; | 331 SparseMatrix sm; |
305 | 332 |
306 if (args(0).class_name () == "sparse") | 333 if (args(0).class_name () == "sparse") |
307 { | 334 { |
338 ridx = sm.xridx (); | 365 ridx = sm.xridx (); |
339 cidx = sm.xcidx (); | 366 cidx = sm.xcidx (); |
340 } | 367 } |
341 | 368 |
342 // Allocate workspace for colamd | 369 // Allocate workspace for colamd |
343 OCTAVE_LOCAL_BUFFER (int, p, n_col+1); | 370 OCTAVE_LOCAL_BUFFER (octave_idx_type, p, n_col+1); |
344 for (int i = 0; i < n_col+1; i++) | 371 for (octave_idx_type i = 0; i < n_col+1; i++) |
345 p[i] = cidx [i]; | 372 p[i] = cidx [i]; |
346 | 373 |
347 int Alen = colamd_recommended (nnz, n_row, n_col); | 374 octave_idx_type Alen = COLAMD_NAME (_recommended) (nnz, n_row, n_col); |
348 OCTAVE_LOCAL_BUFFER (int, A, Alen); | 375 OCTAVE_LOCAL_BUFFER (octave_idx_type, A, Alen); |
349 for (int i = 0; i < nnz; i++) | 376 for (octave_idx_type i = 0; i < nnz; i++) |
350 A[i] = ridx [i]; | 377 A[i] = ridx [i]; |
351 | 378 |
352 // Order the columns (destroys A) | 379 // Order the columns (destroys A) |
353 OCTAVE_LOCAL_BUFFER (int, stats, COLAMD_STATS); | 380 OCTAVE_LOCAL_BUFFER (octave_idx_type, stats, COLAMD_STATS); |
354 if (!colamd (n_row, n_col, Alen, A, p, knobs, stats)) | 381 if (! COLAMD_NAME () (n_row, n_col, Alen, A, p, knobs, stats)) |
355 { | 382 { |
356 colamd_report (stats) ; | 383 COLAMD_NAME (_report) (stats) ; |
357 error ("colamd: internal error!"); | 384 error ("colamd: internal error!"); |
358 return retval; | 385 return retval; |
359 } | 386 } |
360 | 387 |
361 // column elimination tree post-ordering (reuse variables) | 388 // column elimination tree post-ordering (reuse variables) |
362 OCTAVE_LOCAL_BUFFER (int, colbeg, n_col + 1); | 389 OCTAVE_LOCAL_BUFFER (octave_idx_type, colbeg, n_col + 1); |
363 OCTAVE_LOCAL_BUFFER (int, colend, n_col + 1); | 390 OCTAVE_LOCAL_BUFFER (octave_idx_type, colend, n_col + 1); |
364 OCTAVE_LOCAL_BUFFER (int, etree, n_col + 1); | 391 OCTAVE_LOCAL_BUFFER (octave_idx_type, etree, n_col + 1); |
365 | 392 |
366 for (int i = 0; i < n_col; i++) | 393 for (octave_idx_type i = 0; i < n_col; i++) |
367 { | 394 { |
368 colbeg[i] = cidx[p[i]]; | 395 colbeg[i] = cidx[p[i]]; |
369 colend[i] = cidx[p[i]+1]; | 396 colend[i] = cidx[p[i]+1]; |
370 } | 397 } |
371 | 398 |
374 // Calculate the tree post-ordering | 401 // Calculate the tree post-ordering |
375 TreePostorder (n_col, etree, colbeg); | 402 TreePostorder (n_col, etree, colbeg); |
376 | 403 |
377 // return the permutation vector | 404 // return the permutation vector |
378 NDArray out_perm (dim_vector (1, n_col)); | 405 NDArray out_perm (dim_vector (1, n_col)); |
379 for (int i = 0; i < n_col; i++) | 406 for (octave_idx_type i = 0; i < n_col; i++) |
380 out_perm(i) = p [colbeg [i]] + 1; | 407 out_perm(i) = p [colbeg [i]] + 1; |
381 | 408 |
382 retval (0) = out_perm; | 409 retval (0) = out_perm; |
383 | 410 |
384 // print stats if spumoni > 0 | 411 // print stats if spumoni > 0 |
385 if (spumoni > 0) | 412 if (spumoni > 0) |
386 colamd_report (stats) ; | 413 COLAMD_NAME (_report) (stats) ; |
387 | 414 |
388 // Return the stats vector | 415 // Return the stats vector |
389 if (nargout == 2) | 416 if (nargout == 2) |
390 { | 417 { |
391 NDArray out_stats (dim_vector (1, COLAMD_STATS)); | 418 NDArray out_stats (dim_vector (1, COLAMD_STATS)); |
392 for (int i = 0 ; i < COLAMD_STATS ; i++) | 419 for (octave_idx_type i = 0 ; i < COLAMD_STATS ; i++) |
393 out_stats (i) = stats [i] ; | 420 out_stats (i) = stats [i] ; |
394 retval(1) = out_stats; | 421 retval(1) = out_stats; |
395 | 422 |
396 // fix stats (5) and (6), for 1-based information on | 423 // fix stats (5) and (6), for 1-based information on |
397 // jumbled matrix. note that this correction doesn't | 424 // jumbled matrix. note that this correction doesn't |
398 // occur if symamd returns FALSE | 425 // occur if symamd returns FALSE |
399 out_stats (COLAMD_INFO1) ++ ; | 426 out_stats (COLAMD_INFO1) ++ ; |
400 out_stats (COLAMD_INFO2) ++ ; | 427 out_stats (COLAMD_INFO2) ++ ; |
401 } | 428 } |
402 } | 429 } |
403 | |
404 #else | |
405 | |
406 error ("colamd: not available in this version of Octave"); | |
407 | |
408 #endif | |
409 | 430 |
410 return retval; | 431 return retval; |
411 } | 432 } |
412 | 433 |
413 DEFUN_DLD (symamd, args, nargout, | 434 DEFUN_DLD (symamd, args, nargout, |
422 sparser Cholesky factor than @var{s}. Sometimes SYMAMD works well for\n\ | 443 sparser Cholesky factor than @var{s}. Sometimes SYMAMD works well for\n\ |
423 symmetric indefinite matrices too. The matrix @var{s} is assumed to be\n\ | 444 symmetric indefinite matrices too. The matrix @var{s} is assumed to be\n\ |
424 symmetric; only the strictly lower triangular part is referenced. @var{s}\n\ | 445 symmetric; only the strictly lower triangular part is referenced. @var{s}\n\ |
425 must be square.\n\ | 446 must be square.\n\ |
426 \n\ | 447 \n\ |
427 @var{knobs} is an optional input argument. If @var{s} is n-by-n, then\n\ | 448 @var{knobs} is an optional one- to two-element input vector. If @var{s} is\n\ |
428 rows and columns with more than @code{@var{knobs} (1) * @var{n}} entries\n\ | 449 n-by-n, then rows and columns with more than\n\ |
429 are removed prior to ordering, and ordered last in the output permutation\n\ | 450 @code{max(16,@var{knobs}(1)*sqrt(n))} entries are removed prior to ordering,\n\ |
430 @var{p}. If the @var{knobs} parameter is not present, then the default of\n\ | 451 and ordered last in the output permutation @var{p}. No rows/columns are\n\ |
431 0.5 is used instead. @code{@var{knobs} (2)} controls the printing of\n\ | 452 removed if @code{@var{knobs}(1) < 0}. If @code{@var{knobs} (2)} is nonzero,\n\ |
432 statistics and error messages.\n\ | 453 @code{stats} and @var{knobs} are printed. The default is @code{@var{knobs} \n\ |
454 = [10 0]}. Note that @var{knobs} differs from earlier versions of symamd.\n\ | |
433 \n\ | 455 \n\ |
434 @var{stats} is an optional 20-element output vector that provides data\n\ | 456 @var{stats} is an optional 20-element output vector that provides data\n\ |
435 about the ordering and the validity of the input matrix @var{s}. Ordering\n\ | 457 about the ordering and the validity of the input matrix @var{s}. Ordering\n\ |
436 statistics are in @code{@var{stats} (1:3)}. @code{@var{stats} (1) =\n\ | 458 statistics are in @code{@var{stats} (1:3)}. @code{@var{stats} (1) =\n\ |
437 @var{stats} (2)} is the number of dense or empty rows and columns\n\ | 459 @var{stats} (2)} is the number of dense or empty rows and columns\n\ |
473 @url{http://www.cise.ufl.edu/research/sparse/colamd})\n\ | 495 @url{http://www.cise.ufl.edu/research/sparse/colamd})\n\ |
474 @end deftypefn\n\ | 496 @end deftypefn\n\ |
475 @seealso{colperm, colamd}") | 497 @seealso{colperm, colamd}") |
476 { | 498 { |
477 octave_value_list retval; | 499 octave_value_list retval; |
478 | |
479 #if SIZEOF_INT == SIZEOF_OCTAVE_IDX_TYPE | |
480 | |
481 int nargin = args.length (); | 500 int nargin = args.length (); |
482 int spumoni = 0; | 501 int spumoni = 0; |
483 | 502 |
484 if (nargout < 0 || nargout > 2 || nargin < 0 || nargin > 2) | 503 if (nargout < 0 || nargout > 2 || nargin < 0 || nargin > 2) |
485 usage ("symamd: incorrect number of input and/or output arguments"); | 504 usage ("symamd: incorrect number of input and/or output arguments"); |
486 else | 505 else |
487 { | 506 { |
488 // Get knobs | 507 // Get knobs |
489 OCTAVE_LOCAL_BUFFER (double, knobs, COLAMD_KNOBS); | 508 OCTAVE_LOCAL_BUFFER (double, knobs, COLAMD_KNOBS); |
490 colamd_set_defaults (knobs); | 509 COLAMD_NAME (_set_defaults) (knobs); |
491 | 510 |
492 // Check for user-passed knobs | 511 // Check for user-passed knobs |
493 if (nargin == 2) | 512 if (nargin == 2) |
494 { | 513 { |
495 NDArray User_knobs = args(1).array_value (); | 514 NDArray User_knobs = args(1).array_value (); |
504 // print knob settings if spumoni is set | 523 // print knob settings if spumoni is set |
505 if (spumoni > 0) | 524 if (spumoni > 0) |
506 octave_stdout << "symamd: dense row/col fraction: " | 525 octave_stdout << "symamd: dense row/col fraction: " |
507 << knobs [COLAMD_DENSE_ROW] << std::endl; | 526 << knobs [COLAMD_DENSE_ROW] << std::endl; |
508 | 527 |
509 int n_row, n_col, nnz; | 528 octave_idx_type n_row, n_col, nnz; |
510 int *ridx, *cidx; | 529 octave_idx_type *ridx, *cidx; |
511 SparseMatrix sm; | 530 SparseMatrix sm; |
512 SparseComplexMatrix scm; | 531 SparseComplexMatrix scm; |
513 | 532 |
514 if (args(0).class_name () == "sparse") | 533 if (args(0).class_name () == "sparse") |
515 { | 534 { |
551 error ("symamd: matrix must be square"); | 570 error ("symamd: matrix must be square"); |
552 return retval; | 571 return retval; |
553 } | 572 } |
554 | 573 |
555 // Allocate workspace for symamd | 574 // Allocate workspace for symamd |
556 OCTAVE_LOCAL_BUFFER (int, perm, n_col+1); | 575 OCTAVE_LOCAL_BUFFER (octave_idx_type, perm, n_col+1); |
557 OCTAVE_LOCAL_BUFFER (int, stats, COLAMD_STATS); | 576 OCTAVE_LOCAL_BUFFER (octave_idx_type, stats, COLAMD_STATS); |
558 if (!symamd (n_col, ridx, cidx, perm, knobs, stats, &calloc, &free)) | 577 if (!SYMAMD_NAME () (n_col, ridx, cidx, perm, knobs, stats, &calloc, &free)) |
559 { | 578 { |
560 symamd_report (stats) ; | 579 SYMAMD_NAME (_report) (stats) ; |
561 error ("symamd: internal error!") ; | 580 error ("symamd: internal error!") ; |
562 return retval; | 581 return retval; |
563 } | 582 } |
564 | 583 |
565 // column elimination tree post-ordering | 584 // column elimination tree post-ordering |
566 OCTAVE_LOCAL_BUFFER (int, etree, n_col + 1); | 585 OCTAVE_LOCAL_BUFFER (octave_idx_type, etree, n_col + 1); |
567 symetree (ridx, cidx, etree, perm, n_col); | 586 symetree (ridx, cidx, etree, perm, n_col); |
568 | 587 |
569 // Calculate the tree post-ordering | 588 // Calculate the tree post-ordering |
570 OCTAVE_LOCAL_BUFFER (int, post, n_col + 1); | 589 OCTAVE_LOCAL_BUFFER (octave_idx_type, post, n_col + 1); |
571 TreePostorder (n_col, etree, post); | 590 TreePostorder (n_col, etree, post); |
572 | 591 |
573 // return the permutation vector | 592 // return the permutation vector |
574 NDArray out_perm (dim_vector (1, n_col)); | 593 NDArray out_perm (dim_vector (1, n_col)); |
575 for (int i = 0; i < n_col; i++) | 594 for (octave_idx_type i = 0; i < n_col; i++) |
576 out_perm(i) = perm [post [i]] + 1; | 595 out_perm(i) = perm [post [i]] + 1; |
577 | 596 |
578 retval (0) = out_perm; | 597 retval (0) = out_perm; |
579 | 598 |
580 // print stats if spumoni > 0 | 599 // print stats if spumoni > 0 |
581 if (spumoni > 0) | 600 if (spumoni > 0) |
582 symamd_report (stats) ; | 601 SYMAMD_NAME (_report) (stats) ; |
583 | 602 |
584 // Return the stats vector | 603 // Return the stats vector |
585 if (nargout == 2) | 604 if (nargout == 2) |
586 { | 605 { |
587 NDArray out_stats (dim_vector (1, COLAMD_STATS)); | 606 NDArray out_stats (dim_vector (1, COLAMD_STATS)); |
588 for (int i = 0 ; i < COLAMD_STATS ; i++) | 607 for (octave_idx_type i = 0 ; i < COLAMD_STATS ; i++) |
589 out_stats (i) = stats [i] ; | 608 out_stats (i) = stats [i] ; |
590 retval(1) = out_stats; | 609 retval(1) = out_stats; |
591 | 610 |
592 // fix stats (5) and (6), for 1-based information on | 611 // fix stats (5) and (6), for 1-based information on |
593 // jumbled matrix. note that this correction doesn't | 612 // jumbled matrix. note that this correction doesn't |
595 out_stats (COLAMD_INFO1) ++ ; | 614 out_stats (COLAMD_INFO1) ++ ; |
596 out_stats (COLAMD_INFO2) ++ ; | 615 out_stats (COLAMD_INFO2) ++ ; |
597 } | 616 } |
598 } | 617 } |
599 | 618 |
600 #else | |
601 | |
602 error ("symamd: not available in this version of Octave"); | |
603 | |
604 #endif | |
605 | |
606 return retval; | 619 return retval; |
607 } | 620 } |
608 | 621 |
609 DEFUN_DLD (etree, args, nargout, | 622 DEFUN_DLD (etree, args, nargout, |
610 "-*- texinfo -*-\n\ | 623 "-*- texinfo -*-\n\ |
622 permutations on the tree.\n\ | 635 permutations on the tree.\n\ |
623 @end deftypefn") | 636 @end deftypefn") |
624 { | 637 { |
625 octave_value_list retval; | 638 octave_value_list retval; |
626 | 639 |
627 #if SIZEOF_INT == SIZEOF_OCTAVE_IDX_TYPE | |
628 | |
629 int nargin = args.length (); | 640 int nargin = args.length (); |
630 | 641 |
631 if (nargout < 0 || nargout > 2 || nargin < 0 || nargin > 2) | 642 if (nargout < 0 || nargout > 2 || nargin < 0 || nargin > 2) |
632 usage ("etree: incorrect number of input and/or output arguments"); | 643 usage ("etree: incorrect number of input and/or output arguments"); |
633 else | 644 else |
634 { | 645 { |
635 int n_row, n_col, nnz; | 646 octave_idx_type n_row, n_col, nnz; |
636 int *ridx, *cidx; | 647 octave_idx_type *ridx, *cidx; |
637 bool is_sym = true; | 648 bool is_sym = true; |
638 SparseMatrix sm; | 649 SparseMatrix sm; |
639 SparseComplexMatrix scm; | 650 SparseComplexMatrix scm; |
640 | 651 |
641 if (args(0).class_name () == "sparse") | 652 if (args(0).class_name () == "sparse") |
678 error ("etree: second argument must be a string"); | 689 error ("etree: second argument must be a string"); |
679 return retval; | 690 return retval; |
680 } | 691 } |
681 | 692 |
682 // column elimination tree post-ordering (reuse variables) | 693 // column elimination tree post-ordering (reuse variables) |
683 OCTAVE_LOCAL_BUFFER (int, etree, n_col + 1); | 694 OCTAVE_LOCAL_BUFFER (octave_idx_type, etree, n_col + 1); |
684 | 695 |
685 | 696 |
686 if (is_sym) | 697 if (is_sym) |
687 { | 698 { |
688 if (n_row != n_col) | 699 if (n_row != n_col) |
692 } | 703 } |
693 symetree (ridx, cidx, etree, NULL, n_col); | 704 symetree (ridx, cidx, etree, NULL, n_col); |
694 } | 705 } |
695 else | 706 else |
696 { | 707 { |
697 OCTAVE_LOCAL_BUFFER (int, colbeg, n_col); | 708 OCTAVE_LOCAL_BUFFER (octave_idx_type, colbeg, n_col); |
698 OCTAVE_LOCAL_BUFFER (int, colend, n_col); | 709 OCTAVE_LOCAL_BUFFER (octave_idx_type, colend, n_col); |
699 | 710 |
700 for (int i = 0; i < n_col; i++) | 711 for (octave_idx_type i = 0; i < n_col; i++) |
701 { | 712 { |
702 colbeg[i] = cidx[i]; | 713 colbeg[i] = cidx[i]; |
703 colend[i] = cidx[i+1]; | 714 colend[i] = cidx[i+1]; |
704 } | 715 } |
705 | 716 |
706 coletree (ridx, colbeg, colend, etree, n_row, n_col); | 717 coletree (ridx, colbeg, colend, etree, n_row, n_col); |
707 } | 718 } |
708 | 719 |
709 NDArray tree (dim_vector (1, n_col)); | 720 NDArray tree (dim_vector (1, n_col)); |
710 for (int i = 0; i < n_col; i++) | 721 for (octave_idx_type i = 0; i < n_col; i++) |
711 // We flag a root with n_col while Matlab does it with zero | 722 // We flag a root with n_col while Matlab does it with zero |
712 // Convert for matlab compatiable output | 723 // Convert for matlab compatiable output |
713 if (etree[i] == n_col) | 724 if (etree[i] == n_col) |
714 tree (i) = 0; | 725 tree (i) = 0; |
715 else | 726 else |
718 retval (0) = tree; | 729 retval (0) = tree; |
719 | 730 |
720 if (nargout == 2) | 731 if (nargout == 2) |
721 { | 732 { |
722 // Calculate the tree post-ordering | 733 // Calculate the tree post-ordering |
723 OCTAVE_LOCAL_BUFFER (int, post, n_col + 1); | 734 OCTAVE_LOCAL_BUFFER (octave_idx_type, post, n_col + 1); |
724 TreePostorder (n_col, etree, post); | 735 TreePostorder (n_col, etree, post); |
725 | 736 |
726 NDArray postorder (dim_vector (1, n_col)); | 737 NDArray postorder (dim_vector (1, n_col)); |
727 for (int i = 0; i < n_col; i++) | 738 for (octave_idx_type i = 0; i < n_col; i++) |
728 postorder (i) = post[i] + 1; | 739 postorder (i) = post[i] + 1; |
729 | 740 |
730 retval (1) = postorder; | 741 retval (1) = postorder; |
731 } | 742 } |
732 } | 743 } |
733 | |
734 #else | |
735 | |
736 error ("etree: not available in this version of Octave"); | |
737 | |
738 #endif | |
739 | 744 |
740 return retval; | 745 return retval; |
741 } | 746 } |
742 | 747 |
743 DEFUN_DLD (symbfact, args, nargout, | 748 DEFUN_DLD (symbfact, args, nargout, |