GNU Octave  4.2.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
PermMatrix.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2008-2017 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 the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 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 <http://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 
53  : Array<octave_idx_type> (p)
54 {
55  setup (p, false, true);
56 }
57 
58 PermMatrix::PermMatrix (const Array<octave_idx_type>& p, bool colp, bool check)
59  : Array<octave_idx_type> (p)
60 {
61  setup (p, colp, check);
62 }
63 
64 void
65 PermMatrix::setup (const idx_vector& idx, bool colp, octave_idx_type n)
66 {
67  octave_idx_type len = idx.length (n);
68 
69  if (! idx.is_permutation (len))
71 
72  Array<octave_idx_type> idxa (dim_vector (len, 1));
73  for (octave_idx_type i = 0; i < len; i++) idxa(i) = idx(i);
75 
76  if (! colp)
77  *this = this->transpose ();
78 }
79 
82 {
83  setup (idx, false, 0);
84 }
85 
88 {
89  setup (idx, colp, n);
90 }
91 
93  : Array<octave_idx_type> (dim_vector (n, 1))
94 {
95  for (octave_idx_type i = 0; i < n; i++)
96  xelem (i) = i;
97 }
98 
101 {
103  if (i < 0 || j < 0 || i > len || j > len)
104  (*current_liboctave_error_handler) ("index out of range");
105 
106  return elem (i, j);
107 }
108 
111 {
113 
114  PermMatrix retval (len);
115 
116  for (octave_idx_type i = 0; i < len; ++i)
117  retval.xelem (xelem (i)) = i;
118 
119  return retval;
120 }
121 
124 {
125  return transpose ();
126 }
127 
130 {
131  // Determine the sign of a permutation in linear time.
132  // Is this widely known?
133 
134  octave_idx_type len = perm_length ();
135  const octave_idx_type *pa = data ();
136 
139 
140  for (octave_idx_type i = 0; i < len; i++)
141  {
142  p[i] = pa[i];
143  q[p[i]] = i;
144  }
145 
146  bool neg = false;
147 
148  for (octave_idx_type i = 0; i < len; i++)
149  {
150  octave_idx_type j = p[i];
151  octave_idx_type k = q[i];
152  if (j != i)
153  {
154  p[k] = p[i];
155  q[j] = q[i];
156  neg = ! neg;
157  }
158  }
159 
160  return neg ? -1 : 1;
161 }
162 
165 {
166  if (m < 0)
167  return inverse ().pos_power (-m);
168  else if (m > 0)
169  return pos_power (m);
170  else
171  return PermMatrix (rows ());
172 }
173 
176 {
177  octave_idx_type n = rows ();
178 
179  const octave_idx_type *p = data ();
180  Array<octave_idx_type> res_pvec (dim_vector (n, 1), -1);
181  octave_idx_type *q = res_pvec.fortran_vec ();
182 
183  for (octave_idx_type ics = 0; ics < n; ics++)
184  {
185  if (q[ics] > 0)
186  continue;
187 
188  // go forward m steps or until a cycle is found.
189  octave_idx_type ic, j;
190  for (j = 1, ic = p[ics]; j != m && ic != ics; j++, ic = p[ic]) ;
191  if (ic == ics)
192  {
193  // reduce power.
194  octave_idx_type mm = m % j;
195  // go forward mm steps.
196  for (j = 0, ic = ics; j != mm; j++, ic = p[ic]) ;
197  }
198 
199  // now ic = p^m[ics]. Loop through the whole cycle.
200  octave_idx_type jcs = ics;
201  do
202  {
203  q[jcs] = ic;
204  jcs = p[jcs]; ic = p[ic];
205  }
206  while (jcs != ics);
207 
208  }
209 
210  return PermMatrix (res_pvec, true, false);
211 }
212 
215 {
216  return PermMatrix (n);
217 }
218 
221 {
222  PermMatrix r;
223 
224  const Array<octave_idx_type> ia = a.col_perm_vec ();
225  const Array<octave_idx_type> ib = b.col_perm_vec ();
226 
227  octave_idx_type n = a.columns ();
228 
229  if (n != b.rows ())
230  octave::err_nonconformant ("operator *", n, n, b.rows (), b.rows ());
231 
232  r = PermMatrix (ia.index (idx_vector (ib)), true, false);
233 
234  return r;
235 }
octave_idx_type length(octave_idx_type n=0) const
Definition: idx-vector.h:541
octave_idx_type rows(void) const
Definition: PermMatrix.h:59
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:363
octave_idx_type perm_length(void) const
Definition: PermMatrix.h:63
for large enough k
Definition: lu.cc:606
PermMatrix(void)
Definition: PermMatrix.h:38
PermMatrix transpose(void) const
Definition: PermMatrix.cc:110
octave_idx_type checkelem(octave_idx_type i, octave_idx_type j) const
Definition: PermMatrix.cc:100
octave_idx_type columns(void) const
Definition: PermMatrix.h:61
octave_idx_type determinant(void) const
Definition: PermMatrix.cc:129
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:398
PermMatrix operator*(const PermMatrix &a, const PermMatrix &b)
Definition: PermMatrix.cc:220
PermMatrix inverse(void) const
Definition: PermMatrix.cc:123
const Array< octave_idx_type > & col_perm_vec(void) const
Definition: PermMatrix.h:79
nd deftypefn *octave_map m
Definition: ov-struct.cc:2058
const octave_idx_type * data(void) const
Definition: Array.h:582
void err_nonconformant(const char *op, octave_idx_type op1_len, octave_idx_type op2_len)
octave_value retval
Definition: data.cc:6294
octave_idx_type elem(octave_idx_type i, octave_idx_type j) const
Definition: PermMatrix.h:83
bool is_permutation(octave_idx_type n) const
Definition: idx-vector.cc:1135
static OCTAVE_NORETURN void err_invalid_permutation(void)
Definition: PermMatrix.cc:34
PermMatrix pos_power(octave_idx_type m) const
Definition: PermMatrix.cc:175
octave_idx_type & xelem(octave_idx_type n)
Definition: Array.h:455
=val(i)}if ode{val(i)}occurs in table i
Definition: lookup.cc:239
p
Definition: lu.cc:138
b
Definition: cellfun.cc:398
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:200
const T * fortran_vec(void) const
Definition: Array.h:584
static PermMatrix eye(octave_idx_type n)
Definition: PermMatrix.cc:214
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
PermMatrix power(octave_idx_type n) const
Definition: PermMatrix.cc:164
Array< T > & operator=(const Array< T > &a)
Definition: Array.h:309
void setup(const Array< octave_idx_type > &p, bool colp, bool check)
Definition: PermMatrix.cc:40
Array< T > index(const idx_vector &i) const
Indexing without resizing.
Definition: Array.cc:718