comparison src/DLD-FUNCTIONS/colamd.cc @ 10154:40dfc0c99116

DLD-FUNCTIONS/*.cc: untabify
author John W. Eaton <jwe@octave.org>
date Wed, 20 Jan 2010 17:33:41 -0500
parents 7c02ec148a3c
children d0ce5e973937
comparison
equal deleted inserted replaced
10153:2c28f9d0360f 10154:40dfc0c99116
54 54
55 // The symmetric column elimination tree code take from the Davis LDL code. 55 // The symmetric column elimination tree code take from the Davis LDL code.
56 // Copyright given elsewhere in this file. 56 // Copyright given elsewhere in this file.
57 static void 57 static void
58 symetree (const octave_idx_type *ridx, const octave_idx_type *cidx, 58 symetree (const octave_idx_type *ridx, const octave_idx_type *cidx,
59 octave_idx_type *Parent, octave_idx_type *P, octave_idx_type n) 59 octave_idx_type *Parent, octave_idx_type *P, octave_idx_type n)
60 { 60 {
61 OCTAVE_LOCAL_BUFFER (octave_idx_type, Flag, n); 61 OCTAVE_LOCAL_BUFFER (octave_idx_type, Flag, n);
62 OCTAVE_LOCAL_BUFFER (octave_idx_type, Pinv, (P ? n : 0)); 62 OCTAVE_LOCAL_BUFFER (octave_idx_type, Pinv, (P ? n : 0));
63 if (P) 63 if (P)
64 // If P is present then compute Pinv, the inverse of P 64 // If P is present then compute Pinv, the inverse of P
66 Pinv [P [k]] = k ; 66 Pinv [P [k]] = k ;
67 67
68 for (octave_idx_type k = 0 ; k < n ; k++) 68 for (octave_idx_type k = 0 ; k < n ; k++)
69 { 69 {
70 // L(k,:) pattern: all nodes reachable in etree from nz in A(0:k-1,k) 70 // L(k,:) pattern: all nodes reachable in etree from nz in A(0:k-1,k)
71 Parent [k] = n ; // parent of k is not yet known 71 Parent [k] = n ; // parent of k is not yet known
72 Flag [k] = k ; // mark node k as visited 72 Flag [k] = k ; // mark node k as visited
73 octave_idx_type kk = (P) ? (P [k]) : (k) ; // kth original, or permuted, column 73 octave_idx_type kk = (P) ? (P [k]) : (k) ; // kth original, or permuted, column
74 octave_idx_type p2 = cidx [kk+1] ; 74 octave_idx_type p2 = cidx [kk+1] ;
75 for (octave_idx_type p = cidx [kk] ; p < p2 ; p++) 75 for (octave_idx_type p = cidx [kk] ; p < p2 ; p++)
76 { 76 {
77 // A (i,k) is nonzero (original or permuted A) 77 // A (i,k) is nonzero (original or permuted A)
78 octave_idx_type i = (Pinv) ? (Pinv [ridx [p]]) : (ridx [p]) ; 78 octave_idx_type i = (Pinv) ? (Pinv [ridx [p]]) : (ridx [p]) ;
79 if (i < k) 79 if (i < k)
80 { 80 {
81 // follow path from i to root of etree, stop at flagged node 81 // follow path from i to root of etree, stop at flagged node
82 for ( ; Flag [i] != k ; i = Parent [i]) 82 for ( ; Flag [i] != k ; i = Parent [i])
83 { 83 {
84 // find parent of i if not yet determined 84 // find parent of i if not yet determined
85 if (Parent [i] == n) 85 if (Parent [i] == n)
86 Parent [i] = k ; 86 Parent [i] = k ;
87 Flag [i] = k ; // mark i as visited 87 Flag [i] = k ; // mark i as visited
88 } 88 }
89 } 89 }
90 } 90 }
91 } 91 }
92 } 92 }
93 93
94 // The elimination tree post-ordering code below is taken from SuperLU 94 // The elimination tree post-ordering code below is taken from SuperLU
95 static inline octave_idx_type 95 static inline octave_idx_type
138 return postnum; 138 return postnum;
139 } 139 }
140 140
141 static void 141 static void
142 tree_postorder (octave_idx_type n, octave_idx_type *parent, 142 tree_postorder (octave_idx_type n, octave_idx_type *parent,
143 octave_idx_type *post) 143 octave_idx_type *post)
144 { 144 {
145 // Allocate storage for working arrays and results 145 // Allocate storage for working arrays and results
146 OCTAVE_LOCAL_BUFFER (octave_idx_type, first_kid, n+1); 146 OCTAVE_LOCAL_BUFFER (octave_idx_type, first_kid, n+1);
147 OCTAVE_LOCAL_BUFFER (octave_idx_type, next_kid, n+1); 147 OCTAVE_LOCAL_BUFFER (octave_idx_type, next_kid, n+1);
148 148
161 etdfs (n, first_kid, next_kid, post, 0); 161 etdfs (n, first_kid, next_kid, post, 0);
162 } 162 }
163 163
164 static void 164 static void
165 coletree (const octave_idx_type *ridx, const octave_idx_type *colbeg, 165 coletree (const octave_idx_type *ridx, const octave_idx_type *colbeg,
166 octave_idx_type *colend, octave_idx_type *parent, 166 octave_idx_type *colend, octave_idx_type *parent,
167 octave_idx_type nr, octave_idx_type nc) 167 octave_idx_type nr, octave_idx_type nc)
168 { 168 {
169 OCTAVE_LOCAL_BUFFER (octave_idx_type, root, nc); 169 OCTAVE_LOCAL_BUFFER (octave_idx_type, root, nc);
170 OCTAVE_LOCAL_BUFFER (octave_idx_type, pp, nc); 170 OCTAVE_LOCAL_BUFFER (octave_idx_type, pp, nc);
171 OCTAVE_LOCAL_BUFFER (octave_idx_type, firstcol, nr); 171 OCTAVE_LOCAL_BUFFER (octave_idx_type, firstcol, nr);
172 172
175 /* do nothing */; 175 /* do nothing */;
176 176
177 for (octave_idx_type col = 0; col < nc; col++) 177 for (octave_idx_type col = 0; col < nc; col++)
178 for (octave_idx_type p = colbeg[col]; p < colend[col]; p++) 178 for (octave_idx_type p = colbeg[col]; p < colend[col]; p++)
179 { 179 {
180 octave_idx_type row = ridx[p]; 180 octave_idx_type row = ridx[p];
181 if (firstcol[row] > col) 181 if (firstcol[row] > col)
182 firstcol[row] = col; 182 firstcol[row] = col;
183 } 183 }
184 184
185 // Compute etree by Liu's algorithm for symmetric matrices, 185 // Compute etree by Liu's algorithm for symmetric matrices,
186 // except use (firstcol[r],c) in place of an edge (r,c) of A. 186 // except use (firstcol[r],c) in place of an edge (r,c) of A.
187 // Thus each row clique in A'*A is replaced by a star 187 // Thus each row clique in A'*A is replaced by a star
190 { 190 {
191 octave_idx_type cset = make_set (col, pp); 191 octave_idx_type cset = make_set (col, pp);
192 root[cset] = col; 192 root[cset] = col;
193 parent[col] = nc; 193 parent[col] = nc;
194 for (octave_idx_type p = colbeg[col]; p < colend[col]; p++) 194 for (octave_idx_type p = colbeg[col]; p < colend[col]; p++)
195 { 195 {
196 octave_idx_type row = firstcol[ridx[p]]; 196 octave_idx_type row = firstcol[ridx[p]];
197 if (row >= col) 197 if (row >= col)
198 continue; 198 continue;
199 octave_idx_type rset = find (row, pp); 199 octave_idx_type rset = find (row, pp);
200 octave_idx_type rroot = root[rset]; 200 octave_idx_type rroot = root[rset];
201 if (rroot != col) 201 if (rroot != col)
202 { 202 {
203 parent[rroot] = col; 203 parent[rroot] = col;
204 cset = link (cset, rset, pp); 204 cset = link (cset, rset, pp);
205 root[cset] = col; 205 root[cset] = col;
206 } 206 }
207 } 207 }
208 } 208 }
209 } 209 }
210 210
211 DEFUN_DLD (colamd, args, nargout, 211 DEFUN_DLD (colamd, args, nargout,
212 "-*- texinfo -*-\n\ 212 "-*- texinfo -*-\n\
291 OCTAVE_LOCAL_BUFFER (double, knobs, COLAMD_KNOBS); 291 OCTAVE_LOCAL_BUFFER (double, knobs, COLAMD_KNOBS);
292 COLAMD_NAME (_set_defaults) (knobs); 292 COLAMD_NAME (_set_defaults) (knobs);
293 293
294 // Check for user-passed knobs 294 // Check for user-passed knobs
295 if (nargin == 2) 295 if (nargin == 2)
296 { 296 {
297 NDArray User_knobs = args(1).array_value (); 297 NDArray User_knobs = args(1).array_value ();
298 int nel_User_knobs = User_knobs.length (); 298 int nel_User_knobs = User_knobs.length ();
299 299
300 if (nel_User_knobs > 0) 300 if (nel_User_knobs > 0)
301 knobs [COLAMD_DENSE_ROW] = User_knobs (0); 301 knobs [COLAMD_DENSE_ROW] = User_knobs (0);
302 if (nel_User_knobs > 1) 302 if (nel_User_knobs > 1)
303 knobs [COLAMD_DENSE_COL] = User_knobs (1) ; 303 knobs [COLAMD_DENSE_COL] = User_knobs (1) ;
304 if (nel_User_knobs > 2) 304 if (nel_User_knobs > 2)
305 spumoni = static_cast<int> (User_knobs (2)); 305 spumoni = static_cast<int> (User_knobs (2));
306 306
307 // print knob settings if spumoni is set 307 // print knob settings if spumoni is set
308 if (spumoni) 308 if (spumoni)
309 { 309 {
310 310
311 octave_stdout << "\ncolamd version " << COLAMD_MAIN_VERSION << "." 311 octave_stdout << "\ncolamd version " << COLAMD_MAIN_VERSION << "."
312 << COLAMD_SUB_VERSION << ", " << COLAMD_DATE << ":\n"; 312 << COLAMD_SUB_VERSION << ", " << COLAMD_DATE << ":\n";
313 313
314 if (knobs [COLAMD_DENSE_ROW] >= 0) 314 if (knobs [COLAMD_DENSE_ROW] >= 0)
315 octave_stdout << "knobs(1): " << User_knobs (0) 315 octave_stdout << "knobs(1): " << User_knobs (0)
316 << ", rows with > max(16," 316 << ", rows with > max(16,"
317 << knobs [COLAMD_DENSE_ROW] << "*sqrt(size(A,2)))" 317 << knobs [COLAMD_DENSE_ROW] << "*sqrt(size(A,2)))"
318 << " entries removed\n"; 318 << " entries removed\n";
319 else 319 else
320 octave_stdout << "knobs(1): " << User_knobs (0) 320 octave_stdout << "knobs(1): " << User_knobs (0)
321 << ", only completely dense rows removed\n"; 321 << ", only completely dense rows removed\n";
322 322
323 if (knobs [COLAMD_DENSE_COL] >= 0) 323 if (knobs [COLAMD_DENSE_COL] >= 0)
324 octave_stdout << "knobs(2): " << User_knobs (1) 324 octave_stdout << "knobs(2): " << User_knobs (1)
325 << ", cols with > max(16," 325 << ", cols with > max(16,"
326 << knobs [COLAMD_DENSE_COL] << "*sqrt(size(A)))" 326 << knobs [COLAMD_DENSE_COL] << "*sqrt(size(A)))"
327 << " entries removed\n"; 327 << " entries removed\n";
328 else 328 else
329 octave_stdout << "knobs(2): " << User_knobs (1) 329 octave_stdout << "knobs(2): " << User_knobs (1)
330 << ", only completely dense columns removed\n"; 330 << ", only completely dense columns removed\n";
331 331
332 octave_stdout << "knobs(3): " << User_knobs (2) 332 octave_stdout << "knobs(3): " << User_knobs (2)
333 << ", statistics and knobs printed\n"; 333 << ", statistics and knobs printed\n";
334 334
335 } 335 }
336 } 336 }
337 337
338 octave_idx_type n_row, n_col, nnz; 338 octave_idx_type n_row, n_col, nnz;
339 octave_idx_type *ridx, *cidx; 339 octave_idx_type *ridx, *cidx;
340 SparseComplexMatrix scm; 340 SparseComplexMatrix scm;
341 SparseMatrix sm; 341 SparseMatrix sm;
342 342
343 if (args(0).is_sparse_type ()) 343 if (args(0).is_sparse_type ())
344 { 344 {
345 if (args(0).is_complex_type ()) 345 if (args(0).is_complex_type ())
346 { 346 {
347 scm = args(0). sparse_complex_matrix_value (); 347 scm = args(0). sparse_complex_matrix_value ();
348 n_row = scm.rows (); 348 n_row = scm.rows ();
349 n_col = scm.cols (); 349 n_col = scm.cols ();
350 nnz = scm.nzmax (); 350 nnz = scm.nzmax ();
351 ridx = scm.xridx (); 351 ridx = scm.xridx ();
352 cidx = scm.xcidx (); 352 cidx = scm.xcidx ();
353 } 353 }
354 else 354 else
355 { 355 {
356 sm = args(0).sparse_matrix_value (); 356 sm = args(0).sparse_matrix_value ();
357 357
358 n_row = sm.rows (); 358 n_row = sm.rows ();
359 n_col = sm.cols (); 359 n_col = sm.cols ();
360 nnz = sm.nzmax (); 360 nnz = sm.nzmax ();
361 ridx = sm.xridx (); 361 ridx = sm.xridx ();
362 cidx = sm.xcidx (); 362 cidx = sm.xcidx ();
363 } 363 }
364 } 364 }
365 else 365 else
366 { 366 {
367 if (args(0).is_complex_type ()) 367 if (args(0).is_complex_type ())
368 sm = SparseMatrix (real (args(0).complex_matrix_value ())); 368 sm = SparseMatrix (real (args(0).complex_matrix_value ()));
369 else 369 else
370 sm = SparseMatrix (args(0).matrix_value ()); 370 sm = SparseMatrix (args(0).matrix_value ());
371 371
372 n_row = sm.rows (); 372 n_row = sm.rows ();
373 n_col = sm.cols (); 373 n_col = sm.cols ();
374 nnz = sm.nzmax (); 374 nnz = sm.nzmax ();
375 ridx = sm.xridx (); 375 ridx = sm.xridx ();
376 cidx = sm.xcidx (); 376 cidx = sm.xcidx ();
377 } 377 }
378 378
379 // Allocate workspace for colamd 379 // Allocate workspace for colamd
380 OCTAVE_LOCAL_BUFFER (octave_idx_type, p, n_col+1); 380 OCTAVE_LOCAL_BUFFER (octave_idx_type, p, n_col+1);
381 for (octave_idx_type i = 0; i < n_col+1; i++) 381 for (octave_idx_type i = 0; i < n_col+1; i++)
382 p[i] = cidx [i]; 382 p[i] = cidx [i];
383 383
384 octave_idx_type Alen = COLAMD_NAME (_recommended) (nnz, n_row, n_col); 384 octave_idx_type Alen = COLAMD_NAME (_recommended) (nnz, n_row, n_col);
385 OCTAVE_LOCAL_BUFFER (octave_idx_type, A, Alen); 385 OCTAVE_LOCAL_BUFFER (octave_idx_type, A, Alen);
386 for (octave_idx_type i = 0; i < nnz; i++) 386 for (octave_idx_type i = 0; i < nnz; i++)
387 A[i] = ridx [i]; 387 A[i] = ridx [i];
388 388
389 // Order the columns (destroys A) 389 // Order the columns (destroys A)
390 OCTAVE_LOCAL_BUFFER (octave_idx_type, stats, COLAMD_STATS); 390 OCTAVE_LOCAL_BUFFER (octave_idx_type, stats, COLAMD_STATS);
391 if (! COLAMD_NAME () (n_row, n_col, Alen, A, p, knobs, stats)) 391 if (! COLAMD_NAME () (n_row, n_col, Alen, A, p, knobs, stats))
392 { 392 {
393 COLAMD_NAME (_report) (stats) ; 393 COLAMD_NAME (_report) (stats) ;
394 error ("colamd: internal error!"); 394 error ("colamd: internal error!");
395 return retval; 395 return retval;
396 } 396 }
397 397
398 // column elimination tree post-ordering (reuse variables) 398 // column elimination tree post-ordering (reuse variables)
399 OCTAVE_LOCAL_BUFFER (octave_idx_type, colbeg, n_col + 1); 399 OCTAVE_LOCAL_BUFFER (octave_idx_type, colbeg, n_col + 1);
400 OCTAVE_LOCAL_BUFFER (octave_idx_type, colend, n_col + 1); 400 OCTAVE_LOCAL_BUFFER (octave_idx_type, colend, n_col + 1);
401 OCTAVE_LOCAL_BUFFER (octave_idx_type, etree, n_col + 1); 401 OCTAVE_LOCAL_BUFFER (octave_idx_type, etree, n_col + 1);
402 402
403 for (octave_idx_type i = 0; i < n_col; i++) 403 for (octave_idx_type i = 0; i < n_col; i++)
404 { 404 {
405 colbeg[i] = cidx[p[i]]; 405 colbeg[i] = cidx[p[i]];
406 colend[i] = cidx[p[i]+1]; 406 colend[i] = cidx[p[i]+1];
407 } 407 }
408 408
409 coletree (ridx, colbeg, colend, etree, n_row, n_col); 409 coletree (ridx, colbeg, colend, etree, n_row, n_col);
410 410
411 // Calculate the tree post-ordering 411 // Calculate the tree post-ordering
412 tree_postorder (n_col, etree, colbeg); 412 tree_postorder (n_col, etree, colbeg);
413 413
414 // return the permutation vector 414 // return the permutation vector
415 NDArray out_perm (dim_vector (1, n_col)); 415 NDArray out_perm (dim_vector (1, n_col));
416 for (octave_idx_type i = 0; i < n_col; i++) 416 for (octave_idx_type i = 0; i < n_col; i++)
417 out_perm(i) = p [colbeg [i]] + 1; 417 out_perm(i) = p [colbeg [i]] + 1;
418 418
419 retval(0) = out_perm; 419 retval(0) = out_perm;
420 420
421 // print stats if spumoni > 0 421 // print stats if spumoni > 0
422 if (spumoni > 0) 422 if (spumoni > 0)
423 COLAMD_NAME (_report) (stats) ; 423 COLAMD_NAME (_report) (stats) ;
424 424
425 // Return the stats vector 425 // Return the stats vector
426 if (nargout == 2) 426 if (nargout == 2)
427 { 427 {
428 NDArray out_stats (dim_vector (1, COLAMD_STATS)); 428 NDArray out_stats (dim_vector (1, COLAMD_STATS));
429 for (octave_idx_type i = 0 ; i < COLAMD_STATS ; i++) 429 for (octave_idx_type i = 0 ; i < COLAMD_STATS ; i++)
430 out_stats (i) = stats [i] ; 430 out_stats (i) = stats [i] ;
431 retval(1) = out_stats; 431 retval(1) = out_stats;
432 432
433 // fix stats (5) and (6), for 1-based information on 433 // fix stats (5) and (6), for 1-based information on
434 // jumbled matrix. note that this correction doesn't 434 // jumbled matrix. note that this correction doesn't
435 // occur if symamd returns FALSE 435 // occur if symamd returns FALSE
436 out_stats (COLAMD_INFO1) ++ ; 436 out_stats (COLAMD_INFO1) ++ ;
437 out_stats (COLAMD_INFO2) ++ ; 437 out_stats (COLAMD_INFO2) ++ ;
438 } 438 }
439 } 439 }
440 440
441 #else 441 #else
442 442
443 error ("colamd: not available in this version of Octave"); 443 error ("colamd: not available in this version of Octave");
527 OCTAVE_LOCAL_BUFFER (double, knobs, COLAMD_KNOBS); 527 OCTAVE_LOCAL_BUFFER (double, knobs, COLAMD_KNOBS);
528 COLAMD_NAME (_set_defaults) (knobs); 528 COLAMD_NAME (_set_defaults) (knobs);
529 529
530 // Check for user-passed knobs 530 // Check for user-passed knobs
531 if (nargin == 2) 531 if (nargin == 2)
532 { 532 {
533 NDArray User_knobs = args(1).array_value (); 533 NDArray User_knobs = args(1).array_value ();
534 int nel_User_knobs = User_knobs.length (); 534 int nel_User_knobs = User_knobs.length ();
535 535
536 if (nel_User_knobs > 0) 536 if (nel_User_knobs > 0)
537 knobs [COLAMD_DENSE_ROW] = User_knobs (COLAMD_DENSE_ROW); 537 knobs [COLAMD_DENSE_ROW] = User_knobs (COLAMD_DENSE_ROW);
538 if (nel_User_knobs > 1) 538 if (nel_User_knobs > 1)
539 spumoni = static_cast<int> (User_knobs (1)); 539 spumoni = static_cast<int> (User_knobs (1));
540 } 540 }
541 541
542 // print knob settings if spumoni is set 542 // print knob settings if spumoni is set
543 if (spumoni > 0) 543 if (spumoni > 0)
544 octave_stdout << "symamd: dense row/col fraction: " 544 octave_stdout << "symamd: dense row/col fraction: "
545 << knobs [COLAMD_DENSE_ROW] << std::endl; 545 << knobs [COLAMD_DENSE_ROW] << std::endl;
546 546
547 octave_idx_type n_row, n_col, nnz; 547 octave_idx_type n_row, n_col, nnz;
548 octave_idx_type *ridx, *cidx; 548 octave_idx_type *ridx, *cidx;
549 SparseMatrix sm; 549 SparseMatrix sm;
550 SparseComplexMatrix scm; 550 SparseComplexMatrix scm;
551 551
552 if (args(0).is_sparse_type ()) 552 if (args(0).is_sparse_type ())
553 { 553 {
554 if (args(0).is_complex_type ()) 554 if (args(0).is_complex_type ())
555 { 555 {
556 scm = args(0).sparse_complex_matrix_value (); 556 scm = args(0).sparse_complex_matrix_value ();
557 n_row = scm.rows (); 557 n_row = scm.rows ();
558 n_col = scm.cols (); 558 n_col = scm.cols ();
559 nnz = scm.nzmax (); 559 nnz = scm.nzmax ();
560 ridx = scm.xridx (); 560 ridx = scm.xridx ();
561 cidx = scm.xcidx (); 561 cidx = scm.xcidx ();
562 } 562 }
563 else 563 else
564 { 564 {
565 sm = args(0).sparse_matrix_value (); 565 sm = args(0).sparse_matrix_value ();
566 n_row = sm.rows (); 566 n_row = sm.rows ();
567 n_col = sm.cols (); 567 n_col = sm.cols ();
568 nnz = sm.nzmax (); 568 nnz = sm.nzmax ();
569 ridx = sm.xridx (); 569 ridx = sm.xridx ();
570 cidx = sm.xcidx (); 570 cidx = sm.xcidx ();
571 } 571 }
572 } 572 }
573 else 573 else
574 { 574 {
575 if (args(0).is_complex_type ()) 575 if (args(0).is_complex_type ())
576 sm = SparseMatrix (real (args(0).complex_matrix_value ())); 576 sm = SparseMatrix (real (args(0).complex_matrix_value ()));
577 else 577 else
578 sm = SparseMatrix (args(0).matrix_value ()); 578 sm = SparseMatrix (args(0).matrix_value ());
579 579
580 n_row = sm.rows (); 580 n_row = sm.rows ();
581 n_col = sm.cols (); 581 n_col = sm.cols ();
582 nnz = sm.nzmax (); 582 nnz = sm.nzmax ();
583 ridx = sm.xridx (); 583 ridx = sm.xridx ();
584 cidx = sm.xcidx (); 584 cidx = sm.xcidx ();
585 } 585 }
586 586
587 if (n_row != n_col) 587 if (n_row != n_col)
588 { 588 {
589 error ("symamd: matrix must be square"); 589 error ("symamd: matrix must be square");
590 return retval; 590 return retval;
591 } 591 }
592 592
593 // Allocate workspace for symamd 593 // Allocate workspace for symamd
594 OCTAVE_LOCAL_BUFFER (octave_idx_type, perm, n_col+1); 594 OCTAVE_LOCAL_BUFFER (octave_idx_type, perm, n_col+1);
595 OCTAVE_LOCAL_BUFFER (octave_idx_type, stats, COLAMD_STATS); 595 OCTAVE_LOCAL_BUFFER (octave_idx_type, stats, COLAMD_STATS);
596 if (!SYMAMD_NAME () (n_col, ridx, cidx, perm, knobs, stats, &calloc, &free)) 596 if (!SYMAMD_NAME () (n_col, ridx, cidx, perm, knobs, stats, &calloc, &free))
597 { 597 {
598 SYMAMD_NAME (_report) (stats) ; 598 SYMAMD_NAME (_report) (stats) ;
599 error ("symamd: internal error!") ; 599 error ("symamd: internal error!") ;
600 return retval; 600 return retval;
601 } 601 }
602 602
603 // column elimination tree post-ordering 603 // column elimination tree post-ordering
604 OCTAVE_LOCAL_BUFFER (octave_idx_type, etree, n_col + 1); 604 OCTAVE_LOCAL_BUFFER (octave_idx_type, etree, n_col + 1);
605 symetree (ridx, cidx, etree, perm, n_col); 605 symetree (ridx, cidx, etree, perm, n_col);
606 606
609 tree_postorder (n_col, etree, post); 609 tree_postorder (n_col, etree, post);
610 610
611 // return the permutation vector 611 // return the permutation vector
612 NDArray out_perm (dim_vector (1, n_col)); 612 NDArray out_perm (dim_vector (1, n_col));
613 for (octave_idx_type i = 0; i < n_col; i++) 613 for (octave_idx_type i = 0; i < n_col; i++)
614 out_perm(i) = perm [post [i]] + 1; 614 out_perm(i) = perm [post [i]] + 1;
615 615
616 retval(0) = out_perm; 616 retval(0) = out_perm;
617 617
618 // print stats if spumoni > 0 618 // print stats if spumoni > 0
619 if (spumoni > 0) 619 if (spumoni > 0)
620 SYMAMD_NAME (_report) (stats) ; 620 SYMAMD_NAME (_report) (stats) ;
621 621
622 // Return the stats vector 622 // Return the stats vector
623 if (nargout == 2) 623 if (nargout == 2)
624 { 624 {
625 NDArray out_stats (dim_vector (1, COLAMD_STATS)); 625 NDArray out_stats (dim_vector (1, COLAMD_STATS));
626 for (octave_idx_type i = 0 ; i < COLAMD_STATS ; i++) 626 for (octave_idx_type i = 0 ; i < COLAMD_STATS ; i++)
627 out_stats (i) = stats [i] ; 627 out_stats (i) = stats [i] ;
628 retval(1) = out_stats; 628 retval(1) = out_stats;
629 629
630 // fix stats (5) and (6), for 1-based information on 630 // fix stats (5) and (6), for 1-based information on
631 // jumbled matrix. note that this correction doesn't 631 // jumbled matrix. note that this correction doesn't
632 // occur if symamd returns FALSE 632 // occur if symamd returns FALSE
633 out_stats (COLAMD_INFO1) ++ ; 633 out_stats (COLAMD_INFO1) ++ ;
634 out_stats (COLAMD_INFO2) ++ ; 634 out_stats (COLAMD_INFO2) ++ ;
635 } 635 }
636 } 636 }
637 637
638 #else 638 #else
639 639
640 error ("symamd: not available in this version of Octave"); 640 error ("symamd: not available in this version of Octave");
673 bool is_sym = true; 673 bool is_sym = true;
674 SparseMatrix sm; 674 SparseMatrix sm;
675 SparseComplexMatrix scm; 675 SparseComplexMatrix scm;
676 676
677 if (args(0).is_sparse_type ()) 677 if (args(0).is_sparse_type ())
678 { 678 {
679 if (args(0).is_complex_type ()) 679 if (args(0).is_complex_type ())
680 { 680 {
681 scm = args(0).sparse_complex_matrix_value (); 681 scm = args(0).sparse_complex_matrix_value ();
682 n_row = scm.rows (); 682 n_row = scm.rows ();
683 n_col = scm.cols (); 683 n_col = scm.cols ();
684 nnz = scm.nzmax (); 684 nnz = scm.nzmax ();
685 ridx = scm.xridx (); 685 ridx = scm.xridx ();
686 cidx = scm.xcidx (); 686 cidx = scm.xcidx ();
687 } 687 }
688 else 688 else
689 { 689 {
690 sm = args(0).sparse_matrix_value (); 690 sm = args(0).sparse_matrix_value ();
691 n_row = sm.rows (); 691 n_row = sm.rows ();
692 n_col = sm.cols (); 692 n_col = sm.cols ();
693 nnz = sm.nzmax (); 693 nnz = sm.nzmax ();
694 ridx = sm.xridx (); 694 ridx = sm.xridx ();
695 cidx = sm.xcidx (); 695 cidx = sm.xcidx ();
696 } 696 }
697 697
698 } 698 }
699 else 699 else
700 { 700 {
701 error ("etree: must be called with a sparse matrix"); 701 error ("etree: must be called with a sparse matrix");
702 return retval; 702 return retval;
703 } 703 }
704 704
705 if (nargin == 2) 705 if (nargin == 2)
706 { 706 {
707 if (args(1).is_string ()) 707 if (args(1).is_string ())
708 { 708 {
709 std::string str = args(1).string_value (); 709 std::string str = args(1).string_value ();
710 if (str.find ("C") == 0 || str.find ("c") == 0) 710 if (str.find ("C") == 0 || str.find ("c") == 0)
711 is_sym = false; 711 is_sym = false;
712 } 712 }
713 else 713 else
714 { 714 {
715 error ("etree: second argument must be a string"); 715 error ("etree: second argument must be a string");
716 return retval; 716 return retval;
717 } 717 }
718 } 718 }
719 719
720 // column elimination tree post-ordering (reuse variables) 720 // column elimination tree post-ordering (reuse variables)
721 OCTAVE_LOCAL_BUFFER (octave_idx_type, etree, n_col + 1); 721 OCTAVE_LOCAL_BUFFER (octave_idx_type, etree, n_col + 1);
722 722
723 if (is_sym) 723 if (is_sym)
724 { 724 {
725 if (n_row != n_col) 725 if (n_row != n_col)
726 { 726 {
727 error ("etree: matrix is marked as symmetric, but not square"); 727 error ("etree: matrix is marked as symmetric, but not square");
728 return retval; 728 return retval;
729 } 729 }
730 730
731 symetree (ridx, cidx, etree, 0, n_col); 731 symetree (ridx, cidx, etree, 0, n_col);
732 } 732 }
733 else 733 else
734 { 734 {
735 OCTAVE_LOCAL_BUFFER (octave_idx_type, colbeg, n_col); 735 OCTAVE_LOCAL_BUFFER (octave_idx_type, colbeg, n_col);
736 OCTAVE_LOCAL_BUFFER (octave_idx_type, colend, n_col); 736 OCTAVE_LOCAL_BUFFER (octave_idx_type, colend, n_col);
737 737
738 for (octave_idx_type i = 0; i < n_col; i++) 738 for (octave_idx_type i = 0; i < n_col; i++)
739 { 739 {
740 colbeg[i] = cidx[i]; 740 colbeg[i] = cidx[i];
741 colend[i] = cidx[i+1]; 741 colend[i] = cidx[i+1];
742 } 742 }
743 743
744 coletree (ridx, colbeg, colend, etree, n_row, n_col); 744 coletree (ridx, colbeg, colend, etree, n_row, n_col);
745 } 745 }
746 746
747 NDArray tree (dim_vector (1, n_col)); 747 NDArray tree (dim_vector (1, n_col));
748 for (octave_idx_type i = 0; i < n_col; i++) 748 for (octave_idx_type i = 0; i < n_col; i++)
749 // We flag a root with n_col while Matlab does it with zero 749 // We flag a root with n_col while Matlab does it with zero
750 // Convert for matlab compatiable output 750 // Convert for matlab compatiable output
751 if (etree[i] == n_col) 751 if (etree[i] == n_col)
752 tree(i) = 0; 752 tree(i) = 0;
753 else 753 else
754 tree(i) = etree[i] + 1; 754 tree(i) = etree[i] + 1;
755 755
756 retval(0) = tree; 756 retval(0) = tree;
757 757
758 if (nargout == 2) 758 if (nargout == 2)
759 { 759 {
760 // Calculate the tree post-ordering 760 // Calculate the tree post-ordering
761 OCTAVE_LOCAL_BUFFER (octave_idx_type, post, n_col + 1); 761 OCTAVE_LOCAL_BUFFER (octave_idx_type, post, n_col + 1);
762 tree_postorder (n_col, etree, post); 762 tree_postorder (n_col, etree, post);
763 763
764 NDArray postorder (dim_vector (1, n_col)); 764 NDArray postorder (dim_vector (1, n_col));
765 for (octave_idx_type i = 0; i < n_col; i++) 765 for (octave_idx_type i = 0; i < n_col; i++)
766 postorder(i) = post[i] + 1; 766 postorder(i) = post[i] + 1;
767 767
768 retval(1) = postorder; 768 retval(1) = postorder;
769 } 769 }
770 } 770 }
771 771
772 return retval; 772 return retval;
773 } 773 }
774 774