GNU Octave  3.8.0
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-2013 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 #ifdef 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 static void
34 {
35  (*current_liboctave_error_handler)
36  ("PermMatrix: invalid permutation vector");
37 }
38 
39 PermMatrix::PermMatrix (const Array<octave_idx_type>& p, bool colp, bool check)
40  : Array<octave_idx_type> (p), _colp(colp)
41 {
42  if (check)
43  {
44  if (! idx_vector (p).is_permutation (p.length ()))
45  {
48  }
49  }
50 }
51 
53  : Array<octave_idx_type> (), _colp(colp)
54 {
55  octave_idx_type len = idx.length (n);
56  if (! idx.is_permutation (len))
58  else
59  {
60  Array<octave_idx_type> idxa (dim_vector (len, 1));
61  for (octave_idx_type i = 0; i < len; i++) idxa(i) = idx(i);
63  }
64 }
65 
67  : Array<octave_idx_type> (dim_vector (n, 1)), _colp (false)
68 {
69  for (octave_idx_type i = 0; i < n; i++) xelem (i) = i;
70 }
71 
74 {
76  if (i < 0 || j < 0 || i > len || j > len)
77  {
78  (*current_liboctave_error_handler) ("index out of range");
79  return 0;
80  }
81  else
82  return elem (i, j);
83 }
84 
85 
88 {
89  PermMatrix retval (*this);
90  retval._colp = ! retval._colp;
91  return retval;
92 }
93 
95 PermMatrix::inverse (void) const
96 {
97  return transpose ();
98 }
99 
102 {
103  // Determine the sign of a permutation in linear time.
104  // Is this widely known?
105 
106  octave_idx_type len = perm_length ();
107  const octave_idx_type *pa = data ();
108 
111 
112  for (octave_idx_type i = 0; i < len; i++)
113  {
114  p[i] = pa[i];
115  q[p[i]] = i;
116  }
117 
118  bool neg = false;
119 
120  for (octave_idx_type i = 0; i < len; i++)
121  {
122  octave_idx_type j = p[i], k = q[i];
123  if (j != i)
124  {
125  p[k] = p[i];
126  q[j] = q[i];
127  neg = ! neg;
128  }
129  }
130 
131  return neg ? -1 : 1;
132 }
133 
136 {
137  octave_idx_type n = rows ();
138  bool res_colp = _colp;
139  if (m < 0)
140  {
141  res_colp = ! res_colp;
142  m = -m;
143  }
144  else if (m == 0)
145  return PermMatrix (n);
146 
147  const octave_idx_type *p = data ();
148  Array<octave_idx_type> res_pvec (dim_vector (n, 1), -1);
149  octave_idx_type *q = res_pvec.fortran_vec ();
150 
151  for (octave_idx_type ics = 0; ics < n; ics++)
152  {
153  if (q[ics] > 0)
154  continue;
155 
156  // go forward m steps or until a cycle is found.
157  octave_idx_type ic, j;
158  for (j = 1, ic = p[ics]; j != m && ic != ics; j++, ic = p[ic]) ;
159  if (ic == ics)
160  {
161  // reduce power.
162  octave_idx_type mm = m % j;
163  // go forward mm steps.
164  for (j = 0, ic = ics; j != mm; j++, ic = p[ic]) ;
165  }
166 
167  // now ic = p^m[ics]. Loop through the whole cycle.
168  octave_idx_type jcs = ics;
169  do
170  {
171  q[jcs] = ic;
172  jcs = p[jcs]; ic = p[ic];
173  }
174  while (jcs != ics);
175 
176  }
177 
178  return PermMatrix (res_pvec, res_colp, false);
179 }
180 
183 {
185  for (octave_idx_type i = 0; i < n; i++)
186  p(i) = i;
187 
188  return PermMatrix (p, false, false);
189 }
190 
192 operator *(const PermMatrix& a, const PermMatrix& b)
193 {
194  const Array<octave_idx_type> ia = a.pvec (), ib = b.pvec ();
195  PermMatrix r;
196  octave_idx_type n = a.columns ();
197  if (n != b.rows ())
198  gripe_nonconformant ("operator *", n, n, b.rows (), b.rows ());
199  else if (a._colp == b._colp)
200  {
201  r = PermMatrix ((a._colp
202  ? ia.index (idx_vector (ib))
203  : ib.index (idx_vector (ia))), a._colp, false);
204  }
205  else
206  {
208  if (a._colp)
209  ra.assign (idx_vector (ia), ib);
210  else
211  ra.assign (idx_vector (ib), ia);
212  r = PermMatrix (ra, a._colp, false);
213  }
214 
215  return r;
216 }