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 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027
00028 #include "defun-dld.h"
00029 #include "error.h"
00030 #include "gripes.h"
00031 #include "oct-obj.h"
00032 #include "utils.h"
00033
00034 #include "oct-sparse.h"
00035 #include "ov-re-sparse.h"
00036 #include "ov-cx-sparse.h"
00037 #include "SparseQR.h"
00038 #include "SparseCmplxQR.h"
00039
00040 #ifdef IDX_TYPE_LONG
00041 #define CXSPARSE_NAME(name) cs_dl ## name
00042 #else
00043 #define CXSPARSE_NAME(name) cs_di ## name
00044 #endif
00045
00046 static RowVector
00047 put_int (octave_idx_type *p, octave_idx_type n)
00048 {
00049 RowVector ret (n);
00050 for (octave_idx_type i = 0; i < n; i++)
00051 ret.xelem(i) = p[i] + 1;
00052 return ret;
00053 }
00054
00055 #if HAVE_CXSPARSE
00056 static octave_value_list
00057 dmperm_internal (bool rank, const octave_value arg, int nargout)
00058 {
00059 octave_value_list retval;
00060 octave_idx_type nr = arg.rows ();
00061 octave_idx_type nc = arg.columns ();
00062 SparseMatrix m;
00063 SparseComplexMatrix cm;
00064 CXSPARSE_NAME () csm;
00065 csm.m = nr;
00066 csm.n = nc;
00067 csm.x = 0;
00068 csm.nz = -1;
00069
00070 if (arg.is_real_type ())
00071 {
00072 m = arg.sparse_matrix_value ();
00073 csm.nzmax = m.nnz();
00074 csm.p = m.xcidx ();
00075 csm.i = m.xridx ();
00076 }
00077 else
00078 {
00079 cm = arg.sparse_complex_matrix_value ();
00080 csm.nzmax = cm.nnz();
00081 csm.p = cm.xcidx ();
00082 csm.i = cm.xridx ();
00083 }
00084
00085 if (!error_state)
00086 {
00087 if (nargout <= 1 || rank)
00088 {
00089 #if defined(CS_VER) && (CS_VER >= 2)
00090 octave_idx_type *jmatch = CXSPARSE_NAME (_maxtrans) (&csm, 0);
00091 #else
00092 octave_idx_type *jmatch = CXSPARSE_NAME (_maxtrans) (&csm);
00093 #endif
00094 if (rank)
00095 {
00096 octave_idx_type r = 0;
00097 for (octave_idx_type i = 0; i < nc; i++)
00098 if (jmatch[nr+i] >= 0)
00099 r++;
00100 retval(0) = static_cast<double>(r);
00101 }
00102 else
00103 retval(0) = put_int (jmatch + nr, nc);
00104 CXSPARSE_NAME (_free) (jmatch);
00105 }
00106 else
00107 {
00108 #if defined(CS_VER) && (CS_VER >= 2)
00109 CXSPARSE_NAME (d) *dm = CXSPARSE_NAME(_dmperm) (&csm, 0);
00110 #else
00111 CXSPARSE_NAME (d) *dm = CXSPARSE_NAME(_dmperm) (&csm);
00112 #endif
00113
00114
00115
00116 #if defined(CS_VER) && (CS_VER >= 2)
00117 retval(3) = put_int (dm->s, dm->nb+1);
00118 retval(2) = put_int (dm->r, dm->nb+1);
00119 retval(1) = put_int (dm->q, nc);
00120 retval(0) = put_int (dm->p, nr);
00121 #else
00122 retval(3) = put_int (dm->S, dm->nb+1);
00123 retval(2) = put_int (dm->R, dm->nb+1);
00124 retval(1) = put_int (dm->Q, nc);
00125 retval(0) = put_int (dm->P, nr);
00126 #endif
00127 CXSPARSE_NAME (_dfree) (dm);
00128 }
00129 }
00130 return retval;
00131 }
00132 #endif
00133
00134 DEFUN_DLD (dmperm, args, nargout,
00135 "-*- texinfo -*-\n\
00136 @deftypefn {Loadable Function} {@var{p} =} dmperm (@var{S})\n\
00137 @deftypefnx {Loadable Function} {[@var{p}, @var{q}, @var{r}, @var{S}] =} dmperm (@var{S})\n\
00138 \n\
00139 @cindex Dulmage-Mendelsohn decomposition\n\
00140 Perform a Dulmage-Mendelsohn permutation of the sparse matrix @var{S}.\n\
00141 With a single output argument @code{dmperm} performs the row permutations\n\
00142 @var{p} such that @code{@var{S}(@var{p},:)} has no zero elements on the\n\
00143 diagonal.\n\
00144 \n\
00145 Called with two or more output arguments, returns the row and column\n\
00146 permutations, such that @code{@var{S}(@var{p}, @var{q})} is in block\n\
00147 triangular form. The values of @var{r} and @var{S} define the boundaries\n\
00148 of the blocks. If @var{S} is square then @code{@var{r} == @var{S}}.\n\
00149 \n\
00150 The method used is described in: A. Pothen & C.-J. Fan. @cite{Computing the\n\
00151 Block Triangular Form of a Sparse Matrix}. ACM Trans. Math. Software,\n\
00152 16(4):303-324, 1990.\n\
00153 @seealso{colamd, ccolamd}\n\
00154 @end deftypefn")
00155 {
00156 int nargin = args.length();
00157 octave_value_list retval;
00158
00159 if (nargin != 1)
00160 {
00161 print_usage ();
00162 return retval;
00163 }
00164
00165 #if HAVE_CXSPARSE
00166 retval = dmperm_internal (false, args(0), nargout);
00167 #else
00168 error ("dmperm: not available in this version of Octave");
00169 #endif
00170
00171 return retval;
00172 }
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 DEFUN_DLD (sprank, args, nargout,
00192 "-*- texinfo -*-\n\
00193 @deftypefn {Loadable Function} {@var{p} =} sprank (@var{S})\n\
00194 @cindex structural rank\n\
00195 \n\
00196 Calculate the structural rank of the sparse matrix @var{S}. Note that\n\
00197 only the structure of the matrix is used in this calculation based on\n\
00198 a Dulmage-Mendelsohn permutation to block triangular form. As such the\n\
00199 numerical rank of the matrix @var{S} is bounded by\n\
00200 @code{sprank (@var{S}) >= rank (@var{S})}. Ignoring floating point errors\n\
00201 @code{sprank (@var{S}) == rank (@var{S})}.\n\
00202 @seealso{dmperm}\n\
00203 @end deftypefn")
00204 {
00205 int nargin = args.length();
00206 octave_value_list retval;
00207
00208 if (nargin != 1)
00209 {
00210 print_usage ();
00211 return retval;
00212 }
00213
00214 #if HAVE_CXSPARSE
00215 retval = dmperm_internal (true, args(0), nargout);
00216 #else
00217 error ("sprank: not available in this version of Octave");
00218 #endif
00219
00220 return retval;
00221 }
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231