Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00104
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
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
00162 octave_idx_type mm = m % j;
00163
00164 for (j = 0, ic = ics; j != mm; j++, ic = p[ic]) ;
00165 }
00166
00167
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 }