GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
PermMatrix.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2008-2024 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 "PermMatrix.h"
31 #include "idx-vector.h"
32 #include "Array-util.h"
33 #include "oct-locbuf.h"
34 
35 OCTAVE_NORETURN static
36 void
37 err_invalid_permutation ()
38 {
39  (*current_liboctave_error_handler) ("PermMatrix: invalid permutation vector");
40 }
41 
42 void
43 PermMatrix::setup (const Array<octave_idx_type>& p, bool colp, bool check)
44 {
45  if (check)
46  {
47  if (! octave::idx_vector (p).is_permutation (p.numel ()))
48  err_invalid_permutation ();
49  }
50 
51  if (! colp)
52  *this = this->transpose ();
53 }
54 
55 PermMatrix::PermMatrix (const Array<octave_idx_type>& p, bool colp, bool check)
56  : Array<octave_idx_type> (p)
57 {
58  setup (p, colp, check);
59 }
60 
61 void
62 PermMatrix::setup (const octave::idx_vector& idx, bool colp, octave_idx_type n)
63 {
64  octave_idx_type len = idx.length (n);
65 
66  if (! idx.is_permutation (len))
67  err_invalid_permutation ();
68 
70  for (octave_idx_type i = 0; i < len; i++) idxa(i) = idx(i);
72 
73  if (! colp)
74  *this = this->transpose ();
75 }
76 
79 {
80  setup (idx, colp, n);
81 }
82 
85 {
86  for (octave_idx_type i = 0; i < n; i++)
87  xelem (i) = i;
88 }
89 
92 {
94  if (i < 0 || j < 0 || i > len || j > len)
95  (*current_liboctave_error_handler) ("index out of range");
96 
97  return elem (i, j);
98 }
99 
102 {
104 
105  PermMatrix retval (len);
106 
107  for (octave_idx_type i = 0; i < len; ++i)
108  retval.xelem (xelem (i)) = i;
109 
110  return retval;
111 }
112 
115 {
116  return transpose ();
117 }
118 
121 {
122  // Determine the sign of a permutation in linear time.
123  // Is this widely known?
124 
126  const octave_idx_type *pa = data ();
127 
130 
131  for (octave_idx_type i = 0; i < len; i++)
132  {
133  p[i] = pa[i];
134  q[p[i]] = i;
135  }
136 
137  bool neg = false;
138 
139  for (octave_idx_type i = 0; i < len; i++)
140  {
141  octave_idx_type j = p[i];
142  octave_idx_type k = q[i];
143  if (j != i)
144  {
145  p[k] = p[i];
146  q[j] = q[i];
147  neg = ! neg;
148  }
149  }
150 
151  return neg ? -1 : 1;
152 }
153 
156 {
157  if (m < 0)
158  return inverse ().pos_power (-m);
159  else if (m > 0)
160  return pos_power (m);
161  else
162  return PermMatrix (rows ());
163 }
164 
166 PermMatrix::pos_power (octave_idx_type m) const
167 {
168  octave_idx_type n = rows ();
169 
170  const octave_idx_type *p = data ();
171  Array<octave_idx_type> res_pvec (dim_vector (n, 1), -1);
172  octave_idx_type *q = res_pvec.fortran_vec ();
173 
174  for (octave_idx_type ics = 0; ics < n; ics++)
175  {
176  if (q[ics] > 0)
177  continue;
178 
179  // go forward m steps or until a cycle is found.
180  octave_idx_type ic, j;
181  for (j = 1, ic = p[ics]; j != m && ic != ics; j++, ic = p[ic]) ;
182  if (ic == ics)
183  {
184  // reduce power.
185  octave_idx_type mm = m % j;
186  // go forward mm steps.
187  for (j = 0, ic = ics; j != mm; j++, ic = p[ic]) ;
188  }
189 
190  // now ic = p^m[ics]. Loop through the whole cycle.
191  octave_idx_type jcs = ics;
192  do
193  {
194  q[jcs] = ic;
195  jcs = p[jcs]; ic = p[ic];
196  }
197  while (jcs != ics);
198 
199  }
200 
201  return PermMatrix (res_pvec, true, false);
202 }
203 
206 {
207  return PermMatrix (n);
208 }
209 
211 operator *(const PermMatrix& a, const PermMatrix& b)
212 {
213  PermMatrix r;
214 
215  const Array<octave_idx_type> ia = a.col_perm_vec ();
216  const Array<octave_idx_type> ib = b.col_perm_vec ();
217 
218  octave_idx_type n = a.columns ();
219 
220  if (n != b.rows ())
221  octave::err_nonconformant ("operator *", n, n, b.rows (), b.rows ());
222 
223  r = PermMatrix (ia.index (octave::idx_vector (ib)), true, false);
224 
225  return r;
226 }
PermMatrix operator*(const PermMatrix &a, const PermMatrix &b)
Definition: PermMatrix.cc:211
Array< T, Alloc > index(const octave::idx_vector &i) const
Indexing without resizing.
Definition: Array-base.cc:710
const octave_idx_type * data() const
Definition: Array.h:663
Array< T, Alloc > & operator=(const Array< T, Alloc > &a)
Definition: Array.h:361
octave_idx_type & xelem(octave_idx_type n)
Definition: Array.h:524
octave_idx_type numel() const
Number of elements in the array.
Definition: Array.h:414
octave_idx_type elem(octave_idx_type i, octave_idx_type j) const
Definition: PermMatrix.h:87
octave_idx_type rows() const
Definition: PermMatrix.h:62
octave_idx_type checkelem(octave_idx_type i, octave_idx_type j) const
Definition: PermMatrix.cc:91
PermMatrix()=default
PermMatrix inverse() const
Definition: PermMatrix.cc:114
const Array< octave_idx_type > & col_perm_vec() const
Definition: PermMatrix.h:83
static PermMatrix eye(octave_idx_type n)
Definition: PermMatrix.cc:205
octave_idx_type perm_length() const
Definition: PermMatrix.h:66
octave_idx_type columns() const
Definition: PermMatrix.h:64
octave_idx_type determinant() const
Definition: PermMatrix.cc:120
PermMatrix power(octave_idx_type n) const
Definition: PermMatrix.cc:155
PermMatrix transpose() const
Definition: PermMatrix.cc:101
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:94
octave::idx_vector idx_vector
Definition: idx-vector.h:1022
void err_nonconformant(const char *op, octave_idx_type op1_len, octave_idx_type op2_len)
T octave_idx_type m
Definition: mx-inlines.cc:781
octave_idx_type n
Definition: mx-inlines.cc:761
T * r
Definition: mx-inlines.cc:781
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:44
F77_RET_T len
Definition: xerbla.cc:61