ccolamd.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 2005-2012 David Bateman
00004 
00005 This file is part of Octave.
00006 
00007 Octave is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 Octave is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Octave; see the file COPYING.  If not, see
00019 <http://www.gnu.org/licenses/>.
00020 
00021 */
00022 
00023 // This is the octave interface to ccolamd, which bore the copyright given
00024 // in the help of the functions.
00025 
00026 #ifdef HAVE_CONFIG_H
00027 #include <config.h>
00028 #endif
00029 
00030 #include <cstdlib>
00031 
00032 #include <string>
00033 #include <vector>
00034 
00035 #include "ov.h"
00036 #include "defun-dld.h"
00037 #include "pager.h"
00038 #include "ov-re-mat.h"
00039 
00040 #include "ov-re-sparse.h"
00041 #include "ov-cx-sparse.h"
00042 
00043 #include "oct-sparse.h"
00044 #include "oct-locbuf.h"
00045 
00046 #ifdef IDX_TYPE_LONG
00047 #define CCOLAMD_NAME(name) ccolamd_l ## name
00048 #define CSYMAMD_NAME(name) csymamd_l ## name
00049 #else
00050 #define CCOLAMD_NAME(name) ccolamd ## name
00051 #define CSYMAMD_NAME(name) csymamd ## name
00052 #endif
00053 
00054 DEFUN_DLD (ccolamd, args, nargout,
00055     "-*- texinfo -*-\n\
00056 @deftypefn  {Loadable Function} {@var{p} =} ccolamd (@var{S})\n\
00057 @deftypefnx {Loadable Function} {@var{p} =} ccolamd (@var{S}, @var{knobs})\n\
00058 @deftypefnx {Loadable Function} {@var{p} =} ccolamd (@var{S}, @var{knobs}, @var{cmember})\n\
00059 @deftypefnx {Loadable Function} {[@var{p}, @var{stats}] =} ccolamd (@dots{})\n\
00060 \n\
00061 Constrained column approximate minimum degree permutation.\n\
00062 @code{@var{p} = ccolamd (@var{S})} returns the column approximate minimum\n\
00063 degree permutation vector for the sparse matrix @var{S}.  For a non-symmetric\n\
00064 matrix\n\
00065 @var{S},\n\
00066 @code{@var{S}(:, @var{p})} tends to have sparser LU@tie{}factors than\n\
00067 @var{S}.  @code{chol (@var{S}(:, @var{p})' * @var{S}(:, @var{p}))} also\n\
00068 tends to be sparser than @code{chol (@var{S}' * @var{S})}.  @code{@var{p} =\n\
00069 ccolamd (@var{S}, 1)} optimizes the ordering for @code{lu (@var{S}(:,\n\
00070 @var{p}))}.  The ordering is followed by a column elimination tree\n\
00071 post-ordering.\n\
00072 \n\
00073 @var{knobs} is an optional 1-element to 5-element input vector, with a\n\
00074 default value of @code{[0 10 10 1 0]} if not present or empty.  Entries not\n\
00075 present are set to their defaults.\n\
00076 \n\
00077 @table @code\n\
00078 @item @var{knobs}(1)\n\
00079 if nonzero, the ordering is optimized for @code{lu (S(:, p))}.  It will be a\n\
00080 poor ordering for @code{chol (@var{S}(:, @var{p})' * @var{S}(:,\n\
00081 @var{p}))}.  This is the most important knob for ccolamd.\n\
00082 \n\
00083 @item @var{knobs}(2)\n\
00084 if @var{S} is m-by-n, rows with more than @code{max (16, @var{knobs}(2) *\n\
00085 sqrt (n))} entries are ignored.\n\
00086 \n\
00087 @item @var{knobs}(3)\n\
00088 columns with more than @code{max (16, @var{knobs}(3) * sqrt (min (@var{m},\n\
00089 @var{n})))} entries are ignored and ordered last in the output permutation\n\
00090 (subject to the cmember constraints).\n\
00091 \n\
00092 @item @var{knobs}(4)\n\
00093 if nonzero, aggressive absorption is performed.\n\
00094 \n\
00095 @item @var{knobs}(5)\n\
00096 if nonzero, statistics and knobs are printed.\n\
00097 \n\
00098 @end table\n\
00099 \n\
00100 @var{cmember} is an optional vector of length @math{n}.  It defines the\n\
00101 constraints on the column ordering.  If @code{@var{cmember}(j) = @var{c}},\n\
00102 then column @var{j} is in constraint set @var{c} (@var{c} must be in the\n\
00103 range 1 to\n\
00104 n).  In the output permutation @var{p}, all columns in set 1 appear\n\
00105 first, followed by all columns in set 2, and so on.  @code{@var{cmember} =\n\
00106 ones(1,n)} if not present or empty.\n\
00107 @code{ccolamd (@var{S}, [], 1 : n)} returns @code{1 : n}\n\
00108 \n\
00109 @code{@var{p} = ccolamd (@var{S})} is about the same as\n\
00110 @code{@var{p} = colamd (@var{S})}.  @var{knobs} and its default values\n\
00111 differ.  @code{colamd} always does aggressive absorption, and it finds an\n\
00112 ordering suitable for both @code{lu (@var{S}(:, @var{p}))} and @code{chol\n\
00113 (@var{S}(:, @var{p})' * @var{S}(:, @var{p}))}; it cannot optimize its\n\
00114 ordering for @code{lu (@var{S}(:, @var{p}))} to the extent that\n\
00115 @code{ccolamd (@var{S}, 1)} can.\n\
00116 \n\
00117 @var{stats} is an optional 20-element output vector that provides data\n\
00118 about the ordering and the validity of the input matrix @var{S}.  Ordering\n\
00119 statistics are in @code{@var{stats}(1 : 3)}.  @code{@var{stats}(1)} and\n\
00120 @code{@var{stats}(2)} are the number of dense or empty rows and columns\n\
00121 ignored by @sc{ccolamd} and @code{@var{stats}(3)} is the number of garbage\n\
00122 collections performed on the internal data structure used by @sc{ccolamd}\n\
00123 (roughly of size @code{2.2 * nnz (@var{S}) + 4 * @var{m} + 7 * @var{n}}\n\
00124 integers).\n\
00125 \n\
00126 @code{@var{stats}(4 : 7)} provide information if CCOLAMD was able to\n\
00127 continue.  The matrix is OK if @code{@var{stats}(4)} is zero, or 1 if\n\
00128 invalid.  @code{@var{stats}(5)} is the rightmost column index that is\n\
00129 unsorted or contains duplicate entries, or zero if no such column exists.\n\
00130 @code{@var{stats}(6)} is the last seen duplicate or out-of-order row\n\
00131 index in the column index given by @code{@var{stats}(5)}, or zero if no\n\
00132 such row index exists.  @code{@var{stats}(7)} is the number of duplicate\n\
00133 or out-of-order row indices.  @code{@var{stats}(8 : 20)} is always zero in\n\
00134 the current version of @sc{ccolamd} (reserved for future use).\n\
00135 \n\
00136 The authors of the code itself are S. Larimore, T. Davis (Univ. of Florida)\n\
00137 and S. Rajamanickam in collaboration with J. Bilbert and E. Ng.  Supported\n\
00138 by the National Science Foundation (DMS-9504974, DMS-9803599, CCR-0203270),\n\
00139 and a grant from Sandia National Lab.  See\n\
00140 @url{http://www.cise.ufl.edu/research/sparse} for ccolamd, csymamd, amd,\n\
00141 colamd, symamd, and other related orderings.\n\
00142 @seealso{colamd, csymamd}\n\
00143 @end deftypefn")
00144 {
00145   octave_value_list retval;
00146 
00147 #ifdef HAVE_CCOLAMD
00148 
00149   int nargin = args.length ();
00150   int spumoni = 0;
00151 
00152   if (nargout > 2 || nargin < 1 || nargin > 3)
00153     usage ("ccolamd: incorrect number of input and/or output arguments");
00154   else
00155     {
00156       // Get knobs
00157       OCTAVE_LOCAL_BUFFER (double, knobs, CCOLAMD_KNOBS);
00158       CCOLAMD_NAME (_set_defaults) (knobs);
00159 
00160       // Check for user-passed knobs
00161       if (nargin > 1)
00162         {
00163           NDArray User_knobs = args(1).array_value ();
00164           int nel_User_knobs = User_knobs.length ();
00165 
00166           if (nel_User_knobs > 0)
00167             knobs [CCOLAMD_LU] = (User_knobs (0) != 0);
00168           if (nel_User_knobs > 1)
00169             knobs [CCOLAMD_DENSE_ROW]  = User_knobs (1);
00170           if (nel_User_knobs > 2)
00171             knobs [CCOLAMD_DENSE_COL]  = User_knobs (2);
00172           if (nel_User_knobs > 3)
00173             knobs [CCOLAMD_AGGRESSIVE] = (User_knobs (3) != 0);
00174           if (nel_User_knobs > 4)
00175             spumoni = (User_knobs (4) != 0);
00176 
00177           // print knob settings if spumoni is set
00178           if (spumoni)
00179             {
00180               octave_stdout << "\nccolamd version " << CCOLAMD_MAIN_VERSION << "."
00181                             <<  CCOLAMD_SUB_VERSION << ", " << CCOLAMD_DATE
00182                             << ":\nknobs(1): " << User_knobs (0) << ", order for ";
00183               if ( knobs [CCOLAMD_LU] != 0)
00184                 octave_stdout << "lu(A)\n";
00185               else
00186                 octave_stdout << "chol(A'*A)\n";
00187 
00188               if (knobs [CCOLAMD_DENSE_ROW] >= 0)
00189                 octave_stdout << "knobs(2): " << User_knobs (1)
00190                               << ", rows with > max(16,"
00191                               << knobs [CCOLAMD_DENSE_ROW] << "*sqrt(size(A,2)))"
00192                               << " entries removed\n";
00193               else
00194                 octave_stdout << "knobs(2): " << User_knobs (1)
00195                               << ", no dense rows removed\n";
00196 
00197               if (knobs [CCOLAMD_DENSE_COL] >= 0)
00198                 octave_stdout << "knobs(3): " << User_knobs (2)
00199                               << ", cols with > max(16,"
00200                               << knobs [CCOLAMD_DENSE_COL] << "*sqrt(size(A)))"
00201                               << " entries removed\n";
00202               else
00203                 octave_stdout << "knobs(3): " << User_knobs (2)
00204                               << ", no dense columns removed\n";
00205 
00206               if (knobs [CCOLAMD_AGGRESSIVE] != 0)
00207                 octave_stdout << "knobs(4): " << User_knobs(3)
00208                               << ", aggressive absorption: yes";
00209               else
00210                 octave_stdout << "knobs(4): " << User_knobs(3)
00211                               << ", aggressive absorption: no";
00212 
00213               octave_stdout << "knobs(5): " << User_knobs (4)
00214                             << ", statistics and knobs printed\n";
00215             }
00216         }
00217 
00218       octave_idx_type n_row, n_col, nnz;
00219       octave_idx_type *ridx, *cidx;
00220       SparseComplexMatrix scm;
00221       SparseMatrix sm;
00222 
00223       if (args(0).is_sparse_type ())
00224         {
00225           if (args(0).is_complex_type ())
00226             {
00227               scm = args(0). sparse_complex_matrix_value ();
00228               n_row = scm.rows ();
00229               n_col = scm.cols ();
00230               nnz = scm.nnz ();
00231               ridx = scm.xridx ();
00232               cidx = scm.xcidx ();
00233             }
00234           else
00235             {
00236               sm = args(0).sparse_matrix_value ();
00237 
00238               n_row = sm.rows ();
00239               n_col = sm.cols ();
00240               nnz = sm.nnz ();
00241               ridx = sm.xridx ();
00242               cidx = sm.xcidx ();
00243             }
00244         }
00245       else
00246         {
00247           if (args(0).is_complex_type ())
00248             sm = SparseMatrix (real (args(0).complex_matrix_value ()));
00249           else
00250             sm = SparseMatrix (args(0).matrix_value ());
00251 
00252           n_row = sm.rows ();
00253           n_col = sm.cols ();
00254           nnz = sm.nnz ();
00255           ridx = sm.xridx ();
00256           cidx = sm.xcidx ();
00257         }
00258 
00259       // Allocate workspace for ccolamd
00260       OCTAVE_LOCAL_BUFFER (octave_idx_type, p, n_col+1);
00261       for (octave_idx_type i = 0; i < n_col+1; i++)
00262         p[i] = cidx [i];
00263 
00264       octave_idx_type Alen = CCOLAMD_NAME (_recommended) (nnz, n_row, n_col);
00265       OCTAVE_LOCAL_BUFFER (octave_idx_type, A, Alen);
00266       for (octave_idx_type i = 0; i < nnz; i++)
00267         A[i] = ridx [i];
00268 
00269       OCTAVE_LOCAL_BUFFER (octave_idx_type, stats, CCOLAMD_STATS);
00270 
00271       if (nargin > 2)
00272         {
00273           NDArray in_cmember = args(2).array_value();
00274           octave_idx_type cslen = in_cmember.length();
00275           OCTAVE_LOCAL_BUFFER (octave_idx_type, cmember, cslen);
00276           for (octave_idx_type i = 0; i < cslen; i++)
00277             // convert cmember from 1-based to 0-based
00278             cmember[i] = static_cast<octave_idx_type>(in_cmember(i) - 1);
00279 
00280           if (cslen != n_col)
00281             error ("ccolamd: CMEMBER must be of length equal to #cols of A");
00282           else
00283             // Order the columns (destroys A)
00284             if (! CCOLAMD_NAME () (n_row, n_col, Alen, A, p, knobs, stats, cmember))
00285               {
00286                 CCOLAMD_NAME (_report) (stats) ;
00287                 error ("ccolamd: internal error!");
00288                 return retval;
00289               }
00290         }
00291       else
00292         {
00293           // Order the columns (destroys A)
00294           if (! CCOLAMD_NAME () (n_row, n_col, Alen, A, p, knobs, stats, 0))
00295             {
00296               CCOLAMD_NAME (_report) (stats) ;
00297               error ("ccolamd: internal error!");
00298               return retval;
00299             }
00300         }
00301 
00302       // return the permutation vector
00303       NDArray out_perm (dim_vector (1, n_col));
00304       for (octave_idx_type i = 0; i < n_col; i++)
00305         out_perm(i) = p [i] + 1;
00306 
00307       retval (0) = out_perm;
00308 
00309       // print stats if spumoni > 0
00310       if (spumoni > 0)
00311         CCOLAMD_NAME (_report) (stats) ;
00312 
00313       // Return the stats vector
00314       if (nargout == 2)
00315         {
00316           NDArray out_stats (dim_vector (1, CCOLAMD_STATS));
00317           for (octave_idx_type i = 0 ; i < CCOLAMD_STATS ; i++)
00318             out_stats (i) = stats [i] ;
00319           retval(1) = out_stats;
00320 
00321           // fix stats (5) and (6), for 1-based information on
00322           // jumbled matrix.  note that this correction doesn't
00323           // occur if symamd returns FALSE
00324           out_stats (CCOLAMD_INFO1) ++ ;
00325           out_stats (CCOLAMD_INFO2) ++ ;
00326         }
00327     }
00328 
00329 #else
00330 
00331   error ("ccolamd: not available in this version of Octave");
00332 
00333 #endif
00334 
00335   return retval;
00336 }
00337 
00338 DEFUN_DLD (csymamd, args, nargout,
00339     "-*- texinfo -*-\n\
00340 @deftypefn  {Loadable Function} {@var{p} =} csymamd (@var{S})\n\
00341 @deftypefnx {Loadable Function} {@var{p} =} csymamd (@var{S}, @var{knobs})\n\
00342 @deftypefnx {Loadable Function} {@var{p} =} csymamd (@var{S}, @var{knobs}, @var{cmember})\n\
00343 @deftypefnx {Loadable Function} {[@var{p}, @var{stats}] =} csymamd (@dots{})\n\
00344 \n\
00345 For a symmetric positive definite matrix @var{S}, returns the permutation\n\
00346 vector @var{p} such that @code{@var{S}(@var{p},@var{p})} tends to have a\n\
00347 sparser Cholesky@tie{}factor than @var{S}.  Sometimes @code{csymamd} works\n\
00348 well for symmetric indefinite matrices too.  The matrix @var{S} is assumed\n\
00349 to be symmetric; only the strictly lower triangular part is referenced.\n\
00350 @var{S} must be square.  The ordering is followed by an elimination tree\n\
00351 post-ordering.\n\
00352 \n\
00353 @var{knobs} is an optional 1-element to 3-element input vector, with a\n\
00354 default value of @code{[10 1 0]} if present or empty.  Entries not\n\
00355 present are set to their defaults.\n\
00356 \n\
00357 @table @code\n\
00358 @item @var{knobs}(1)\n\
00359 If @var{S} is n-by-n, then rows and columns with more than\n\
00360 @code{max(16,@var{knobs}(1)*sqrt(n))} entries are ignored, and ordered\n\
00361 last in the output permutation (subject to the cmember constraints).\n\
00362 \n\
00363 @item @var{knobs}(2)\n\
00364 If nonzero, aggressive absorption is performed.\n\
00365 \n\
00366 @item @var{knobs}(3)\n\
00367 If nonzero, statistics and knobs are printed.\n\
00368 \n\
00369 @end table\n\
00370 \n\
00371 @var{cmember} is an optional vector of length n. It defines the constraints\n\
00372 on the ordering.  If @code{@var{cmember}(j) = @var{S}}, then row/column j is\n\
00373 in constraint set @var{c} (@var{c} must be in the range 1 to n).  In the\n\
00374 output permutation @var{p}, rows/columns in set 1 appear first, followed\n\
00375 by all rows/columns in set 2, and so on.  @code{@var{cmember} = ones(1,n)}\n\
00376 if not present or empty.  @code{csymamd(@var{S},[],1:n)} returns @code{1:n}.\n\
00377 \n\
00378 @code{@var{p} = csymamd(@var{S})} is about the same as @code{@var{p} =\n\
00379 symamd(@var{S})}.  @var{knobs} and its default values differ.\n\
00380 \n\
00381 @code{@var{stats}(4:7)} provide information if CCOLAMD was able to\n\
00382 continue.  The matrix is OK if @code{@var{stats}(4)} is zero, or 1 if\n\
00383 invalid.  @code{@var{stats}(5)} is the rightmost column index that is\n\
00384 unsorted or contains duplicate entries, or zero if no such column exists.\n\
00385 @code{@var{stats}(6)} is the last seen duplicate or out-of-order row\n\
00386 index in the column index given by @code{@var{stats}(5)}, or zero if no\n\
00387 such row index exists.  @code{@var{stats}(7)} is the number of duplicate\n\
00388 or out-of-order row indices.  @code{@var{stats}(8:20)} is always zero in\n\
00389 the current version of @sc{ccolamd} (reserved for future use).\n\
00390 \n\
00391 The authors of the code itself are S. Larimore, T. Davis (Uni of Florida)\n\
00392 and S. Rajamanickam in collaboration with J. Bilbert and E. Ng.  Supported\n\
00393 by the National Science Foundation (DMS-9504974, DMS-9803599, CCR-0203270),\n\
00394 and a grant from Sandia National Lab.  See\n\
00395 @url{http://www.cise.ufl.edu/research/sparse} for ccolamd, csymamd, amd,\n\
00396 colamd, symamd, and other related orderings.\n\
00397 @seealso{symamd, ccolamd}\n\
00398 @end deftypefn")
00399 {
00400   octave_value_list retval;
00401 
00402 #if HAVE_CCOLAMD
00403 
00404   int nargin = args.length ();
00405   int spumoni = 0;
00406 
00407   if (nargout > 2 || nargin < 1 || nargin > 3)
00408     usage ("ccolamd: incorrect number of input and/or output arguments");
00409   else
00410     {
00411       // Get knobs
00412       OCTAVE_LOCAL_BUFFER (double, knobs, CCOLAMD_KNOBS);
00413       CCOLAMD_NAME (_set_defaults) (knobs);
00414 
00415       // Check for user-passed knobs
00416       if (nargin > 1)
00417         {
00418           NDArray User_knobs = args(1).array_value ();
00419           int nel_User_knobs = User_knobs.length ();
00420 
00421           if (nel_User_knobs > 0)
00422             knobs [CCOLAMD_DENSE_ROW] = User_knobs (0);
00423           if (nel_User_knobs > 0)
00424             knobs [CCOLAMD_AGGRESSIVE] = User_knobs (1);
00425           if (nel_User_knobs > 1)
00426             spumoni = static_cast<int> (User_knobs (2));
00427 
00428           // print knob settings if spumoni is set
00429           if (spumoni)
00430             {
00431               octave_stdout << "\ncsymamd version " << CCOLAMD_MAIN_VERSION << "."
00432                             <<  CCOLAMD_SUB_VERSION << ", " << CCOLAMD_DATE << "\n";
00433 
00434               if (knobs [CCOLAMD_DENSE_ROW] >= 0)
00435                 octave_stdout << "knobs(1): " << User_knobs (0)
00436                               << ", rows/cols with > max(16,"
00437                               << knobs [CCOLAMD_DENSE_ROW] << "*sqrt(size(A,2)))"
00438                               << " entries removed\n";
00439               else
00440                 octave_stdout << "knobs(1): " << User_knobs (0)
00441                               << ", no dense rows/cols removed\n";
00442 
00443               if (knobs [CCOLAMD_AGGRESSIVE] != 0)
00444                 octave_stdout << "knobs(2): " << User_knobs(1)
00445                               << ", aggressive absorption: yes";
00446               else
00447                 octave_stdout << "knobs(2): " << User_knobs(1)
00448                               << ", aggressive absorption: no";
00449 
00450 
00451               octave_stdout << "knobs(3): " << User_knobs (2)
00452                             << ", statistics and knobs printed\n";
00453             }
00454         }
00455 
00456       octave_idx_type n_row, n_col;
00457       octave_idx_type *ridx, *cidx;
00458       SparseMatrix sm;
00459       SparseComplexMatrix scm;
00460 
00461       if (args(0).is_sparse_type ())
00462         {
00463           if (args(0).is_complex_type ())
00464             {
00465               scm = args(0).sparse_complex_matrix_value ();
00466               n_row = scm.rows ();
00467               n_col = scm.cols ();
00468               ridx = scm.xridx ();
00469               cidx = scm.xcidx ();
00470             }
00471           else
00472             {
00473               sm = args(0).sparse_matrix_value ();
00474               n_row = sm.rows ();
00475               n_col = sm.cols ();
00476               ridx = sm.xridx ();
00477               cidx = sm.xcidx ();
00478             }
00479         }
00480       else
00481         {
00482           if (args(0).is_complex_type ())
00483             sm = SparseMatrix (real (args(0).complex_matrix_value ()));
00484           else
00485             sm = SparseMatrix (args(0).matrix_value ());
00486 
00487           n_row = sm.rows ();
00488           n_col = sm.cols ();
00489           ridx = sm.xridx ();
00490           cidx = sm.xcidx ();
00491         }
00492 
00493       if (n_row != n_col)
00494         {
00495           error ("csymamd: matrix S must be square");
00496           return retval;
00497         }
00498 
00499       // Allocate workspace for symamd
00500       OCTAVE_LOCAL_BUFFER (octave_idx_type, perm, n_col+1);
00501       OCTAVE_LOCAL_BUFFER (octave_idx_type, stats, CCOLAMD_STATS);
00502 
00503       if (nargin > 2)
00504         {
00505           NDArray in_cmember = args(2).array_value();
00506           octave_idx_type cslen = in_cmember.length();
00507           OCTAVE_LOCAL_BUFFER (octave_idx_type, cmember, cslen);
00508           for (octave_idx_type i = 0; i < cslen; i++)
00509             // convert cmember from 1-based to 0-based
00510             cmember[i] = static_cast<octave_idx_type>(in_cmember(i) - 1);
00511 
00512           if (cslen != n_col)
00513             error ("csymamd: CMEMBER must be of length equal to #cols of A");
00514           else
00515             if (!CSYMAMD_NAME () (n_col, ridx, cidx, perm, knobs, stats,
00516                                   &calloc, &free, cmember, -1))
00517               {
00518                 CSYMAMD_NAME (_report) (stats) ;
00519                 error ("csymamd: internal error!") ;
00520                 return retval;
00521               }
00522         }
00523       else
00524         {
00525           if (!CSYMAMD_NAME () (n_col, ridx, cidx, perm, knobs, stats,
00526                                 &calloc, &free, 0, -1))
00527             {
00528               CSYMAMD_NAME (_report) (stats) ;
00529               error ("csymamd: internal error!") ;
00530               return retval;
00531             }
00532         }
00533 
00534       // return the permutation vector
00535       NDArray out_perm (dim_vector (1, n_col));
00536       for (octave_idx_type i = 0; i < n_col; i++)
00537         out_perm(i) = perm [i] + 1;
00538 
00539       retval (0) = out_perm;
00540 
00541       // Return the stats vector
00542       if (nargout == 2)
00543         {
00544           NDArray out_stats (dim_vector (1, CCOLAMD_STATS));
00545           for (octave_idx_type i = 0 ; i < CCOLAMD_STATS ; i++)
00546             out_stats (i) = stats [i] ;
00547           retval(1) = out_stats;
00548 
00549           // fix stats (5) and (6), for 1-based information on
00550           // jumbled matrix.  note that this correction doesn't
00551           // occur if symamd returns FALSE
00552           out_stats (CCOLAMD_INFO1) ++ ;
00553           out_stats (CCOLAMD_INFO2) ++ ;
00554         }
00555 
00556       // print stats if spumoni > 0
00557       if (spumoni > 0)
00558         CSYMAMD_NAME (_report) (stats) ;
00559 
00560       // Return the stats vector
00561       if (nargout == 2)
00562         {
00563           NDArray out_stats (dim_vector (1, CCOLAMD_STATS));
00564           for (octave_idx_type i = 0 ; i < CCOLAMD_STATS ; i++)
00565             out_stats (i) = stats [i] ;
00566           retval(1) = out_stats;
00567 
00568           // fix stats (5) and (6), for 1-based information on
00569           // jumbled matrix.  note that this correction doesn't
00570           // occur if symamd returns FALSE
00571           out_stats (CCOLAMD_INFO1) ++ ;
00572           out_stats (CCOLAMD_INFO2) ++ ;
00573         }
00574     }
00575 
00576 #else
00577 
00578   error ("csymamd: not available in this version of Octave");
00579 
00580 #endif
00581 
00582   return retval;
00583 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines