Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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 #include "oct-map.h"
00043
00044 #include "oct-sparse.h"
00045 #include "oct-locbuf.h"
00046
00047 #ifdef IDX_TYPE_LONG
00048 #define AMD_NAME(name) amd_l ## name
00049 #else
00050 #define AMD_NAME(name) amd ## name
00051 #endif
00052
00053 DEFUN_DLD (amd, args, nargout,
00054 "-*- texinfo -*-\n\
00055 @deftypefn {Loadable Function} {@var{p} =} amd (@var{S})\n\
00056 @deftypefnx {Loadable Function} {@var{p} =} amd (@var{S}, @var{opts})\n\
00057 \n\
00058 Return the approximate minimum degree permutation of a matrix. This\n\
00059 permutation such that the Cholesky@tie{}factorization of @code{@var{S}\n\
00060 (@var{p}, @var{p})} tends to be sparser than the Cholesky@tie{}factorization\n\
00061 of @var{S} itself. @code{amd} is typically faster than @code{symamd} but\n\
00062 serves a similar purpose.\n\
00063 \n\
00064 The optional parameter @var{opts} is a structure that controls the\n\
00065 behavior of @code{amd}. The fields of the structure are\n\
00066 \n\
00067 @table @asis\n\
00068 @item @var{opts}.dense\n\
00069 Determines what @code{amd} considers to be a dense row or column of the\n\
00070 input matrix. Rows or columns with more than @code{max(16, (dense *\n\
00071 sqrt (@var{n})} entries, where @var{n} is the order of the matrix @var{S},\n\
00072 are ignored by @code{amd} during the calculation of the permutation\n\
00073 The value of dense must be a positive scalar and its default value is 10.0\n\
00074 \n\
00075 @item @var{opts}.aggressive\n\
00076 If this value is a non zero scalar, then @code{amd} performs aggressive\n\
00077 absorption. The default is not to perform aggressive absorption.\n\
00078 @end table\n\
00079 \n\
00080 The author of the code itself is Timothy A. Davis\n\
00081 @email{davis@@cise.ufl.edu}, University of Florida (see\n\
00082 @url{http://www.cise.ufl.edu/research/sparse/amd}).\n\
00083 @seealso{symamd, colamd}\n\
00084 @end deftypefn")
00085 {
00086 octave_value_list retval;
00087
00088 #ifdef HAVE_AMD
00089 int nargin = args.length ();
00090
00091 if (nargin < 1 || nargin > 2)
00092 print_usage ();
00093 else
00094 {
00095 octave_idx_type n_row, n_col;
00096 const octave_idx_type *ridx, *cidx;
00097 SparseMatrix sm;
00098 SparseComplexMatrix scm;
00099
00100 if (args(0).is_sparse_type ())
00101 {
00102 if (args(0).is_complex_type ())
00103 {
00104 scm = args(0).sparse_complex_matrix_value ();
00105 n_row = scm.rows ();
00106 n_col = scm.cols ();
00107 ridx = scm.xridx ();
00108 cidx = scm.xcidx ();
00109 }
00110 else
00111 {
00112 sm = args(0).sparse_matrix_value ();
00113 n_row = sm.rows ();
00114 n_col = sm.cols ();
00115 ridx = sm.xridx ();
00116 cidx = sm.xcidx ();
00117 }
00118 }
00119 else
00120 {
00121 if (args(0).is_complex_type ())
00122 sm = SparseMatrix (real (args(0).complex_matrix_value ()));
00123 else
00124 sm = SparseMatrix (args(0).matrix_value ());
00125
00126 n_row = sm.rows ();
00127 n_col = sm.cols ();
00128 ridx = sm.xridx ();
00129 cidx = sm.xcidx ();
00130 }
00131
00132 if (!error_state && n_row != n_col)
00133 error ("amd: matrix S must be square");
00134
00135 if (!error_state)
00136 {
00137 OCTAVE_LOCAL_BUFFER (double, Control, AMD_CONTROL);
00138 AMD_NAME (_defaults) (Control) ;
00139 if (nargin > 1)
00140 {
00141 octave_scalar_map arg1 = args(1).scalar_map_value ();
00142
00143 if (!error_state)
00144 {
00145 octave_value tmp;
00146
00147 tmp = arg1.getfield ("dense");
00148 if (tmp.is_defined ())
00149 Control[AMD_DENSE] = tmp.double_value ();
00150
00151 tmp = arg1.getfield ("aggressive");
00152 if (tmp.is_defined ())
00153 Control[AMD_AGGRESSIVE] = tmp.double_value ();
00154 }
00155 else
00156 error ("amd: OPTS argument must be a scalar structure");
00157 }
00158
00159 if (!error_state)
00160 {
00161 OCTAVE_LOCAL_BUFFER (octave_idx_type, P, n_col);
00162 Matrix xinfo (AMD_INFO, 1);
00163 double *Info = xinfo.fortran_vec ();
00164
00165
00166
00167 amd_malloc = malloc;
00168 amd_free = free;
00169 amd_calloc = calloc;
00170 amd_realloc = realloc;
00171 amd_printf = printf;
00172
00173 octave_idx_type result = AMD_NAME (_order) (n_col, cidx, ridx, P,
00174 Control, Info);
00175
00176 switch (result)
00177 {
00178 case AMD_OUT_OF_MEMORY:
00179 error ("amd: out of memory");
00180 break;
00181 case AMD_INVALID:
00182 error ("amd: matrix S is corrupted");
00183 break;
00184 default:
00185 {
00186 if (nargout > 1)
00187 retval(1) = xinfo;
00188
00189 Matrix Pout (1, n_col);
00190 for (octave_idx_type i = 0; i < n_col; i++)
00191 Pout.xelem (i) = P[i] + 1;
00192
00193 retval (0) = Pout;
00194 }
00195 }
00196 }
00197 }
00198 }
00199 #else
00200
00201 error ("amd: not available in this version of Octave");
00202
00203 #endif
00204
00205 return retval;
00206 }