GNU Octave  4.0.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
ccolamd.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2005-2015 David Bateman
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 // This is the octave interface to ccolamd, which bore the copyright given
24 // in the help of the functions.
25 
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29 
30 #include <cstdlib>
31 
32 #include <string>
33 #include <vector>
34 
35 #include "ov.h"
36 #include "defun-dld.h"
37 #include "pager.h"
38 #include "ov-re-mat.h"
39 
40 #include "ov-re-sparse.h"
41 #include "ov-cx-sparse.h"
42 
43 #include "oct-sparse.h"
44 #include "oct-locbuf.h"
45 
46 #ifdef USE_64_BIT_IDX_T
47 #define CCOLAMD_NAME(name) ccolamd_l ## name
48 #define CSYMAMD_NAME(name) csymamd_l ## name
49 #else
50 #define CCOLAMD_NAME(name) ccolamd ## name
51 #define CSYMAMD_NAME(name) csymamd ## name
52 #endif
53 
54 DEFUN_DLD (ccolamd, args, nargout,
55  "-*- texinfo -*-\n\
56 @deftypefn {Loadable Function} {@var{p} =} ccolamd (@var{S})\n\
57 @deftypefnx {Loadable Function} {@var{p} =} ccolamd (@var{S}, @var{knobs})\n\
58 @deftypefnx {Loadable Function} {@var{p} =} ccolamd (@var{S}, @var{knobs}, @var{cmember})\n\
59 @deftypefnx {Loadable Function} {[@var{p}, @var{stats}] =} ccolamd (@dots{})\n\
60 \n\
61 Constrained column approximate minimum degree permutation.\n\
62 \n\
63 @code{@var{p} = ccolamd (@var{S})} returns the column approximate minimum\n\
64 degree permutation vector for the sparse matrix @var{S}. For a non-symmetric\n\
65 matrix @var{S}, @code{@var{S}(:, @var{p})} tends to have sparser\n\
66 LU@tie{}factors than @var{S}.\n\
67 @code{chol (@var{S}(:, @var{p})' * @var{S}(:, @var{p}))} also tends to be\n\
68 sparser than @code{chol (@var{S}' * @var{S})}.\n\
69 @code{@var{p} = ccolamd (@var{S}, 1)} optimizes the ordering for\n\
70 @code{lu (@var{S}(:, @var{p}))}. The ordering is followed by a column\n\
71 elimination tree post-ordering.\n\
72 \n\
73 @var{knobs} is an optional 1-element to 5-element input vector, with a\n\
74 default value of @code{[0 10 10 1 0]} if not present or empty. Entries not\n\
75 present are set to their defaults.\n\
76 \n\
77 @table @code\n\
78 @item @var{knobs}(1)\n\
79 if nonzero, the ordering is optimized for @code{lu (S(:, p))}. It will be a\n\
80 poor ordering for @code{chol (@var{S}(:, @var{p})' * @var{S}(:, @var{p}))}.\n\
81 This is the most important knob for ccolamd.\n\
82 \n\
83 @item @var{knobs}(2)\n\
84 if @var{S} is m-by-n, rows with more than\n\
85 @code{max (16, @var{knobs}(2) * sqrt (n))} entries are ignored.\n\
86 \n\
87 @item @var{knobs}(3)\n\
88 columns with more than\n\
89 @code{max (16, @var{knobs}(3) * sqrt (min (@var{m}, @var{n})))} entries are\n\
90 ignored and ordered last in the output permutation\n\
91 (subject to the cmember constraints).\n\
92 \n\
93 @item @var{knobs}(4)\n\
94 if nonzero, aggressive absorption is performed.\n\
95 \n\
96 @item @var{knobs}(5)\n\
97 if nonzero, statistics and knobs are printed.\n\
98 \n\
99 @end table\n\
100 \n\
101 @var{cmember} is an optional vector of length @math{n}. It defines the\n\
102 constraints on the column ordering. If @code{@var{cmember}(j) = @var{c}},\n\
103 then column @var{j} is in constraint set @var{c} (@var{c} must be in the\n\
104 range 1 to n). In the output permutation @var{p}, all columns in set 1\n\
105 appear first, followed by all columns in set 2, and so on.\n\
106 @code{@var{cmember} = ones (1,n)} if not present or empty.\n\
107 @code{ccolamd (@var{S}, [], 1 : n)} returns @code{1 : n}\n\
108 \n\
109 @code{@var{p} = ccolamd (@var{S})} is about the same as\n\
110 @code{@var{p} = colamd (@var{S})}. @var{knobs} and its default values\n\
111 differ. @code{colamd} always does aggressive absorption, and it finds an\n\
112 ordering suitable for both @code{lu (@var{S}(:, @var{p}))} and @code{chol\n\
113 (@var{S}(:, @var{p})' * @var{S}(:, @var{p}))}; it cannot optimize its\n\
114 ordering for @code{lu (@var{S}(:, @var{p}))} to the extent that\n\
115 @code{ccolamd (@var{S}, 1)} can.\n\
116 \n\
117 @var{stats} is an optional 20-element output vector that provides data\n\
118 about the ordering and the validity of the input matrix @var{S}. Ordering\n\
119 statistics are in @code{@var{stats}(1 : 3)}. @code{@var{stats}(1)} and\n\
120 @code{@var{stats}(2)} are the number of dense or empty rows and columns\n\
121 ignored by @sc{ccolamd} and @code{@var{stats}(3)} is the number of garbage\n\
122 collections performed on the internal data structure used by @sc{ccolamd}\n\
123 (roughly of size @code{2.2 * nnz (@var{S}) + 4 * @var{m} + 7 * @var{n}}\n\
124 integers).\n\
125 \n\
126 @code{@var{stats}(4 : 7)} provide information if CCOLAMD was able to\n\
127 continue. The matrix is OK if @code{@var{stats}(4)} is zero, or 1 if\n\
128 invalid. @code{@var{stats}(5)} is the rightmost column index that is\n\
129 unsorted or contains duplicate entries, or zero if no such column exists.\n\
130 @code{@var{stats}(6)} is the last seen duplicate or out-of-order row\n\
131 index in the column index given by @code{@var{stats}(5)}, or zero if no\n\
132 such row index exists. @code{@var{stats}(7)} is the number of duplicate\n\
133 or out-of-order row indices. @code{@var{stats}(8 : 20)} is always zero in\n\
134 the current version of @sc{ccolamd} (reserved for future use).\n\
135 \n\
136 The authors of the code itself are @nospell{S. Larimore, T. Davis}\n\
137 (Univ. of Florida) and @nospell{S. Rajamanickam} in collaboration with\n\
138 @nospell{J. Bilbert and E. Ng}. Supported by the National Science Foundation\n\
139 @nospell{(DMS-9504974, DMS-9803599, CCR-0203270)}, and a grant from\n\
140 @nospell{Sandia} National Lab.\n\
141 See @url{http://www.cise.ufl.edu/research/sparse} for\n\
142 ccolamd, csymamd, amd, colamd, symamd, and other related orderings.\n\
143 @seealso{colamd, csymamd}\n\
144 @end deftypefn")
145 {
146  octave_value_list retval;
147 
148 #ifdef HAVE_CCOLAMD
149 
150  int nargin = args.length ();
151  int spumoni = 0;
152 
153  if (nargout > 2 || nargin < 1 || nargin > 3)
154  usage ("ccolamd: incorrect number of input and/or output arguments");
155  else
156  {
157  // Get knobs
158  OCTAVE_LOCAL_BUFFER (double, knobs, CCOLAMD_KNOBS);
159  CCOLAMD_NAME (_set_defaults) (knobs);
160 
161  // Check for user-passed knobs
162  if (nargin > 1)
163  {
164  NDArray User_knobs = args(1).array_value ();
165  int nel_User_knobs = User_knobs.length ();
166 
167  if (nel_User_knobs > 0)
168  knobs[CCOLAMD_LU] = (User_knobs(0) != 0);
169  if (nel_User_knobs > 1)
170  knobs[CCOLAMD_DENSE_ROW] = User_knobs(1);
171  if (nel_User_knobs > 2)
172  knobs[CCOLAMD_DENSE_COL] = User_knobs(2);
173  if (nel_User_knobs > 3)
174  knobs[CCOLAMD_AGGRESSIVE] = (User_knobs(3) != 0);
175  if (nel_User_knobs > 4)
176  spumoni = (User_knobs(4) != 0);
177 
178  // print knob settings if spumoni is set
179  if (spumoni)
180  {
181  octave_stdout << "\nccolamd version " << CCOLAMD_MAIN_VERSION << "."
182  << CCOLAMD_SUB_VERSION << ", " << CCOLAMD_DATE
183  << ":\nknobs(1): " << User_knobs(0) << ", order for ";
184  if (knobs[CCOLAMD_LU] != 0)
185  octave_stdout << "lu (A)\n";
186  else
187  octave_stdout << "chol (A'*A)\n";
188 
189  if (knobs[CCOLAMD_DENSE_ROW] >= 0)
190  octave_stdout << "knobs(2): " << User_knobs(1)
191  << ", rows with > max (16,"
192  << knobs[CCOLAMD_DENSE_ROW]
193  << "*sqrt (size(A,2)))"
194  << " entries removed\n";
195  else
196  octave_stdout << "knobs(2): " << User_knobs(1)
197  << ", no dense rows removed\n";
198 
199  if (knobs[CCOLAMD_DENSE_COL] >= 0)
200  octave_stdout << "knobs(3): " << User_knobs(2)
201  << ", cols with > max (16,"
202  << knobs[CCOLAMD_DENSE_COL] << "*sqrt (size(A)))"
203  << " entries removed\n";
204  else
205  octave_stdout << "knobs(3): " << User_knobs(2)
206  << ", no dense columns removed\n";
207 
208  if (knobs[CCOLAMD_AGGRESSIVE] != 0)
209  octave_stdout << "knobs(4): " << User_knobs(3)
210  << ", aggressive absorption: yes";
211  else
212  octave_stdout << "knobs(4): " << User_knobs(3)
213  << ", aggressive absorption: no";
214 
215  octave_stdout << "knobs(5): " << User_knobs(4)
216  << ", statistics and knobs printed\n";
217  }
218  }
219 
220  octave_idx_type n_row, n_col, nnz;
221  octave_idx_type *ridx, *cidx;
223  SparseMatrix sm;
224 
225  if (args(0).is_sparse_type ())
226  {
227  if (args(0).is_complex_type ())
228  {
229  scm = args(0). sparse_complex_matrix_value ();
230  n_row = scm.rows ();
231  n_col = scm.cols ();
232  nnz = scm.nnz ();
233  ridx = scm.xridx ();
234  cidx = scm.xcidx ();
235  }
236  else
237  {
238  sm = args(0).sparse_matrix_value ();
239 
240  n_row = sm.rows ();
241  n_col = sm.cols ();
242  nnz = sm.nnz ();
243  ridx = sm.xridx ();
244  cidx = sm.xcidx ();
245  }
246  }
247  else
248  {
249  if (args(0).is_complex_type ())
250  sm = SparseMatrix (real (args(0).complex_matrix_value ()));
251  else
252  sm = SparseMatrix (args(0).matrix_value ());
253 
254  n_row = sm.rows ();
255  n_col = sm.cols ();
256  nnz = sm.nnz ();
257  ridx = sm.xridx ();
258  cidx = sm.xcidx ();
259  }
260 
261  // Allocate workspace for ccolamd
262  OCTAVE_LOCAL_BUFFER (octave_idx_type, p, n_col+1);
263  for (octave_idx_type i = 0; i < n_col+1; i++)
264  p[i] = cidx[i];
265 
266  octave_idx_type Alen = CCOLAMD_NAME (_recommended) (nnz, n_row, n_col);
268  for (octave_idx_type i = 0; i < nnz; i++)
269  A[i] = ridx[i];
270 
271  OCTAVE_LOCAL_BUFFER (octave_idx_type, stats, CCOLAMD_STATS);
272 
273  if (nargin > 2)
274  {
275  NDArray in_cmember = args(2).array_value ();
276  octave_idx_type cslen = in_cmember.length ();
277  OCTAVE_LOCAL_BUFFER (octave_idx_type, cmember, cslen);
278  for (octave_idx_type i = 0; i < cslen; i++)
279  // convert cmember from 1-based to 0-based
280  cmember[i] = static_cast<octave_idx_type>(in_cmember(i) - 1);
281 
282  if (cslen != n_col)
283  error ("ccolamd: CMEMBER must be of length equal to #cols of A");
284  else
285  // Order the columns (destroys A)
286  if (! CCOLAMD_NAME () (n_row, n_col, Alen, A, p,
287  knobs, stats, cmember))
288  {
289  CCOLAMD_NAME (_report) (stats) ;
290  error ("ccolamd: internal error!");
291  return retval;
292  }
293  }
294  else
295  {
296  // Order the columns (destroys A)
297  if (! CCOLAMD_NAME () (n_row, n_col, Alen, A, p, knobs, stats, 0))
298  {
299  CCOLAMD_NAME (_report) (stats) ;
300  error ("ccolamd: internal error!");
301  return retval;
302  }
303  }
304 
305  // return the permutation vector
306  NDArray out_perm (dim_vector (1, n_col));
307  for (octave_idx_type i = 0; i < n_col; i++)
308  out_perm(i) = p[i] + 1;
309 
310  retval(0) = out_perm;
311 
312  // print stats if spumoni > 0
313  if (spumoni > 0)
314  CCOLAMD_NAME (_report) (stats) ;
315 
316  // Return the stats vector
317  if (nargout == 2)
318  {
319  NDArray out_stats (dim_vector (1, CCOLAMD_STATS));
320  for (octave_idx_type i = 0 ; i < CCOLAMD_STATS ; i++)
321  out_stats(i) = stats[i] ;
322  retval(1) = out_stats;
323 
324  // fix stats (5) and (6), for 1-based information on
325  // jumbled matrix. note that this correction doesn't
326  // occur if symamd returns FALSE
327  out_stats (CCOLAMD_INFO1) ++ ;
328  out_stats (CCOLAMD_INFO2) ++ ;
329  }
330  }
331 
332 #else
333 
334  error ("ccolamd: not available in this version of Octave");
335 
336 #endif
337 
338  return retval;
339 }
340 
341 DEFUN_DLD (csymamd, args, nargout,
342  "-*- texinfo -*-\n\
343 @deftypefn {Loadable Function} {@var{p} =} csymamd (@var{S})\n\
344 @deftypefnx {Loadable Function} {@var{p} =} csymamd (@var{S}, @var{knobs})\n\
345 @deftypefnx {Loadable Function} {@var{p} =} csymamd (@var{S}, @var{knobs}, @var{cmember})\n\
346 @deftypefnx {Loadable Function} {[@var{p}, @var{stats}] =} csymamd (@dots{})\n\
347 \n\
348 For a symmetric positive definite matrix @var{S}, return the permutation\n\
349 vector @var{p} such that @code{@var{S}(@var{p},@var{p})} tends to have a\n\
350 sparser Cholesky@tie{}factor than @var{S}.\n\
351 \n\
352 Sometimes @code{csymamd} works well for symmetric indefinite matrices too. \n\
353 The matrix @var{S} is assumed to be symmetric; only the strictly lower\n\
354 triangular part is referenced. @var{S} must be square. The ordering is\n\
355 followed by an elimination tree post-ordering.\n\
356 \n\
357 @var{knobs} is an optional 1-element to 3-element input vector, with a\n\
358 default value of @code{[10 1 0]}. Entries not present are set to their\n\
359 defaults.\n\
360 \n\
361 @table @code\n\
362 @item @var{knobs}(1)\n\
363 If @var{S} is n-by-n, then rows and columns with more than\n\
364 @code{max(16,@var{knobs}(1)*sqrt(n))} entries are ignored, and ordered\n\
365 last in the output permutation (subject to the cmember constraints).\n\
366 \n\
367 @item @var{knobs}(2)\n\
368 If nonzero, aggressive absorption is performed.\n\
369 \n\
370 @item @var{knobs}(3)\n\
371 If nonzero, statistics and knobs are printed.\n\
372 \n\
373 @end table\n\
374 \n\
375 @var{cmember} is an optional vector of length n. It defines the constraints\n\
376 on the ordering. If @code{@var{cmember}(j) = @var{S}}, then row/column j is\n\
377 in constraint set @var{c} (@var{c} must be in the range 1 to n). In the\n\
378 output permutation @var{p}, rows/columns in set 1 appear first, followed\n\
379 by all rows/columns in set 2, and so on. @code{@var{cmember} = ones (1,n)}\n\
380 if not present or empty. @code{csymamd (@var{S},[],1:n)} returns @code{1:n}.\n\
381 \n\
382 @code{@var{p} = csymamd (@var{S})} is about the same as\n\
383 @code{@var{p} = symamd (@var{S})}. @var{knobs} and its default values\n\
384 differ.\n\
385 \n\
386 @code{@var{stats}(4:7)} provide information if CCOLAMD was able to\n\
387 continue. The matrix is OK if @code{@var{stats}(4)} is zero, or 1 if\n\
388 invalid. @code{@var{stats}(5)} is the rightmost column index that is\n\
389 unsorted or contains duplicate entries, or zero if no such column exists.\n\
390 @code{@var{stats}(6)} is the last seen duplicate or out-of-order row\n\
391 index in the column index given by @code{@var{stats}(5)}, or zero if no\n\
392 such row index exists. @code{@var{stats}(7)} is the number of duplicate\n\
393 or out-of-order row indices. @code{@var{stats}(8:20)} is always zero in\n\
394 the current version of @sc{ccolamd} (reserved for future use).\n\
395 \n\
396 The authors of the code itself are @nospell{S. Larimore, T. Davis}\n\
397 (Univ. of Florida) and @nospell{S. Rajamanickam} in collaboration with\n\
398 @nospell{J. Bilbert and E. Ng}. Supported by the National Science Foundation\n\
399 @nospell{(DMS-9504974, DMS-9803599, CCR-0203270)}, and a grant from\n\
400 @nospell{Sandia} National Lab.\n\
401 See @url{http://www.cise.ufl.edu/research/sparse} for\n\
402 ccolamd, csymamd, amd, colamd, symamd, and other related orderings.\n\
403 @seealso{symamd, ccolamd}\n\
404 @end deftypefn")
405 {
406  octave_value_list retval;
407 
408 #if HAVE_CCOLAMD
409 
410  int nargin = args.length ();
411  int spumoni = 0;
412 
413  if (nargout > 2 || nargin < 1 || nargin > 3)
414  usage ("ccolamd: incorrect number of input and/or output arguments");
415  else
416  {
417  // Get knobs
418  OCTAVE_LOCAL_BUFFER (double, knobs, CCOLAMD_KNOBS);
419  CCOLAMD_NAME (_set_defaults) (knobs);
420 
421  // Check for user-passed knobs
422  if (nargin > 1)
423  {
424  NDArray User_knobs = args(1).array_value ();
425  int nel_User_knobs = User_knobs.length ();
426 
427  if (nel_User_knobs > 0)
428  knobs[CCOLAMD_DENSE_ROW] = User_knobs(0);
429  if (nel_User_knobs > 0)
430  knobs[CCOLAMD_AGGRESSIVE] = User_knobs(1);
431  if (nel_User_knobs > 1)
432  spumoni = static_cast<int> (User_knobs(2));
433 
434  // print knob settings if spumoni is set
435  if (spumoni)
436  {
437  octave_stdout << "\ncsymamd version " << CCOLAMD_MAIN_VERSION
438  << "." << CCOLAMD_SUB_VERSION
439  << ", " << CCOLAMD_DATE << "\n";
440 
441  if (knobs[CCOLAMD_DENSE_ROW] >= 0)
442  octave_stdout << "knobs(1): " << User_knobs(0)
443  << ", rows/cols with > max (16,"
444  << knobs[CCOLAMD_DENSE_ROW]
445  << "*sqrt (size(A,2)))"
446  << " entries removed\n";
447  else
448  octave_stdout << "knobs(1): " << User_knobs(0)
449  << ", no dense rows/cols removed\n";
450 
451  if (knobs[CCOLAMD_AGGRESSIVE] != 0)
452  octave_stdout << "knobs(2): " << User_knobs(1)
453  << ", aggressive absorption: yes";
454  else
455  octave_stdout << "knobs(2): " << User_knobs(1)
456  << ", aggressive absorption: no";
457 
458 
459  octave_stdout << "knobs(3): " << User_knobs(2)
460  << ", statistics and knobs printed\n";
461  }
462  }
463 
464  octave_idx_type n_row, n_col;
465  octave_idx_type *ridx, *cidx;
466  SparseMatrix sm;
468 
469  if (args(0).is_sparse_type ())
470  {
471  if (args(0).is_complex_type ())
472  {
473  scm = args(0).sparse_complex_matrix_value ();
474  n_row = scm.rows ();
475  n_col = scm.cols ();
476  ridx = scm.xridx ();
477  cidx = scm.xcidx ();
478  }
479  else
480  {
481  sm = args(0).sparse_matrix_value ();
482  n_row = sm.rows ();
483  n_col = sm.cols ();
484  ridx = sm.xridx ();
485  cidx = sm.xcidx ();
486  }
487  }
488  else
489  {
490  if (args(0).is_complex_type ())
491  sm = SparseMatrix (real (args(0).complex_matrix_value ()));
492  else
493  sm = SparseMatrix (args(0).matrix_value ());
494 
495  n_row = sm.rows ();
496  n_col = sm.cols ();
497  ridx = sm.xridx ();
498  cidx = sm.xcidx ();
499  }
500 
501  if (n_row != n_col)
502  {
503  error ("csymamd: matrix S must be square");
504  return retval;
505  }
506 
507  // Allocate workspace for symamd
508  OCTAVE_LOCAL_BUFFER (octave_idx_type, perm, n_col+1);
509  OCTAVE_LOCAL_BUFFER (octave_idx_type, stats, CCOLAMD_STATS);
510 
511  if (nargin > 2)
512  {
513  NDArray in_cmember = args(2).array_value ();
514  octave_idx_type cslen = in_cmember.length ();
515  OCTAVE_LOCAL_BUFFER (octave_idx_type, cmember, cslen);
516  for (octave_idx_type i = 0; i < cslen; i++)
517  // convert cmember from 1-based to 0-based
518  cmember[i] = static_cast<octave_idx_type>(in_cmember(i) - 1);
519 
520  if (cslen != n_col)
521  error ("csymamd: CMEMBER must be of length equal to #cols of A");
522  else if (!CSYMAMD_NAME () (n_col, ridx, cidx, perm, knobs, stats,
523  &calloc, &free, cmember, -1))
524  {
525  CSYMAMD_NAME (_report) (stats) ;
526  error ("csymamd: internal error!") ;
527  return retval;
528  }
529  }
530  else
531  {
532  if (!CSYMAMD_NAME () (n_col, ridx, cidx, perm, knobs, stats,
533  &calloc, &free, 0, -1))
534  {
535  CSYMAMD_NAME (_report) (stats) ;
536  error ("csymamd: internal error!") ;
537  return retval;
538  }
539  }
540 
541  // return the permutation vector
542  NDArray out_perm (dim_vector (1, n_col));
543  for (octave_idx_type i = 0; i < n_col; i++)
544  out_perm(i) = perm[i] + 1;
545 
546  retval(0) = out_perm;
547 
548  // Return the stats vector
549  if (nargout == 2)
550  {
551  NDArray out_stats (dim_vector (1, CCOLAMD_STATS));
552  for (octave_idx_type i = 0 ; i < CCOLAMD_STATS ; i++)
553  out_stats(i) = stats[i] ;
554  retval(1) = out_stats;
555 
556  // fix stats (5) and (6), for 1-based information on
557  // jumbled matrix. note that this correction doesn't
558  // occur if symamd returns FALSE
559  out_stats (CCOLAMD_INFO1) ++ ;
560  out_stats (CCOLAMD_INFO2) ++ ;
561  }
562 
563  // print stats if spumoni > 0
564  if (spumoni > 0)
565  CSYMAMD_NAME (_report) (stats) ;
566 
567  // Return the stats vector
568  if (nargout == 2)
569  {
570  NDArray out_stats (dim_vector (1, CCOLAMD_STATS));
571  for (octave_idx_type i = 0 ; i < CCOLAMD_STATS ; i++)
572  out_stats(i) = stats[i] ;
573  retval(1) = out_stats;
574 
575  // fix stats (5) and (6), for 1-based information on
576  // jumbled matrix. note that this correction doesn't
577  // occur if symamd returns FALSE
578  out_stats (CCOLAMD_INFO1) ++ ;
579  out_stats (CCOLAMD_INFO2) ++ ;
580  }
581  }
582 
583 #else
584 
585  error ("csymamd: not available in this version of Octave");
586 
587 #endif
588 
589  return retval;
590 }
octave_idx_type * xridx(void)
Definition: Sparse.h:524
octave_idx_type cols(void) const
Definition: Sparse.h:264
octave_idx_type rows(void) const
Definition: Sparse.h:263
octave_idx_type length(void) const
Definition: oct-obj.h:89
F77_RET_T const octave_idx_type Complex * A
Definition: CmplxGEPBAL.cc:39
octave_idx_type * xcidx(void)
Definition: Sparse.h:537
void error(const char *fmt,...)
Definition: error.cc:476
void usage(const char *fmt,...)
Definition: error.cc:418
octave_idx_type nnz(void) const
Definition: Sparse.h:248
#define CSYMAMD_NAME(name)
Definition: ccolamd.cc:51
octave_idx_type length(void) const
Number of elements in the array.
Definition: Array.h:267
#define octave_stdout
Definition: pager.h:144
void free(void *)
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:197
#define DEFUN_DLD(name, args_name, nargout_name, doc)
Definition: defun-dld.h:59
ColumnVector real(const ComplexColumnVector &a)
Definition: dColVector.cc:156
#define CCOLAMD_NAME(name)
Definition: ccolamd.cc:50