GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
PermMatrix.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2008-2018 Jaroslav Hajek
4 
5 This file is part of Octave.
6 
7 Octave is free software: you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <https://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if defined (HAVE_CONFIG_H)
24 # include "config.h"
25 #endif
26 
27 #include "PermMatrix.h"
28 #include "idx-vector.h"
29 #include "Array-util.h"
30 #include "oct-locbuf.h"
31 
32 OCTAVE_NORETURN static
33 void
35 {
36  (*current_liboctave_error_handler) ("PermMatrix: invalid permutation vector");
37 }
38 
39 void
40 PermMatrix::setup (const Array<octave_idx_type>& p, bool colp, bool check)
41 {
42  if (check)
43  {
44  if (! idx_vector (p).is_permutation (p.numel ()))
46  }
47 
48  if (! colp)
49  *this = this->transpose ();
50 }
51 
52 PermMatrix::PermMatrix (const Array<octave_idx_type>& p, bool colp, bool check)
54 {
55  setup (p, colp, check);
56 }
57 
58 void
59 PermMatrix::setup (const idx_vector& idx, bool colp, octave_idx_type n)
60 {
61  octave_idx_type len = idx.length (n);
62 
63  if (! idx.is_permutation (len))
65 
66  Array<octave_idx_type> idxa (dim_vector (len, 1));
67  for (octave_idx_type i = 0; i < len; i++) idxa(i) = idx(i);
69 
70  if (! colp)
71  *this = this->transpose ();
72 }
73 
76 {
77  setup (idx, colp, n);
78 }
79 
81  : Array<octave_idx_type> (dim_vector (n, 1))
82 {
83  for (octave_idx_type i = 0; i < n; i++)
84  xelem (i) = i;
85 }
86 
89 {
91  if (i < 0 || j < 0 || i > len || j > len)
92  (*current_liboctave_error_handler) ("index out of range");
93 
94  return elem (i, j);
95 }
96 
99 {
101 
102  PermMatrix retval (len);
103 
104  for (octave_idx_type i = 0; i < len; ++i)
105  retval.xelem (xelem (i)) = i;
106 
107  return retval;
108 }
109 
112 {
113  return transpose ();
114 }
115 
118 {
119  // Determine the sign of a permutation in linear time.
120  // Is this widely known?
121 
122  octave_idx_type len = perm_length ();
123  const octave_idx_type *pa = data ();
124 
127 
128  for (octave_idx_type i = 0; i < len; i++)
129  {
130  p[i] = pa[i];
131  q[p[i]] = i;
132  }
133 
134  bool neg = false;
135 
136  for (octave_idx_type i = 0; i < len; i++)
137  {
138  octave_idx_type j = p[i];
139  octave_idx_type k = q[i];
140  if (j != i)
141  {
142  p[k] = p[i];
143  q[j] = q[i];
144  neg = ! neg;
145  }
146  }
147 
148  return neg ? -1 : 1;
149 }
150 
153 {
154  if (m < 0)
155  return inverse ().pos_power (-m);
156  else if (m > 0)
157  return pos_power (m);
158  else
159  return PermMatrix (rows ());
160 }
161 
164 {
165  octave_idx_type n = rows ();
166 
167  const octave_idx_type *p = data ();
168  Array<octave_idx_type> res_pvec (dim_vector (n, 1), -1);
169  octave_idx_type *q = res_pvec.fortran_vec ();
170 
171  for (octave_idx_type ics = 0; ics < n; ics++)
172  {
173  if (q[ics] > 0)
174  continue;
175 
176  // go forward m steps or until a cycle is found.
177  octave_idx_type ic, j;
178  for (j = 1, ic = p[ics]; j != m && ic != ics; j++, ic = p[ic]) ;
179  if (ic == ics)
180  {
181  // reduce power.
182  octave_idx_type mm = m % j;
183  // go forward mm steps.
184  for (j = 0, ic = ics; j != mm; j++, ic = p[ic]) ;
185  }
186 
187  // now ic = p^m[ics]. Loop through the whole cycle.
188  octave_idx_type jcs = ics;
189  do
190  {
191  q[jcs] = ic;
192  jcs = p[jcs]; ic = p[ic];
193  }
194  while (jcs != ics);
195 
196  }
197 
198  return PermMatrix (res_pvec, true, false);
199 }
200 
203 {
204  return PermMatrix (n);
205 }
206 
209 {
210  PermMatrix r;
211 
212  const Array<octave_idx_type> ia = a.col_perm_vec ();
213  const Array<octave_idx_type> ib = b.col_perm_vec ();
214 
215  octave_idx_type n = a.columns ();
216 
217  if (n != b.rows ())
218  octave::err_nonconformant ("operator *", n, n, b.rows (), b.rows ());
219 
220  r = PermMatrix (ia.index (idx_vector (ib)), true, false);
221 
222  return r;
223 }
octave_idx_type rows(void) const
Definition: PermMatrix.h:53
const octave_idx_type * data(void) const
Definition: Array.h:582
for large enough k
Definition: lu.cc:617
const T * fortran_vec(void) const
Definition: Array.h:584
PermMatrix(void)
Definition: PermMatrix.h:38
octave_idx_type perm_length(void) const
Definition: PermMatrix.h:57
calling an anonymous function involves an overhead quite comparable to the overhead of an m file function Passing a handle to a built in function is because the interpreter is not involved in the internal loop For a
Definition: cellfun.cc:400
bool is_permutation(octave_idx_type n) const
Definition: idx-vector.cc:1139
PermMatrix operator*(const PermMatrix &a, const PermMatrix &b)
Definition: PermMatrix.cc:208
Array< T > index(const idx_vector &i) const
Indexing without resizing.
Definition: Array.cc:697
octave_idx_type determinant(void) const
Definition: PermMatrix.cc:117
PermMatrix inverse(void) const
Definition: PermMatrix.cc:111
void err_nonconformant(const char *op, octave_idx_type op1_len, octave_idx_type op2_len)
octave_idx_type length(octave_idx_type n=0) const
Definition: idx-vector.h:557
octave_value retval
Definition: data.cc:6246
static OCTAVE_NORETURN void err_invalid_permutation(void)
Definition: PermMatrix.cc:34
octave_idx_type & xelem(octave_idx_type n)
Definition: Array.h:458
octave_idx_type elem(octave_idx_type i, octave_idx_type j) const
Definition: PermMatrix.h:81
octave_idx_type checkelem(octave_idx_type i, octave_idx_type j) const
Definition: PermMatrix.cc:88
p
Definition: lu.cc:138
b
Definition: cellfun.cc:400
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:41
for i
Definition: data.cc:5264
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:366
static PermMatrix eye(octave_idx_type n)
Definition: PermMatrix.cc:202
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
Array< T > & operator=(const Array< T > &a)
Definition: Array.h:311
void setup(const Array< octave_idx_type > &p, bool colp, bool check)
Definition: PermMatrix.cc:40
PermMatrix transpose(void) const
Definition: PermMatrix.cc:98
PermMatrix pos_power(octave_idx_type m) const
Definition: PermMatrix.cc:163
PermMatrix power(octave_idx_type n) const
Definition: PermMatrix.cc:152