47 #ifdef USE_64_BIT_IDX_T
48 #define COLAMD_NAME(name) colamd_l ## name
49 #define SYMAMD_NAME(name) symamd_l ## name
51 #define COLAMD_NAME(name) colamd ## name
52 #define SYMAMD_NAME(name) symamd ## name
83 for ( ; Flag[i] != k ; i = Parent[i])
135 postnum =
etdfs (
w, first_kid, next_kid, post, postnum);
157 next_kid[v] = first_kid[dad];
162 etdfs (n, first_kid, next_kid, post, 0);
182 if (firstcol[row] > col)
205 cset =
link (cset, rset, pp);
214 @deftypefn {Loadable Function} {@var{p} =} colamd (@var{S})\n\
215 @deftypefnx {Loadable Function} {@var{p} =} colamd (@var{S}, @var{knobs})\n\
216 @deftypefnx {Loadable Function} {[@var{p}, @var{stats}] =} colamd (@var{S})\n\
217 @deftypefnx {Loadable Function} {[@var{p}, @var{stats}] =} colamd (@var{S}, @var{knobs})\n\
219 Compute the column approximate minimum degree permutation.\n\
221 @code{@var{p} = colamd (@var{S})} returns the column approximate minimum\n\
222 degree permutation vector for the sparse matrix @var{S}. For a\n\
223 non-symmetric matrix @var{S}, @code{@var{S}(:,@var{p})} tends to have\n\
224 sparser LU@tie{}factors than @var{S}. The Cholesky@tie{}factorization of\n\
225 @code{@var{S}(:,@var{p})' * @var{S}(:,@var{p})} also tends to be sparser\n\
226 than that of @code{@var{S}' * @var{S}}.\n\
228 @var{knobs} is an optional one- to three-element input vector. If @var{S} is\n\
229 m-by-n, then rows with more than @code{max(16,@var{knobs}(1)*sqrt(n))}\n\
230 entries are ignored. Columns with more than\n\
231 @code{max (16,@var{knobs}(2)*sqrt(min(m,n)))} entries are removed prior to\n\
232 ordering, and ordered last in the output permutation @var{p}. Only\n\
233 completely dense rows or columns are removed if @code{@var{knobs}(1)} and\n\
234 @code{@var{knobs}(2)} are < 0, respectively. If @code{@var{knobs}(3)} is\n\
235 nonzero, @var{stats} and @var{knobs} are printed. The default is\n\
236 @code{@var{knobs} = [10 10 0]}. Note that @var{knobs} differs from earlier\n\
237 versions of colamd.\n\
239 @var{stats} is an optional 20-element output vector that provides data\n\
240 about the ordering and the validity of the input matrix @var{S}. Ordering\n\
241 statistics are in @code{@var{stats}(1:3)}. @code{@var{stats}(1)} and\n\
242 @code{@var{stats}(2)} are the number of dense or empty rows and columns\n\
243 ignored by @sc{colamd} and @code{@var{stats}(3)} is the number of garbage\n\
244 collections performed on the internal data structure used by @sc{colamd}\n\
245 (roughly of size @code{2.2 * nnz(@var{S}) + 4 * @var{m} + 7 * @var{n}}\n\
248 Octave built-in functions are intended to generate valid sparse matrices,\n\
249 with no duplicate entries, with ascending row indices of the nonzeros\n\
250 in each column, with a non-negative number of entries in each column (!)\n\
251 and so on. If a matrix is invalid, then @sc{colamd} may or may not be able\n\
252 to continue. If there are duplicate entries (a row index appears two or\n\
253 more times in the same column) or if the row indices in a column are out\n\
254 of order, then @sc{colamd} can correct these errors by ignoring the duplicate\n\
255 entries and sorting each column of its internal copy of the matrix\n\
256 @var{S} (the input matrix @var{S} is not repaired, however). If a matrix\n\
257 is invalid in other ways then @sc{colamd} cannot continue, an error message\n\
258 is printed, and no output arguments (@var{p} or @var{stats}) are returned.\n\
259 @sc{colamd} is thus a simple way to check a sparse matrix to see if it's\n\
262 @code{@var{stats}(4:7)} provide information if @sc{colamd} was able to\n\
263 continue. The matrix is OK if @code{@var{stats}(4)} is zero, or 1 if\n\
264 invalid. @code{@var{stats}(5)} is the rightmost column index that is\n\
265 unsorted or contains duplicate entries, or zero if no such column exists.\n\
266 @code{@var{stats}(6)} is the last seen duplicate or out-of-order row\n\
267 index in the column index given by @code{@var{stats}(5)}, or zero if no\n\
268 such row index exists. @code{@var{stats}(7)} is the number of duplicate\n\
269 or out-of-order row indices. @code{@var{stats}(8:20)} is always zero in\n\
270 the current version of @sc{colamd} (reserved for future use).\n\
272 The ordering is followed by a column elimination tree post-ordering.\n\
274 The authors of the code itself are @nospell{Stefan I. Larimore} and\n\
275 @nospell{Timothy A. Davis @email{davis@@cise.ufl.edu}}, University of Florida. The algorithm was developed in collaboration with @nospell{John Gilbert},\n\
276 Xerox PARC, and @nospell{Esmond Ng}, Oak Ridge National Laboratory. (see\n\
277 @url{http://www.cise.ufl.edu/research/sparse/colamd})\n\
278 @seealso{colperm, symamd, ccolamd}\n\
285 int nargin = args.
length ();
288 if (nargout > 2 || nargin < 1 || nargin > 2)
299 NDArray User_knobs = args(1).array_value ();
300 int nel_User_knobs = User_knobs.
length ();
302 if (nel_User_knobs > 0)
303 knobs[COLAMD_DENSE_ROW] = User_knobs(0);
304 if (nel_User_knobs > 1)
305 knobs[COLAMD_DENSE_COL] = User_knobs(1) ;
306 if (nel_User_knobs > 2)
307 spumoni =
static_cast<int> (User_knobs(2));
314 <<
"." << COLAMD_SUB_VERSION
315 <<
", " << COLAMD_DATE <<
":\n";
317 if (knobs[COLAMD_DENSE_ROW] >= 0)
319 <<
", rows with > max (16,"
320 << knobs[COLAMD_DENSE_ROW] <<
"*sqrt (size(A,2)))"
321 <<
" entries removed\n";
324 <<
", only completely dense rows removed\n";
326 if (knobs[COLAMD_DENSE_COL] >= 0)
328 <<
", cols with > max (16,"
329 << knobs[COLAMD_DENSE_COL] <<
"*sqrt (size(A)))"
330 <<
" entries removed\n";
333 <<
", only completely dense columns removed\n";
336 <<
", statistics and knobs printed\n";
346 if (args(0).is_sparse_type ())
348 if (args(0).is_complex_type ())
350 scm = args(0). sparse_complex_matrix_value ();
359 sm = args(0).sparse_matrix_value ();
370 if (args(0).is_complex_type ())
394 if (!
COLAMD_NAME () (n_row, n_col, Alen,
A, p, knobs, stats))
397 error (
"colamd: internal error!");
408 colbeg[i] = cidx[p[i]];
409 colend[i] = cidx[p[i]+1];
412 coletree (ridx, colbeg, colend, etree, n_row, n_col);
420 out_perm(i) = p[colbeg[i]] + 1;
422 retval(0) = out_perm;
433 out_stats(i) = stats[i] ;
434 retval(1) = out_stats;
439 out_stats (COLAMD_INFO1) ++ ;
440 out_stats (COLAMD_INFO2) ++ ;
446 error (
"colamd: not available in this version of Octave");
455 @deftypefn {Loadable Function} {@var{p} =} symamd (@var{S})\n\
456 @deftypefnx {Loadable Function} {@var{p} =} symamd (@var{S}, @var{knobs})\n\
457 @deftypefnx {Loadable Function} {[@var{p}, @var{stats}] =} symamd (@var{S})\n\
458 @deftypefnx {Loadable Function} {[@var{p}, @var{stats}] =} symamd (@var{S}, @var{knobs})\n\
460 For a symmetric positive definite matrix @var{S}, returns the permutation\n\
461 vector p such that @code{@var{S}(@var{p}, @var{p})} tends to have a\n\
462 sparser Cholesky@tie{}factor than @var{S}.\n\
464 Sometimes @code{symamd} works well for symmetric indefinite matrices too. \n\
465 The matrix @var{S} is assumed to be symmetric; only the strictly lower\n\
466 triangular part is referenced. @var{S} must be square.\n\
468 @var{knobs} is an optional one- to two-element input vector. If @var{S} is\n\
469 n-by-n, then rows and columns with more than\n\
470 @code{max (16,@var{knobs}(1)*sqrt(n))} entries are removed prior to ordering,\n\
471 and ordered last in the output permutation @var{p}. No rows/columns are\n\
472 removed if @code{@var{knobs}(1) < 0}. If @code{@var{knobs} (2)} is nonzero,\n\
473 @code{stats} and @var{knobs} are printed. The default is\n\
474 @code{@var{knobs} = [10 0]}. Note that @var{knobs} differs from earlier\n\
475 versions of @code{symamd}.\n\
477 @var{stats} is an optional 20-element output vector that provides data\n\
478 about the ordering and the validity of the input matrix @var{S}. Ordering\n\
479 statistics are in @code{@var{stats}(1:3)}.\n\
480 @code{@var{stats}(1) = @var{stats}(2)} is the number of dense or empty rows\n\
481 and columns ignored by SYMAMD and @code{@var{stats}(3)} is the number of\n\
482 garbage collections performed on the internal data structure used by SYMAMD\n\
483 (roughly of size @code{8.4 * nnz (tril (@var{S}, -1)) + 9 * @var{n}}\n\
486 Octave built-in functions are intended to generate valid sparse matrices,\n\
487 with no duplicate entries, with ascending row indices of the nonzeros\n\
488 in each column, with a non-negative number of entries in each column (!)\n\
489 and so on. If a matrix is invalid, then SYMAMD may or may not be able\n\
490 to continue. If there are duplicate entries (a row index appears two or\n\
491 more times in the same column) or if the row indices in a column are out\n\
492 of order, then SYMAMD can correct these errors by ignoring the duplicate\n\
493 entries and sorting each column of its internal copy of the matrix S (the\n\
494 input matrix S is not repaired, however). If a matrix is invalid in\n\
495 other ways then SYMAMD cannot continue, an error message is printed, and\n\
496 no output arguments (@var{p} or @var{stats}) are returned. SYMAMD is\n\
497 thus a simple way to check a sparse matrix to see if it's valid.\n\
499 @code{@var{stats}(4:7)} provide information if SYMAMD was able to\n\
500 continue. The matrix is OK if @code{@var{stats} (4)} is zero, or 1\n\
501 if invalid. @code{@var{stats}(5)} is the rightmost column index that\n\
502 is unsorted or contains duplicate entries, or zero if no such column\n\
503 exists. @code{@var{stats}(6)} is the last seen duplicate or out-of-order\n\
504 row index in the column index given by @code{@var{stats}(5)}, or zero\n\
505 if no such row index exists. @code{@var{stats}(7)} is the number of\n\
506 duplicate or out-of-order row indices. @code{@var{stats}(8:20)} is\n\
507 always zero in the current version of SYMAMD (reserved for future use).\n\
509 The ordering is followed by a column elimination tree post-ordering.\n\
511 The authors of the code itself are @nospell{Stefan I. Larimore} and\n\
512 @nospell{Timothy A. Davis @email{davis@@cise.ufl.edu}}, University of Florida. The algorithm was developed in collaboration with @nospell{John Gilbert},\n\
513 Xerox PARC, and @nospell{Esmond Ng}, Oak Ridge National Laboratory. (see\n\
514 @url{http://www.cise.ufl.edu/research/sparse/colamd})\n\
515 @seealso{colperm, colamd}\n\
522 int nargin = args.
length ();
525 if (nargout > 2 || nargin < 1 || nargin > 2)
536 NDArray User_knobs = args(1).array_value ();
537 int nel_User_knobs = User_knobs.
length ();
539 if (nel_User_knobs > 0)
540 knobs[COLAMD_DENSE_ROW] = User_knobs(COLAMD_DENSE_ROW);
541 if (nel_User_knobs > 1)
542 spumoni =
static_cast<int> (User_knobs (1));
548 << knobs[COLAMD_DENSE_ROW] << std::endl;
555 if (args(0).is_sparse_type ())
557 if (args(0).is_complex_type ())
559 scm = args(0).sparse_complex_matrix_value ();
567 sm = args(0).sparse_matrix_value ();
576 if (args(0).is_complex_type ())
589 error (
"symamd: matrix S must be square");
597 knobs, stats, &calloc, &
free))
600 error (
"symamd: internal error!") ;
606 symetree (ridx, cidx, etree, perm, n_col);
615 out_perm(i) = perm[post[i]] + 1;
617 retval(0) = out_perm;
628 out_stats(i) = stats[i] ;
629 retval(1) = out_stats;
634 out_stats (COLAMD_INFO1) ++ ;
635 out_stats (COLAMD_INFO2) ++ ;
641 error (
"symamd: not available in this version of Octave");
650 @deftypefn {Loadable Function} {@var{p} =} etree (@var{S})\n\
651 @deftypefnx {Loadable Function} {@var{p} =} etree (@var{S}, @var{typ})\n\
652 @deftypefnx {Loadable Function} {[@var{p}, @var{q}] =} etree (@var{S}, @var{typ})\n\
654 Return the elimination tree for the matrix @var{S}.\n\
656 By default @var{S} is assumed to be symmetric and the symmetric elimination\n\
657 tree is returned. The argument @var{typ} controls whether a symmetric or\n\
658 column elimination tree is returned. Valid values of @var{typ} are\n\
659 @qcode{\"sym\"} or @qcode{\"col\"}, for symmetric or column elimination tree\n\
662 Called with a second argument, @code{etree} also returns the postorder\n\
663 permutations on the tree.\n\
668 int nargin = args.
length ();
670 if (nargout > 2 || nargin < 1 || nargin > 2)
680 if (args(0).is_sparse_type ())
682 if (args(0).is_complex_type ())
684 scm = args(0).sparse_complex_matrix_value ();
692 sm = args(0).sparse_matrix_value ();
702 error (
"etree: S must be a sparse matrix");
708 if (args(1).is_string ())
710 std::string str = args(1).string_value ();
711 if (str.find (
"C") == 0 || str.find (
"c") == 0)
716 error (
"etree: TYP must be a string");
728 error (
"etree: S is marked as symmetric, but is not square");
732 symetree (ridx, cidx, etree, 0, n_col);
742 colend[i] = cidx[i+1];
745 coletree (ridx, colbeg, colend, etree, n_row, n_col);
752 if (etree[i] == n_col)
755 tree(i) = etree[i] + 1;
767 postorder(i) = post[i] + 1;
769 retval(1) = postorder;
octave_idx_type * xridx(void)
octave_idx_type cols(void) const
octave_idx_type rows(void) const
OCTINTERP_API void print_usage(void)
octave_idx_type length(void) const
F77_RET_T const octave_idx_type Complex * A
octave_idx_type * xcidx(void)
void error(const char *fmt,...)
static void coletree(const octave_idx_type *ridx, const octave_idx_type *colbeg, octave_idx_type *colend, octave_idx_type *parent, octave_idx_type nr, octave_idx_type nc)
static void tree_postorder(octave_idx_type n, octave_idx_type *parent, octave_idx_type *post)
octave_idx_type nnz(void) const
static octave_idx_type make_set(octave_idx_type i, octave_idx_type *pp)
static octave_idx_type link(octave_idx_type s, octave_idx_type t, octave_idx_type *pp)
std::complex< double > w(std::complex< double > z, double relerr=0)
static octave_idx_type find(octave_idx_type i, octave_idx_type *pp)
octave_idx_type length(void) const
Number of elements in the array.
#define SYMAMD_NAME(name)
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
#define DEFUN_DLD(name, args_name, nargout_name, doc)
static void symetree(const octave_idx_type *ridx, const octave_idx_type *cidx, octave_idx_type *Parent, octave_idx_type *P, octave_idx_type n)
#define COLAMD_NAME(name)
ColumnVector real(const ComplexColumnVector &a)
static octave_idx_type etdfs(octave_idx_type v, octave_idx_type *first_kid, octave_idx_type *next_kid, octave_idx_type *post, octave_idx_type postnum)