GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
dmperm.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2005-2018 David Bateman
4 Copyright (C) 1998-2005 Andy Adler
5 
6 This file is part of Octave.
7 
8 Octave is free software: you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see
20 <https://www.gnu.org/licenses/>.
21 
22 */
23 
24 #if defined (HAVE_CONFIG_H)
25 # include "config.h"
26 #endif
27 
28 #include "CSparse.h"
29 #include "dRowVector.h"
30 #include "dSparse.h"
31 #include "oct-sparse.h"
32 
33 #include "defun-dld.h"
34 #include "errwarn.h"
35 #include "ov.h"
36 #include "ovl.h"
37 #include "utils.h"
38 
39 #if defined (OCTAVE_ENABLE_64)
40 # define CXSPARSE_NAME(name) cs_dl ## name
41 #else
42 # define CXSPARSE_NAME(name) cs_di ## name
43 #endif
44 
45 #if defined (HAVE_CXSPARSE)
46 
47 static RowVector
49 {
50  RowVector ret (n);
51  for (octave_idx_type i = 0; i < n; i++)
52  ret.xelem (i) = p[i] + 1;
53  return ret;
54 }
55 
56 static octave_value_list
57 dmperm_internal (bool rank, const octave_value arg, int nargout)
58 {
60  octave_idx_type nr = arg.rows ();
61  octave_idx_type nc = arg.columns ();
62  SparseMatrix m;
64  CXSPARSE_NAME () csm;
65  csm.m = nr;
66  csm.n = nc;
67  csm.x = nullptr;
68  csm.nz = -1;
69 
70  if (arg.isreal ())
71  {
72  m = arg.sparse_matrix_value ();
73  csm.nzmax = m.nnz ();
74  csm.p = octave::to_suitesparse_intptr (m.xcidx ());
75  csm.i = octave::to_suitesparse_intptr (m.xridx ());
76  }
77  else
78  {
80  csm.nzmax = cm.nnz ();
81  csm.p = octave::to_suitesparse_intptr (cm.xcidx ());
82  csm.i = octave::to_suitesparse_intptr (cm.xridx ());
83  }
84 
85  if (nargout <= 1 || rank)
86  {
87  octave::suitesparse_integer *jmatch = CXSPARSE_NAME (_maxtrans) (&csm, 0);
88  if (rank)
89  {
90  octave_idx_type r = 0;
91  for (octave_idx_type i = 0; i < nc; i++)
92  if (jmatch[nr+i] >= 0)
93  r++;
94  retval(0) = static_cast<double>(r);
95  }
96  else
97  retval(0) = put_int (jmatch + nr, nc);
98  CXSPARSE_NAME (_free) (jmatch);
99  }
100  else
101  {
102  CXSPARSE_NAME (d) *dm = CXSPARSE_NAME(_dmperm) (&csm, 0);
103 
104  //retval(5) = put_int (dm->rr, 5);
105  //retval(4) = put_int (dm->cc, 5);
106  retval = ovl (put_int (dm->p, nr), put_int (dm->q, nc),
107  put_int (dm->r, dm->nb+1), put_int (dm->s, dm->nb+1));
108 
109  CXSPARSE_NAME (_dfree) (dm);
110  }
111 
112  return retval;
113 }
114 
115 #endif
116 
117 DEFUN_DLD (dmperm, args, nargout,
118  doc: /* -*- texinfo -*-
119 @deftypefn {} {@var{p} =} dmperm (@var{S})
120 @deftypefnx {} {[@var{p}, @var{q}, @var{r}, @var{S}] =} dmperm (@var{S})
121 
122 @cindex @nospell{Dulmage-Mendelsohn} decomposition
123 Perform a @nospell{Dulmage-Mendelsohn} permutation of the sparse matrix
124 @var{S}.
125 
126 With a single output argument @code{dmperm} performs the row permutations
127 @var{p} such that @code{@var{S}(@var{p},:)} has no zero elements on the
128 diagonal.
129 
130 Called with two or more output arguments, returns the row and column
131 permutations, such that @code{@var{S}(@var{p}, @var{q})} is in block
132 triangular form. The values of @var{r} and @var{S} define the boundaries
133 of the blocks. If @var{S} is square then @code{@var{r} == @var{S}}.
134 
135 The method used is described in: @nospell{A. Pothen & C.-J. Fan.}
136 @cite{Computing the Block Triangular Form of a Sparse Matrix}.
137 @nospell{ACM} Trans. Math. Software, 16(4):303-324, 1990.
138 @seealso{colamd, ccolamd}
139 @end deftypefn */)
140 {
141 #if defined (HAVE_CXSPARSE)
142 
143  if (args.length () != 1)
144  print_usage ();
145 
146  return dmperm_internal (false, args(0), nargout);
147 
148 #else
149 
150  octave_unused_parameter (args);
151  octave_unused_parameter (nargout);
152 
153  err_disabled_feature ("dmperm", "CXSparse");
154 
155 #endif
156 }
157 
158 /*
159 %!testif HAVE_CXSPARSE
160 %! n = 20;
161 %! a = speye (n,n);
162 %! a = a(randperm (n),:);
163 %! assert (a(dmperm (a),:), speye (n));
164 
165 %!testif HAVE_CXSPARSE
166 %! n = 20;
167 %! d = 0.2;
168 %! a = tril (sprandn (n,n,d), -1) + speye (n,n);
169 %! a = a(randperm (n), randperm (n));
170 %! [p,q,r,s] = dmperm (a);
171 %! assert (tril (a(p,q), -1), sparse (n, n));
172 */
173 
174 DEFUN_DLD (sprank, args, nargout,
175  doc: /* -*- texinfo -*-
176 @deftypefn {} {@var{p} =} sprank (@var{S})
177 @cindex structural rank
178 
179 Calculate the structural rank of the sparse matrix @var{S}.
180 
181 Note that only the structure of the matrix is used in this calculation based
182 on a @nospell{Dulmage-Mendelsohn} permutation to block triangular form. As
183 such the numerical rank of the matrix @var{S} is bounded by
184 @code{sprank (@var{S}) >= rank (@var{S})}. Ignoring floating point errors
185 @code{sprank (@var{S}) == rank (@var{S})}.
186 @seealso{dmperm}
187 @end deftypefn */)
188 {
189 #if defined (HAVE_CXSPARSE)
190 
191  if (args.length () != 1)
192  print_usage ();
193 
194  return dmperm_internal (true, args(0), nargout);
195 
196 #else
197 
198  octave_unused_parameter (args);
199  octave_unused_parameter (nargout);
200 
201  err_disabled_feature ("sprank", "CXSparse");
202 
203 #endif
204 }
205 
206 /*
207 %!testif HAVE_CXSPARSE
208 %! assert (sprank (speye (20)), 20);
209 %!testif HAVE_CXSPARSE
210 %! assert (sprank ([1,0,2,0;2,0,4,0]), 2);
211 
212 %!error sprank (1,2)
213 */
static RowVector put_int(octave::suitesparse_integer *p, octave_idx_type n)
Definition: dmperm.cc:48
OCTINTERP_API void print_usage(void)
Definition: defun.cc:54
octave_value arg
Definition: pr-output.cc:3244
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
#define CXSPARSE_NAME(name)
Definition: dmperm.cc:42
octave_idx_type nnz(void) const
Actual number of nonzero terms.
Definition: Sparse.h:240
OCTAVE_EXPORT octave_value_list return the number of command line arguments passed to Octave If called with the optional argument the function xample nargout(@histc)
Definition: ov-usr-fcn.cc:997
int suitesparse_integer
Definition: oct-sparse.h:168
octave_idx_type nzmax(void) const
Amount of storage for nonzero elements.
Definition: Sparse.h:232
octave_idx_type columns(void) const
Definition: ov.h:474
octave_idx_type rows(void) const
Definition: ov.h:472
octave_value retval
Definition: data.cc:6246
octave_idx_type * xridx(void)
Definition: Sparse.h:501
SparseComplexMatrix sparse_complex_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:885
T & xelem(octave_idx_type n)
Definition: Array.h:458
bool isreal(void) const
Definition: ov.h:703
OCTAVE_EXPORT octave_value_list isa nd deftypefn *return ovl(args(0).isinteger())
p
Definition: lu.cc:138
SparseMatrix sparse_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:881
for i
Definition: data.cc:5264
#define DEFUN_DLD(name, args_name, nargout_name, doc)
Macro to define an at run time dynamically loadable builtin function.
Definition: defun-dld.h:58
octave_idx_type * xcidx(void)
Definition: Sparse.h:514
static octave_value_list dmperm_internal(bool rank, const octave_value arg, int nargout)
Definition: dmperm.cc:57
void err_disabled_feature(const std::string &fcn, const std::string &feature, const std::string &pkg)
Definition: errwarn.cc:50
suitesparse_integer * to_suitesparse_intptr(octave_idx_type *i)
Definition: oct-sparse.cc:48