PermMatrix.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 2008-2012 Jaroslav Hajek
00004 
00005 This file is part of Octave.
00006 
00007 Octave is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 Octave is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Octave; see the file COPYING.  If not, see
00019 <http://www.gnu.org/licenses/>.
00020 
00021 */
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026 
00027 #include "PermMatrix.h"
00028 #include "idx-vector.h"
00029 #include "Array-util.h"
00030 #include "oct-locbuf.h"
00031 
00032 static void
00033 gripe_invalid_permutation (void)
00034 {
00035   (*current_liboctave_error_handler)
00036     ("PermMatrix: invalid permutation vector");
00037 }
00038 
00039 PermMatrix::PermMatrix (const Array<octave_idx_type>& p, bool colp, bool check)
00040   : Array<octave_idx_type> (p), _colp(colp)
00041 {
00042   if (check)
00043     {
00044       if (! idx_vector (p).is_permutation (p.length ()))
00045         {
00046           gripe_invalid_permutation ();
00047           Array<octave_idx_type>::operator = (Array<octave_idx_type> ());
00048         }
00049     }
00050 }
00051 
00052 PermMatrix::PermMatrix (const idx_vector& idx, bool colp, octave_idx_type n)
00053   : Array<octave_idx_type> (), _colp(colp)
00054 {
00055   octave_idx_type len = idx.length (n);
00056   if (! idx.is_permutation (len))
00057     gripe_invalid_permutation ();
00058   else
00059     {
00060       Array<octave_idx_type> idxa (dim_vector (len, 1));
00061       for (octave_idx_type i = 0; i < len; i++) idxa(i) = idx(i);
00062       Array<octave_idx_type>::operator = (idxa);
00063     }
00064 }
00065 
00066 PermMatrix::PermMatrix (octave_idx_type n)
00067   : Array<octave_idx_type> (dim_vector (n, 1)), _colp (false)
00068 {
00069   for (octave_idx_type i = 0; i < n; i++) xelem (i) = i;
00070 }
00071 
00072 octave_idx_type
00073 PermMatrix::checkelem (octave_idx_type i, octave_idx_type j) const
00074 {
00075   octave_idx_type len = Array<octave_idx_type>::length ();
00076   if (i < 0 || j < 0 || i > len || j > len)
00077     {
00078       (*current_liboctave_error_handler) ("index out of range");
00079       return 0;
00080     }
00081   else
00082     return elem (i, j);
00083 }
00084 
00085 
00086 PermMatrix
00087 PermMatrix::transpose (void) const
00088 {
00089   PermMatrix retval (*this);
00090   retval._colp = ! retval._colp;
00091   return retval;
00092 }
00093 
00094 PermMatrix
00095 PermMatrix::inverse (void) const
00096 {
00097   return transpose ();
00098 }
00099 
00100 octave_idx_type
00101 PermMatrix::determinant (void) const
00102 {
00103   // Determine the sign of a permutation in linear time.
00104   // Is this widely known?
00105 
00106   octave_idx_type len = perm_length ();
00107   const octave_idx_type *pa = data ();
00108 
00109   OCTAVE_LOCAL_BUFFER (octave_idx_type, p, len);
00110   OCTAVE_LOCAL_BUFFER (octave_idx_type, q, len);
00111 
00112   for (octave_idx_type i = 0; i < len; i++)
00113     {
00114       p[i] = pa[i];
00115       q[p[i]] = i;
00116     }
00117 
00118   bool neg = false;
00119 
00120   for (octave_idx_type i = 0; i < len; i++)
00121     {
00122       octave_idx_type j = p[i], k = q[i];
00123       if (j != i)
00124         {
00125           p[k] = p[i];
00126           q[j] = q[i];
00127           neg = ! neg;
00128         }
00129     }
00130 
00131   return neg ? -1 : 1;
00132 }
00133 
00134 PermMatrix
00135 PermMatrix::power (octave_idx_type m) const
00136 {
00137   octave_idx_type n = rows ();
00138   bool res_colp = _colp;
00139   if (m < 0)
00140     {
00141       res_colp = ! res_colp;
00142       m = -m;
00143     }
00144   else if (m == 0)
00145     return PermMatrix (n);
00146 
00147   const octave_idx_type *p = data ();
00148   Array<octave_idx_type> res_pvec (dim_vector (n, 1), -1);
00149   octave_idx_type *q = res_pvec.fortran_vec ();
00150 
00151   for (octave_idx_type ics = 0; ics < n; ics++)
00152     {
00153       if (q[ics] > 0)
00154         continue;
00155 
00156       // go forward m steps or until a cycle is found.
00157       octave_idx_type ic, j;
00158       for (j = 1, ic = p[ics]; j != m && ic != ics; j++, ic = p[ic]) ;
00159       if (ic == ics)
00160         {
00161           // reduce power.
00162           octave_idx_type mm = m % j;
00163           // go forward mm steps.
00164           for (j = 0, ic = ics; j != mm; j++, ic = p[ic]) ;
00165         }
00166 
00167       // now ic = p^m[ics]. Loop through the whole cycle.
00168       octave_idx_type jcs = ics;
00169       do
00170         {
00171           q[jcs] = ic;
00172           jcs = p[jcs]; ic = p[ic];
00173         }
00174       while (jcs != ics);
00175 
00176     }
00177 
00178   return PermMatrix (res_pvec, res_colp, false);
00179 }
00180 
00181 PermMatrix
00182 PermMatrix::eye (octave_idx_type n)
00183 {
00184   Array<octave_idx_type> p (dim_vector (n, 1));
00185   for (octave_idx_type i = 0; i < n; i++)
00186     p(i) = i;
00187 
00188   return PermMatrix (p, false, false);
00189 }
00190 
00191 PermMatrix
00192 operator *(const PermMatrix& a, const PermMatrix& b)
00193 {
00194   const Array<octave_idx_type> ia = a.pvec (), ib = b.pvec ();
00195   PermMatrix r;
00196   octave_idx_type n = a.columns ();
00197   if (n != b.rows ())
00198     gripe_nonconformant ("operator *", n, n, b.rows (), b.rows ());
00199   else if (a._colp == b._colp)
00200     {
00201       r = PermMatrix ((a._colp
00202                        ? ia.index (idx_vector (ib))
00203                        : ib.index (idx_vector (ia))), a._colp, false);
00204     }
00205   else
00206     {
00207       Array<octave_idx_type> ra (dim_vector (n, 1));
00208       if (a._colp)
00209         ra.assign (idx_vector (ia), ib);
00210       else
00211         ra.assign (idx_vector (ib), ia);
00212       r = PermMatrix (ra, a._colp, false);
00213     }
00214 
00215   return r;
00216 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines