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