Eigne Matrix Class Library
Dependents: Eigen_test Odometry_test AttitudeEstimation_usingTicker MPU9250_Quaternion_Binary_Serial ... more
Eigen Matrix Class Library for mbed.
Finally, you can use Eigen on your mbed!!!
src/Core/PermutationMatrix.h@0:13a5d365ba16, 2016-10-13 (annotated)
- Committer:
- ykuroda
- Date:
- Thu Oct 13 04:07:23 2016 +0000
- Revision:
- 0:13a5d365ba16
First commint, Eigne Matrix Class Library
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
ykuroda | 0:13a5d365ba16 | 1 | // This file is part of Eigen, a lightweight C++ template library |
ykuroda | 0:13a5d365ba16 | 2 | // for linear algebra. |
ykuroda | 0:13a5d365ba16 | 3 | // |
ykuroda | 0:13a5d365ba16 | 4 | // Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com> |
ykuroda | 0:13a5d365ba16 | 5 | // Copyright (C) 2009-2011 Gael Guennebaud <gael.guennebaud@inria.fr> |
ykuroda | 0:13a5d365ba16 | 6 | // |
ykuroda | 0:13a5d365ba16 | 7 | // This Source Code Form is subject to the terms of the Mozilla |
ykuroda | 0:13a5d365ba16 | 8 | // Public License v. 2.0. If a copy of the MPL was not distributed |
ykuroda | 0:13a5d365ba16 | 9 | // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
ykuroda | 0:13a5d365ba16 | 10 | |
ykuroda | 0:13a5d365ba16 | 11 | #ifndef EIGEN_PERMUTATIONMATRIX_H |
ykuroda | 0:13a5d365ba16 | 12 | #define EIGEN_PERMUTATIONMATRIX_H |
ykuroda | 0:13a5d365ba16 | 13 | |
ykuroda | 0:13a5d365ba16 | 14 | namespace Eigen { |
ykuroda | 0:13a5d365ba16 | 15 | |
ykuroda | 0:13a5d365ba16 | 16 | template<int RowCol,typename IndicesType,typename MatrixType, typename StorageKind> class PermutedImpl; |
ykuroda | 0:13a5d365ba16 | 17 | |
ykuroda | 0:13a5d365ba16 | 18 | /** \class PermutationBase |
ykuroda | 0:13a5d365ba16 | 19 | * \ingroup Core_Module |
ykuroda | 0:13a5d365ba16 | 20 | * |
ykuroda | 0:13a5d365ba16 | 21 | * \brief Base class for permutations |
ykuroda | 0:13a5d365ba16 | 22 | * |
ykuroda | 0:13a5d365ba16 | 23 | * \param Derived the derived class |
ykuroda | 0:13a5d365ba16 | 24 | * |
ykuroda | 0:13a5d365ba16 | 25 | * This class is the base class for all expressions representing a permutation matrix, |
ykuroda | 0:13a5d365ba16 | 26 | * internally stored as a vector of integers. |
ykuroda | 0:13a5d365ba16 | 27 | * The convention followed here is that if \f$ \sigma \f$ is a permutation, the corresponding permutation matrix |
ykuroda | 0:13a5d365ba16 | 28 | * \f$ P_\sigma \f$ is such that if \f$ (e_1,\ldots,e_p) \f$ is the canonical basis, we have: |
ykuroda | 0:13a5d365ba16 | 29 | * \f[ P_\sigma(e_i) = e_{\sigma(i)}. \f] |
ykuroda | 0:13a5d365ba16 | 30 | * This convention ensures that for any two permutations \f$ \sigma, \tau \f$, we have: |
ykuroda | 0:13a5d365ba16 | 31 | * \f[ P_{\sigma\circ\tau} = P_\sigma P_\tau. \f] |
ykuroda | 0:13a5d365ba16 | 32 | * |
ykuroda | 0:13a5d365ba16 | 33 | * Permutation matrices are square and invertible. |
ykuroda | 0:13a5d365ba16 | 34 | * |
ykuroda | 0:13a5d365ba16 | 35 | * Notice that in addition to the member functions and operators listed here, there also are non-member |
ykuroda | 0:13a5d365ba16 | 36 | * operator* to multiply any kind of permutation object with any kind of matrix expression (MatrixBase) |
ykuroda | 0:13a5d365ba16 | 37 | * on either side. |
ykuroda | 0:13a5d365ba16 | 38 | * |
ykuroda | 0:13a5d365ba16 | 39 | * \sa class PermutationMatrix, class PermutationWrapper |
ykuroda | 0:13a5d365ba16 | 40 | */ |
ykuroda | 0:13a5d365ba16 | 41 | |
ykuroda | 0:13a5d365ba16 | 42 | namespace internal { |
ykuroda | 0:13a5d365ba16 | 43 | |
ykuroda | 0:13a5d365ba16 | 44 | template<typename PermutationType, typename MatrixType, int Side, bool Transposed=false> |
ykuroda | 0:13a5d365ba16 | 45 | struct permut_matrix_product_retval; |
ykuroda | 0:13a5d365ba16 | 46 | template<typename PermutationType, typename MatrixType, int Side, bool Transposed=false> |
ykuroda | 0:13a5d365ba16 | 47 | struct permut_sparsematrix_product_retval; |
ykuroda | 0:13a5d365ba16 | 48 | enum PermPermProduct_t {PermPermProduct}; |
ykuroda | 0:13a5d365ba16 | 49 | |
ykuroda | 0:13a5d365ba16 | 50 | } // end namespace internal |
ykuroda | 0:13a5d365ba16 | 51 | |
ykuroda | 0:13a5d365ba16 | 52 | template<typename Derived> |
ykuroda | 0:13a5d365ba16 | 53 | class PermutationBase : public EigenBase<Derived> |
ykuroda | 0:13a5d365ba16 | 54 | { |
ykuroda | 0:13a5d365ba16 | 55 | typedef internal::traits<Derived> Traits; |
ykuroda | 0:13a5d365ba16 | 56 | typedef EigenBase<Derived> Base; |
ykuroda | 0:13a5d365ba16 | 57 | public: |
ykuroda | 0:13a5d365ba16 | 58 | |
ykuroda | 0:13a5d365ba16 | 59 | #ifndef EIGEN_PARSED_BY_DOXYGEN |
ykuroda | 0:13a5d365ba16 | 60 | typedef typename Traits::IndicesType IndicesType; |
ykuroda | 0:13a5d365ba16 | 61 | enum { |
ykuroda | 0:13a5d365ba16 | 62 | Flags = Traits::Flags, |
ykuroda | 0:13a5d365ba16 | 63 | CoeffReadCost = Traits::CoeffReadCost, |
ykuroda | 0:13a5d365ba16 | 64 | RowsAtCompileTime = Traits::RowsAtCompileTime, |
ykuroda | 0:13a5d365ba16 | 65 | ColsAtCompileTime = Traits::ColsAtCompileTime, |
ykuroda | 0:13a5d365ba16 | 66 | MaxRowsAtCompileTime = Traits::MaxRowsAtCompileTime, |
ykuroda | 0:13a5d365ba16 | 67 | MaxColsAtCompileTime = Traits::MaxColsAtCompileTime |
ykuroda | 0:13a5d365ba16 | 68 | }; |
ykuroda | 0:13a5d365ba16 | 69 | typedef typename Traits::Scalar Scalar; |
ykuroda | 0:13a5d365ba16 | 70 | typedef typename Traits::Index Index; |
ykuroda | 0:13a5d365ba16 | 71 | typedef Matrix<Scalar,RowsAtCompileTime,ColsAtCompileTime,0,MaxRowsAtCompileTime,MaxColsAtCompileTime> |
ykuroda | 0:13a5d365ba16 | 72 | DenseMatrixType; |
ykuroda | 0:13a5d365ba16 | 73 | typedef PermutationMatrix<IndicesType::SizeAtCompileTime,IndicesType::MaxSizeAtCompileTime,Index> |
ykuroda | 0:13a5d365ba16 | 74 | PlainPermutationType; |
ykuroda | 0:13a5d365ba16 | 75 | using Base::derived; |
ykuroda | 0:13a5d365ba16 | 76 | #endif |
ykuroda | 0:13a5d365ba16 | 77 | |
ykuroda | 0:13a5d365ba16 | 78 | /** Copies the other permutation into *this */ |
ykuroda | 0:13a5d365ba16 | 79 | template<typename OtherDerived> |
ykuroda | 0:13a5d365ba16 | 80 | Derived& operator=(const PermutationBase<OtherDerived>& other) |
ykuroda | 0:13a5d365ba16 | 81 | { |
ykuroda | 0:13a5d365ba16 | 82 | indices() = other.indices(); |
ykuroda | 0:13a5d365ba16 | 83 | return derived(); |
ykuroda | 0:13a5d365ba16 | 84 | } |
ykuroda | 0:13a5d365ba16 | 85 | |
ykuroda | 0:13a5d365ba16 | 86 | /** Assignment from the Transpositions \a tr */ |
ykuroda | 0:13a5d365ba16 | 87 | template<typename OtherDerived> |
ykuroda | 0:13a5d365ba16 | 88 | Derived& operator=(const TranspositionsBase<OtherDerived>& tr) |
ykuroda | 0:13a5d365ba16 | 89 | { |
ykuroda | 0:13a5d365ba16 | 90 | setIdentity(tr.size()); |
ykuroda | 0:13a5d365ba16 | 91 | for(Index k=size()-1; k>=0; --k) |
ykuroda | 0:13a5d365ba16 | 92 | applyTranspositionOnTheRight(k,tr.coeff(k)); |
ykuroda | 0:13a5d365ba16 | 93 | return derived(); |
ykuroda | 0:13a5d365ba16 | 94 | } |
ykuroda | 0:13a5d365ba16 | 95 | |
ykuroda | 0:13a5d365ba16 | 96 | #ifndef EIGEN_PARSED_BY_DOXYGEN |
ykuroda | 0:13a5d365ba16 | 97 | /** This is a special case of the templated operator=. Its purpose is to |
ykuroda | 0:13a5d365ba16 | 98 | * prevent a default operator= from hiding the templated operator=. |
ykuroda | 0:13a5d365ba16 | 99 | */ |
ykuroda | 0:13a5d365ba16 | 100 | Derived& operator=(const PermutationBase& other) |
ykuroda | 0:13a5d365ba16 | 101 | { |
ykuroda | 0:13a5d365ba16 | 102 | indices() = other.indices(); |
ykuroda | 0:13a5d365ba16 | 103 | return derived(); |
ykuroda | 0:13a5d365ba16 | 104 | } |
ykuroda | 0:13a5d365ba16 | 105 | #endif |
ykuroda | 0:13a5d365ba16 | 106 | |
ykuroda | 0:13a5d365ba16 | 107 | /** \returns the number of rows */ |
ykuroda | 0:13a5d365ba16 | 108 | inline Index rows() const { return Index(indices().size()); } |
ykuroda | 0:13a5d365ba16 | 109 | |
ykuroda | 0:13a5d365ba16 | 110 | /** \returns the number of columns */ |
ykuroda | 0:13a5d365ba16 | 111 | inline Index cols() const { return Index(indices().size()); } |
ykuroda | 0:13a5d365ba16 | 112 | |
ykuroda | 0:13a5d365ba16 | 113 | /** \returns the size of a side of the respective square matrix, i.e., the number of indices */ |
ykuroda | 0:13a5d365ba16 | 114 | inline Index size() const { return Index(indices().size()); } |
ykuroda | 0:13a5d365ba16 | 115 | |
ykuroda | 0:13a5d365ba16 | 116 | #ifndef EIGEN_PARSED_BY_DOXYGEN |
ykuroda | 0:13a5d365ba16 | 117 | template<typename DenseDerived> |
ykuroda | 0:13a5d365ba16 | 118 | void evalTo(MatrixBase<DenseDerived>& other) const |
ykuroda | 0:13a5d365ba16 | 119 | { |
ykuroda | 0:13a5d365ba16 | 120 | other.setZero(); |
ykuroda | 0:13a5d365ba16 | 121 | for (int i=0; i<rows();++i) |
ykuroda | 0:13a5d365ba16 | 122 | other.coeffRef(indices().coeff(i),i) = typename DenseDerived::Scalar(1); |
ykuroda | 0:13a5d365ba16 | 123 | } |
ykuroda | 0:13a5d365ba16 | 124 | #endif |
ykuroda | 0:13a5d365ba16 | 125 | |
ykuroda | 0:13a5d365ba16 | 126 | /** \returns a Matrix object initialized from this permutation matrix. Notice that it |
ykuroda | 0:13a5d365ba16 | 127 | * is inefficient to return this Matrix object by value. For efficiency, favor using |
ykuroda | 0:13a5d365ba16 | 128 | * the Matrix constructor taking EigenBase objects. |
ykuroda | 0:13a5d365ba16 | 129 | */ |
ykuroda | 0:13a5d365ba16 | 130 | DenseMatrixType toDenseMatrix() const |
ykuroda | 0:13a5d365ba16 | 131 | { |
ykuroda | 0:13a5d365ba16 | 132 | return derived(); |
ykuroda | 0:13a5d365ba16 | 133 | } |
ykuroda | 0:13a5d365ba16 | 134 | |
ykuroda | 0:13a5d365ba16 | 135 | /** const version of indices(). */ |
ykuroda | 0:13a5d365ba16 | 136 | const IndicesType& indices() const { return derived().indices(); } |
ykuroda | 0:13a5d365ba16 | 137 | /** \returns a reference to the stored array representing the permutation. */ |
ykuroda | 0:13a5d365ba16 | 138 | IndicesType& indices() { return derived().indices(); } |
ykuroda | 0:13a5d365ba16 | 139 | |
ykuroda | 0:13a5d365ba16 | 140 | /** Resizes to given size. |
ykuroda | 0:13a5d365ba16 | 141 | */ |
ykuroda | 0:13a5d365ba16 | 142 | inline void resize(Index newSize) |
ykuroda | 0:13a5d365ba16 | 143 | { |
ykuroda | 0:13a5d365ba16 | 144 | indices().resize(newSize); |
ykuroda | 0:13a5d365ba16 | 145 | } |
ykuroda | 0:13a5d365ba16 | 146 | |
ykuroda | 0:13a5d365ba16 | 147 | /** Sets *this to be the identity permutation matrix */ |
ykuroda | 0:13a5d365ba16 | 148 | void setIdentity() |
ykuroda | 0:13a5d365ba16 | 149 | { |
ykuroda | 0:13a5d365ba16 | 150 | for(Index i = 0; i < size(); ++i) |
ykuroda | 0:13a5d365ba16 | 151 | indices().coeffRef(i) = i; |
ykuroda | 0:13a5d365ba16 | 152 | } |
ykuroda | 0:13a5d365ba16 | 153 | |
ykuroda | 0:13a5d365ba16 | 154 | /** Sets *this to be the identity permutation matrix of given size. |
ykuroda | 0:13a5d365ba16 | 155 | */ |
ykuroda | 0:13a5d365ba16 | 156 | void setIdentity(Index newSize) |
ykuroda | 0:13a5d365ba16 | 157 | { |
ykuroda | 0:13a5d365ba16 | 158 | resize(newSize); |
ykuroda | 0:13a5d365ba16 | 159 | setIdentity(); |
ykuroda | 0:13a5d365ba16 | 160 | } |
ykuroda | 0:13a5d365ba16 | 161 | |
ykuroda | 0:13a5d365ba16 | 162 | /** Multiplies *this by the transposition \f$(ij)\f$ on the left. |
ykuroda | 0:13a5d365ba16 | 163 | * |
ykuroda | 0:13a5d365ba16 | 164 | * \returns a reference to *this. |
ykuroda | 0:13a5d365ba16 | 165 | * |
ykuroda | 0:13a5d365ba16 | 166 | * \warning This is much slower than applyTranspositionOnTheRight(int,int): |
ykuroda | 0:13a5d365ba16 | 167 | * this has linear complexity and requires a lot of branching. |
ykuroda | 0:13a5d365ba16 | 168 | * |
ykuroda | 0:13a5d365ba16 | 169 | * \sa applyTranspositionOnTheRight(int,int) |
ykuroda | 0:13a5d365ba16 | 170 | */ |
ykuroda | 0:13a5d365ba16 | 171 | Derived& applyTranspositionOnTheLeft(Index i, Index j) |
ykuroda | 0:13a5d365ba16 | 172 | { |
ykuroda | 0:13a5d365ba16 | 173 | eigen_assert(i>=0 && j>=0 && i<size() && j<size()); |
ykuroda | 0:13a5d365ba16 | 174 | for(Index k = 0; k < size(); ++k) |
ykuroda | 0:13a5d365ba16 | 175 | { |
ykuroda | 0:13a5d365ba16 | 176 | if(indices().coeff(k) == i) indices().coeffRef(k) = j; |
ykuroda | 0:13a5d365ba16 | 177 | else if(indices().coeff(k) == j) indices().coeffRef(k) = i; |
ykuroda | 0:13a5d365ba16 | 178 | } |
ykuroda | 0:13a5d365ba16 | 179 | return derived(); |
ykuroda | 0:13a5d365ba16 | 180 | } |
ykuroda | 0:13a5d365ba16 | 181 | |
ykuroda | 0:13a5d365ba16 | 182 | /** Multiplies *this by the transposition \f$(ij)\f$ on the right. |
ykuroda | 0:13a5d365ba16 | 183 | * |
ykuroda | 0:13a5d365ba16 | 184 | * \returns a reference to *this. |
ykuroda | 0:13a5d365ba16 | 185 | * |
ykuroda | 0:13a5d365ba16 | 186 | * This is a fast operation, it only consists in swapping two indices. |
ykuroda | 0:13a5d365ba16 | 187 | * |
ykuroda | 0:13a5d365ba16 | 188 | * \sa applyTranspositionOnTheLeft(int,int) |
ykuroda | 0:13a5d365ba16 | 189 | */ |
ykuroda | 0:13a5d365ba16 | 190 | Derived& applyTranspositionOnTheRight(Index i, Index j) |
ykuroda | 0:13a5d365ba16 | 191 | { |
ykuroda | 0:13a5d365ba16 | 192 | eigen_assert(i>=0 && j>=0 && i<size() && j<size()); |
ykuroda | 0:13a5d365ba16 | 193 | std::swap(indices().coeffRef(i), indices().coeffRef(j)); |
ykuroda | 0:13a5d365ba16 | 194 | return derived(); |
ykuroda | 0:13a5d365ba16 | 195 | } |
ykuroda | 0:13a5d365ba16 | 196 | |
ykuroda | 0:13a5d365ba16 | 197 | /** \returns the inverse permutation matrix. |
ykuroda | 0:13a5d365ba16 | 198 | * |
ykuroda | 0:13a5d365ba16 | 199 | * \note \note_try_to_help_rvo |
ykuroda | 0:13a5d365ba16 | 200 | */ |
ykuroda | 0:13a5d365ba16 | 201 | inline Transpose<PermutationBase> inverse() const |
ykuroda | 0:13a5d365ba16 | 202 | { return derived(); } |
ykuroda | 0:13a5d365ba16 | 203 | /** \returns the tranpose permutation matrix. |
ykuroda | 0:13a5d365ba16 | 204 | * |
ykuroda | 0:13a5d365ba16 | 205 | * \note \note_try_to_help_rvo |
ykuroda | 0:13a5d365ba16 | 206 | */ |
ykuroda | 0:13a5d365ba16 | 207 | inline Transpose<PermutationBase> transpose() const |
ykuroda | 0:13a5d365ba16 | 208 | { return derived(); } |
ykuroda | 0:13a5d365ba16 | 209 | |
ykuroda | 0:13a5d365ba16 | 210 | /**** multiplication helpers to hopefully get RVO ****/ |
ykuroda | 0:13a5d365ba16 | 211 | |
ykuroda | 0:13a5d365ba16 | 212 | |
ykuroda | 0:13a5d365ba16 | 213 | #ifndef EIGEN_PARSED_BY_DOXYGEN |
ykuroda | 0:13a5d365ba16 | 214 | protected: |
ykuroda | 0:13a5d365ba16 | 215 | template<typename OtherDerived> |
ykuroda | 0:13a5d365ba16 | 216 | void assignTranspose(const PermutationBase<OtherDerived>& other) |
ykuroda | 0:13a5d365ba16 | 217 | { |
ykuroda | 0:13a5d365ba16 | 218 | for (int i=0; i<rows();++i) indices().coeffRef(other.indices().coeff(i)) = i; |
ykuroda | 0:13a5d365ba16 | 219 | } |
ykuroda | 0:13a5d365ba16 | 220 | template<typename Lhs,typename Rhs> |
ykuroda | 0:13a5d365ba16 | 221 | void assignProduct(const Lhs& lhs, const Rhs& rhs) |
ykuroda | 0:13a5d365ba16 | 222 | { |
ykuroda | 0:13a5d365ba16 | 223 | eigen_assert(lhs.cols() == rhs.rows()); |
ykuroda | 0:13a5d365ba16 | 224 | for (int i=0; i<rows();++i) indices().coeffRef(i) = lhs.indices().coeff(rhs.indices().coeff(i)); |
ykuroda | 0:13a5d365ba16 | 225 | } |
ykuroda | 0:13a5d365ba16 | 226 | #endif |
ykuroda | 0:13a5d365ba16 | 227 | |
ykuroda | 0:13a5d365ba16 | 228 | public: |
ykuroda | 0:13a5d365ba16 | 229 | |
ykuroda | 0:13a5d365ba16 | 230 | /** \returns the product permutation matrix. |
ykuroda | 0:13a5d365ba16 | 231 | * |
ykuroda | 0:13a5d365ba16 | 232 | * \note \note_try_to_help_rvo |
ykuroda | 0:13a5d365ba16 | 233 | */ |
ykuroda | 0:13a5d365ba16 | 234 | template<typename Other> |
ykuroda | 0:13a5d365ba16 | 235 | inline PlainPermutationType operator*(const PermutationBase<Other>& other) const |
ykuroda | 0:13a5d365ba16 | 236 | { return PlainPermutationType(internal::PermPermProduct, derived(), other.derived()); } |
ykuroda | 0:13a5d365ba16 | 237 | |
ykuroda | 0:13a5d365ba16 | 238 | /** \returns the product of a permutation with another inverse permutation. |
ykuroda | 0:13a5d365ba16 | 239 | * |
ykuroda | 0:13a5d365ba16 | 240 | * \note \note_try_to_help_rvo |
ykuroda | 0:13a5d365ba16 | 241 | */ |
ykuroda | 0:13a5d365ba16 | 242 | template<typename Other> |
ykuroda | 0:13a5d365ba16 | 243 | inline PlainPermutationType operator*(const Transpose<PermutationBase<Other> >& other) const |
ykuroda | 0:13a5d365ba16 | 244 | { return PlainPermutationType(internal::PermPermProduct, *this, other.eval()); } |
ykuroda | 0:13a5d365ba16 | 245 | |
ykuroda | 0:13a5d365ba16 | 246 | /** \returns the product of an inverse permutation with another permutation. |
ykuroda | 0:13a5d365ba16 | 247 | * |
ykuroda | 0:13a5d365ba16 | 248 | * \note \note_try_to_help_rvo |
ykuroda | 0:13a5d365ba16 | 249 | */ |
ykuroda | 0:13a5d365ba16 | 250 | template<typename Other> friend |
ykuroda | 0:13a5d365ba16 | 251 | inline PlainPermutationType operator*(const Transpose<PermutationBase<Other> >& other, const PermutationBase& perm) |
ykuroda | 0:13a5d365ba16 | 252 | { return PlainPermutationType(internal::PermPermProduct, other.eval(), perm); } |
ykuroda | 0:13a5d365ba16 | 253 | |
ykuroda | 0:13a5d365ba16 | 254 | /** \returns the determinant of the permutation matrix, which is either 1 or -1 depending on the parity of the permutation. |
ykuroda | 0:13a5d365ba16 | 255 | * |
ykuroda | 0:13a5d365ba16 | 256 | * This function is O(\c n) procedure allocating a buffer of \c n booleans. |
ykuroda | 0:13a5d365ba16 | 257 | */ |
ykuroda | 0:13a5d365ba16 | 258 | Index determinant() const |
ykuroda | 0:13a5d365ba16 | 259 | { |
ykuroda | 0:13a5d365ba16 | 260 | Index res = 1; |
ykuroda | 0:13a5d365ba16 | 261 | Index n = size(); |
ykuroda | 0:13a5d365ba16 | 262 | Matrix<bool,RowsAtCompileTime,1,0,MaxRowsAtCompileTime> mask(n); |
ykuroda | 0:13a5d365ba16 | 263 | mask.fill(false); |
ykuroda | 0:13a5d365ba16 | 264 | Index r = 0; |
ykuroda | 0:13a5d365ba16 | 265 | while(r < n) |
ykuroda | 0:13a5d365ba16 | 266 | { |
ykuroda | 0:13a5d365ba16 | 267 | // search for the next seed |
ykuroda | 0:13a5d365ba16 | 268 | while(r<n && mask[r]) r++; |
ykuroda | 0:13a5d365ba16 | 269 | if(r>=n) |
ykuroda | 0:13a5d365ba16 | 270 | break; |
ykuroda | 0:13a5d365ba16 | 271 | // we got one, let's follow it until we are back to the seed |
ykuroda | 0:13a5d365ba16 | 272 | Index k0 = r++; |
ykuroda | 0:13a5d365ba16 | 273 | mask.coeffRef(k0) = true; |
ykuroda | 0:13a5d365ba16 | 274 | for(Index k=indices().coeff(k0); k!=k0; k=indices().coeff(k)) |
ykuroda | 0:13a5d365ba16 | 275 | { |
ykuroda | 0:13a5d365ba16 | 276 | mask.coeffRef(k) = true; |
ykuroda | 0:13a5d365ba16 | 277 | res = -res; |
ykuroda | 0:13a5d365ba16 | 278 | } |
ykuroda | 0:13a5d365ba16 | 279 | } |
ykuroda | 0:13a5d365ba16 | 280 | return res; |
ykuroda | 0:13a5d365ba16 | 281 | } |
ykuroda | 0:13a5d365ba16 | 282 | |
ykuroda | 0:13a5d365ba16 | 283 | protected: |
ykuroda | 0:13a5d365ba16 | 284 | |
ykuroda | 0:13a5d365ba16 | 285 | }; |
ykuroda | 0:13a5d365ba16 | 286 | |
ykuroda | 0:13a5d365ba16 | 287 | /** \class PermutationMatrix |
ykuroda | 0:13a5d365ba16 | 288 | * \ingroup Core_Module |
ykuroda | 0:13a5d365ba16 | 289 | * |
ykuroda | 0:13a5d365ba16 | 290 | * \brief Permutation matrix |
ykuroda | 0:13a5d365ba16 | 291 | * |
ykuroda | 0:13a5d365ba16 | 292 | * \param SizeAtCompileTime the number of rows/cols, or Dynamic |
ykuroda | 0:13a5d365ba16 | 293 | * \param MaxSizeAtCompileTime the maximum number of rows/cols, or Dynamic. This optional parameter defaults to SizeAtCompileTime. Most of the time, you should not have to specify it. |
ykuroda | 0:13a5d365ba16 | 294 | * \param IndexType the interger type of the indices |
ykuroda | 0:13a5d365ba16 | 295 | * |
ykuroda | 0:13a5d365ba16 | 296 | * This class represents a permutation matrix, internally stored as a vector of integers. |
ykuroda | 0:13a5d365ba16 | 297 | * |
ykuroda | 0:13a5d365ba16 | 298 | * \sa class PermutationBase, class PermutationWrapper, class DiagonalMatrix |
ykuroda | 0:13a5d365ba16 | 299 | */ |
ykuroda | 0:13a5d365ba16 | 300 | |
ykuroda | 0:13a5d365ba16 | 301 | namespace internal { |
ykuroda | 0:13a5d365ba16 | 302 | template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType> |
ykuroda | 0:13a5d365ba16 | 303 | struct traits<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, IndexType> > |
ykuroda | 0:13a5d365ba16 | 304 | : traits<Matrix<IndexType,SizeAtCompileTime,SizeAtCompileTime,0,MaxSizeAtCompileTime,MaxSizeAtCompileTime> > |
ykuroda | 0:13a5d365ba16 | 305 | { |
ykuroda | 0:13a5d365ba16 | 306 | typedef IndexType Index; |
ykuroda | 0:13a5d365ba16 | 307 | typedef Matrix<IndexType, SizeAtCompileTime, 1, 0, MaxSizeAtCompileTime, 1> IndicesType; |
ykuroda | 0:13a5d365ba16 | 308 | }; |
ykuroda | 0:13a5d365ba16 | 309 | } |
ykuroda | 0:13a5d365ba16 | 310 | |
ykuroda | 0:13a5d365ba16 | 311 | template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType> |
ykuroda | 0:13a5d365ba16 | 312 | class PermutationMatrix : public PermutationBase<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, IndexType> > |
ykuroda | 0:13a5d365ba16 | 313 | { |
ykuroda | 0:13a5d365ba16 | 314 | typedef PermutationBase<PermutationMatrix> Base; |
ykuroda | 0:13a5d365ba16 | 315 | typedef internal::traits<PermutationMatrix> Traits; |
ykuroda | 0:13a5d365ba16 | 316 | public: |
ykuroda | 0:13a5d365ba16 | 317 | |
ykuroda | 0:13a5d365ba16 | 318 | #ifndef EIGEN_PARSED_BY_DOXYGEN |
ykuroda | 0:13a5d365ba16 | 319 | typedef typename Traits::IndicesType IndicesType; |
ykuroda | 0:13a5d365ba16 | 320 | #endif |
ykuroda | 0:13a5d365ba16 | 321 | |
ykuroda | 0:13a5d365ba16 | 322 | inline PermutationMatrix() |
ykuroda | 0:13a5d365ba16 | 323 | {} |
ykuroda | 0:13a5d365ba16 | 324 | |
ykuroda | 0:13a5d365ba16 | 325 | /** Constructs an uninitialized permutation matrix of given size. |
ykuroda | 0:13a5d365ba16 | 326 | */ |
ykuroda | 0:13a5d365ba16 | 327 | inline PermutationMatrix(int size) : m_indices(size) |
ykuroda | 0:13a5d365ba16 | 328 | {} |
ykuroda | 0:13a5d365ba16 | 329 | |
ykuroda | 0:13a5d365ba16 | 330 | /** Copy constructor. */ |
ykuroda | 0:13a5d365ba16 | 331 | template<typename OtherDerived> |
ykuroda | 0:13a5d365ba16 | 332 | inline PermutationMatrix(const PermutationBase<OtherDerived>& other) |
ykuroda | 0:13a5d365ba16 | 333 | : m_indices(other.indices()) {} |
ykuroda | 0:13a5d365ba16 | 334 | |
ykuroda | 0:13a5d365ba16 | 335 | #ifndef EIGEN_PARSED_BY_DOXYGEN |
ykuroda | 0:13a5d365ba16 | 336 | /** Standard copy constructor. Defined only to prevent a default copy constructor |
ykuroda | 0:13a5d365ba16 | 337 | * from hiding the other templated constructor */ |
ykuroda | 0:13a5d365ba16 | 338 | inline PermutationMatrix(const PermutationMatrix& other) : m_indices(other.indices()) {} |
ykuroda | 0:13a5d365ba16 | 339 | #endif |
ykuroda | 0:13a5d365ba16 | 340 | |
ykuroda | 0:13a5d365ba16 | 341 | /** Generic constructor from expression of the indices. The indices |
ykuroda | 0:13a5d365ba16 | 342 | * array has the meaning that the permutations sends each integer i to indices[i]. |
ykuroda | 0:13a5d365ba16 | 343 | * |
ykuroda | 0:13a5d365ba16 | 344 | * \warning It is your responsibility to check that the indices array that you passes actually |
ykuroda | 0:13a5d365ba16 | 345 | * describes a permutation, i.e., each value between 0 and n-1 occurs exactly once, where n is the |
ykuroda | 0:13a5d365ba16 | 346 | * array's size. |
ykuroda | 0:13a5d365ba16 | 347 | */ |
ykuroda | 0:13a5d365ba16 | 348 | template<typename Other> |
ykuroda | 0:13a5d365ba16 | 349 | explicit inline PermutationMatrix(const MatrixBase<Other>& a_indices) : m_indices(a_indices) |
ykuroda | 0:13a5d365ba16 | 350 | {} |
ykuroda | 0:13a5d365ba16 | 351 | |
ykuroda | 0:13a5d365ba16 | 352 | /** Convert the Transpositions \a tr to a permutation matrix */ |
ykuroda | 0:13a5d365ba16 | 353 | template<typename Other> |
ykuroda | 0:13a5d365ba16 | 354 | explicit PermutationMatrix(const TranspositionsBase<Other>& tr) |
ykuroda | 0:13a5d365ba16 | 355 | : m_indices(tr.size()) |
ykuroda | 0:13a5d365ba16 | 356 | { |
ykuroda | 0:13a5d365ba16 | 357 | *this = tr; |
ykuroda | 0:13a5d365ba16 | 358 | } |
ykuroda | 0:13a5d365ba16 | 359 | |
ykuroda | 0:13a5d365ba16 | 360 | /** Copies the other permutation into *this */ |
ykuroda | 0:13a5d365ba16 | 361 | template<typename Other> |
ykuroda | 0:13a5d365ba16 | 362 | PermutationMatrix& operator=(const PermutationBase<Other>& other) |
ykuroda | 0:13a5d365ba16 | 363 | { |
ykuroda | 0:13a5d365ba16 | 364 | m_indices = other.indices(); |
ykuroda | 0:13a5d365ba16 | 365 | return *this; |
ykuroda | 0:13a5d365ba16 | 366 | } |
ykuroda | 0:13a5d365ba16 | 367 | |
ykuroda | 0:13a5d365ba16 | 368 | /** Assignment from the Transpositions \a tr */ |
ykuroda | 0:13a5d365ba16 | 369 | template<typename Other> |
ykuroda | 0:13a5d365ba16 | 370 | PermutationMatrix& operator=(const TranspositionsBase<Other>& tr) |
ykuroda | 0:13a5d365ba16 | 371 | { |
ykuroda | 0:13a5d365ba16 | 372 | return Base::operator=(tr.derived()); |
ykuroda | 0:13a5d365ba16 | 373 | } |
ykuroda | 0:13a5d365ba16 | 374 | |
ykuroda | 0:13a5d365ba16 | 375 | #ifndef EIGEN_PARSED_BY_DOXYGEN |
ykuroda | 0:13a5d365ba16 | 376 | /** This is a special case of the templated operator=. Its purpose is to |
ykuroda | 0:13a5d365ba16 | 377 | * prevent a default operator= from hiding the templated operator=. |
ykuroda | 0:13a5d365ba16 | 378 | */ |
ykuroda | 0:13a5d365ba16 | 379 | PermutationMatrix& operator=(const PermutationMatrix& other) |
ykuroda | 0:13a5d365ba16 | 380 | { |
ykuroda | 0:13a5d365ba16 | 381 | m_indices = other.m_indices; |
ykuroda | 0:13a5d365ba16 | 382 | return *this; |
ykuroda | 0:13a5d365ba16 | 383 | } |
ykuroda | 0:13a5d365ba16 | 384 | #endif |
ykuroda | 0:13a5d365ba16 | 385 | |
ykuroda | 0:13a5d365ba16 | 386 | /** const version of indices(). */ |
ykuroda | 0:13a5d365ba16 | 387 | const IndicesType& indices() const { return m_indices; } |
ykuroda | 0:13a5d365ba16 | 388 | /** \returns a reference to the stored array representing the permutation. */ |
ykuroda | 0:13a5d365ba16 | 389 | IndicesType& indices() { return m_indices; } |
ykuroda | 0:13a5d365ba16 | 390 | |
ykuroda | 0:13a5d365ba16 | 391 | |
ykuroda | 0:13a5d365ba16 | 392 | /**** multiplication helpers to hopefully get RVO ****/ |
ykuroda | 0:13a5d365ba16 | 393 | |
ykuroda | 0:13a5d365ba16 | 394 | #ifndef EIGEN_PARSED_BY_DOXYGEN |
ykuroda | 0:13a5d365ba16 | 395 | template<typename Other> |
ykuroda | 0:13a5d365ba16 | 396 | PermutationMatrix(const Transpose<PermutationBase<Other> >& other) |
ykuroda | 0:13a5d365ba16 | 397 | : m_indices(other.nestedPermutation().size()) |
ykuroda | 0:13a5d365ba16 | 398 | { |
ykuroda | 0:13a5d365ba16 | 399 | for (int i=0; i<m_indices.size();++i) m_indices.coeffRef(other.nestedPermutation().indices().coeff(i)) = i; |
ykuroda | 0:13a5d365ba16 | 400 | } |
ykuroda | 0:13a5d365ba16 | 401 | template<typename Lhs,typename Rhs> |
ykuroda | 0:13a5d365ba16 | 402 | PermutationMatrix(internal::PermPermProduct_t, const Lhs& lhs, const Rhs& rhs) |
ykuroda | 0:13a5d365ba16 | 403 | : m_indices(lhs.indices().size()) |
ykuroda | 0:13a5d365ba16 | 404 | { |
ykuroda | 0:13a5d365ba16 | 405 | Base::assignProduct(lhs,rhs); |
ykuroda | 0:13a5d365ba16 | 406 | } |
ykuroda | 0:13a5d365ba16 | 407 | #endif |
ykuroda | 0:13a5d365ba16 | 408 | |
ykuroda | 0:13a5d365ba16 | 409 | protected: |
ykuroda | 0:13a5d365ba16 | 410 | |
ykuroda | 0:13a5d365ba16 | 411 | IndicesType m_indices; |
ykuroda | 0:13a5d365ba16 | 412 | }; |
ykuroda | 0:13a5d365ba16 | 413 | |
ykuroda | 0:13a5d365ba16 | 414 | |
ykuroda | 0:13a5d365ba16 | 415 | namespace internal { |
ykuroda | 0:13a5d365ba16 | 416 | template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType, int _PacketAccess> |
ykuroda | 0:13a5d365ba16 | 417 | struct traits<Map<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, IndexType>,_PacketAccess> > |
ykuroda | 0:13a5d365ba16 | 418 | : traits<Matrix<IndexType,SizeAtCompileTime,SizeAtCompileTime,0,MaxSizeAtCompileTime,MaxSizeAtCompileTime> > |
ykuroda | 0:13a5d365ba16 | 419 | { |
ykuroda | 0:13a5d365ba16 | 420 | typedef IndexType Index; |
ykuroda | 0:13a5d365ba16 | 421 | typedef Map<const Matrix<IndexType, SizeAtCompileTime, 1, 0, MaxSizeAtCompileTime, 1>, _PacketAccess> IndicesType; |
ykuroda | 0:13a5d365ba16 | 422 | }; |
ykuroda | 0:13a5d365ba16 | 423 | } |
ykuroda | 0:13a5d365ba16 | 424 | |
ykuroda | 0:13a5d365ba16 | 425 | template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType, int _PacketAccess> |
ykuroda | 0:13a5d365ba16 | 426 | class Map<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, IndexType>,_PacketAccess> |
ykuroda | 0:13a5d365ba16 | 427 | : public PermutationBase<Map<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, IndexType>,_PacketAccess> > |
ykuroda | 0:13a5d365ba16 | 428 | { |
ykuroda | 0:13a5d365ba16 | 429 | typedef PermutationBase<Map> Base; |
ykuroda | 0:13a5d365ba16 | 430 | typedef internal::traits<Map> Traits; |
ykuroda | 0:13a5d365ba16 | 431 | public: |
ykuroda | 0:13a5d365ba16 | 432 | |
ykuroda | 0:13a5d365ba16 | 433 | #ifndef EIGEN_PARSED_BY_DOXYGEN |
ykuroda | 0:13a5d365ba16 | 434 | typedef typename Traits::IndicesType IndicesType; |
ykuroda | 0:13a5d365ba16 | 435 | typedef typename IndicesType::Scalar Index; |
ykuroda | 0:13a5d365ba16 | 436 | #endif |
ykuroda | 0:13a5d365ba16 | 437 | |
ykuroda | 0:13a5d365ba16 | 438 | inline Map(const Index* indicesPtr) |
ykuroda | 0:13a5d365ba16 | 439 | : m_indices(indicesPtr) |
ykuroda | 0:13a5d365ba16 | 440 | {} |
ykuroda | 0:13a5d365ba16 | 441 | |
ykuroda | 0:13a5d365ba16 | 442 | inline Map(const Index* indicesPtr, Index size) |
ykuroda | 0:13a5d365ba16 | 443 | : m_indices(indicesPtr,size) |
ykuroda | 0:13a5d365ba16 | 444 | {} |
ykuroda | 0:13a5d365ba16 | 445 | |
ykuroda | 0:13a5d365ba16 | 446 | /** Copies the other permutation into *this */ |
ykuroda | 0:13a5d365ba16 | 447 | template<typename Other> |
ykuroda | 0:13a5d365ba16 | 448 | Map& operator=(const PermutationBase<Other>& other) |
ykuroda | 0:13a5d365ba16 | 449 | { return Base::operator=(other.derived()); } |
ykuroda | 0:13a5d365ba16 | 450 | |
ykuroda | 0:13a5d365ba16 | 451 | /** Assignment from the Transpositions \a tr */ |
ykuroda | 0:13a5d365ba16 | 452 | template<typename Other> |
ykuroda | 0:13a5d365ba16 | 453 | Map& operator=(const TranspositionsBase<Other>& tr) |
ykuroda | 0:13a5d365ba16 | 454 | { return Base::operator=(tr.derived()); } |
ykuroda | 0:13a5d365ba16 | 455 | |
ykuroda | 0:13a5d365ba16 | 456 | #ifndef EIGEN_PARSED_BY_DOXYGEN |
ykuroda | 0:13a5d365ba16 | 457 | /** This is a special case of the templated operator=. Its purpose is to |
ykuroda | 0:13a5d365ba16 | 458 | * prevent a default operator= from hiding the templated operator=. |
ykuroda | 0:13a5d365ba16 | 459 | */ |
ykuroda | 0:13a5d365ba16 | 460 | Map& operator=(const Map& other) |
ykuroda | 0:13a5d365ba16 | 461 | { |
ykuroda | 0:13a5d365ba16 | 462 | m_indices = other.m_indices; |
ykuroda | 0:13a5d365ba16 | 463 | return *this; |
ykuroda | 0:13a5d365ba16 | 464 | } |
ykuroda | 0:13a5d365ba16 | 465 | #endif |
ykuroda | 0:13a5d365ba16 | 466 | |
ykuroda | 0:13a5d365ba16 | 467 | /** const version of indices(). */ |
ykuroda | 0:13a5d365ba16 | 468 | const IndicesType& indices() const { return m_indices; } |
ykuroda | 0:13a5d365ba16 | 469 | /** \returns a reference to the stored array representing the permutation. */ |
ykuroda | 0:13a5d365ba16 | 470 | IndicesType& indices() { return m_indices; } |
ykuroda | 0:13a5d365ba16 | 471 | |
ykuroda | 0:13a5d365ba16 | 472 | protected: |
ykuroda | 0:13a5d365ba16 | 473 | |
ykuroda | 0:13a5d365ba16 | 474 | IndicesType m_indices; |
ykuroda | 0:13a5d365ba16 | 475 | }; |
ykuroda | 0:13a5d365ba16 | 476 | |
ykuroda | 0:13a5d365ba16 | 477 | /** \class PermutationWrapper |
ykuroda | 0:13a5d365ba16 | 478 | * \ingroup Core_Module |
ykuroda | 0:13a5d365ba16 | 479 | * |
ykuroda | 0:13a5d365ba16 | 480 | * \brief Class to view a vector of integers as a permutation matrix |
ykuroda | 0:13a5d365ba16 | 481 | * |
ykuroda | 0:13a5d365ba16 | 482 | * \param _IndicesType the type of the vector of integer (can be any compatible expression) |
ykuroda | 0:13a5d365ba16 | 483 | * |
ykuroda | 0:13a5d365ba16 | 484 | * This class allows to view any vector expression of integers as a permutation matrix. |
ykuroda | 0:13a5d365ba16 | 485 | * |
ykuroda | 0:13a5d365ba16 | 486 | * \sa class PermutationBase, class PermutationMatrix |
ykuroda | 0:13a5d365ba16 | 487 | */ |
ykuroda | 0:13a5d365ba16 | 488 | |
ykuroda | 0:13a5d365ba16 | 489 | struct PermutationStorage {}; |
ykuroda | 0:13a5d365ba16 | 490 | |
ykuroda | 0:13a5d365ba16 | 491 | template<typename _IndicesType> class TranspositionsWrapper; |
ykuroda | 0:13a5d365ba16 | 492 | namespace internal { |
ykuroda | 0:13a5d365ba16 | 493 | template<typename _IndicesType> |
ykuroda | 0:13a5d365ba16 | 494 | struct traits<PermutationWrapper<_IndicesType> > |
ykuroda | 0:13a5d365ba16 | 495 | { |
ykuroda | 0:13a5d365ba16 | 496 | typedef PermutationStorage StorageKind; |
ykuroda | 0:13a5d365ba16 | 497 | typedef typename _IndicesType::Scalar Scalar; |
ykuroda | 0:13a5d365ba16 | 498 | typedef typename _IndicesType::Scalar Index; |
ykuroda | 0:13a5d365ba16 | 499 | typedef _IndicesType IndicesType; |
ykuroda | 0:13a5d365ba16 | 500 | enum { |
ykuroda | 0:13a5d365ba16 | 501 | RowsAtCompileTime = _IndicesType::SizeAtCompileTime, |
ykuroda | 0:13a5d365ba16 | 502 | ColsAtCompileTime = _IndicesType::SizeAtCompileTime, |
ykuroda | 0:13a5d365ba16 | 503 | MaxRowsAtCompileTime = IndicesType::MaxRowsAtCompileTime, |
ykuroda | 0:13a5d365ba16 | 504 | MaxColsAtCompileTime = IndicesType::MaxColsAtCompileTime, |
ykuroda | 0:13a5d365ba16 | 505 | Flags = 0, |
ykuroda | 0:13a5d365ba16 | 506 | CoeffReadCost = _IndicesType::CoeffReadCost |
ykuroda | 0:13a5d365ba16 | 507 | }; |
ykuroda | 0:13a5d365ba16 | 508 | }; |
ykuroda | 0:13a5d365ba16 | 509 | } |
ykuroda | 0:13a5d365ba16 | 510 | |
ykuroda | 0:13a5d365ba16 | 511 | template<typename _IndicesType> |
ykuroda | 0:13a5d365ba16 | 512 | class PermutationWrapper : public PermutationBase<PermutationWrapper<_IndicesType> > |
ykuroda | 0:13a5d365ba16 | 513 | { |
ykuroda | 0:13a5d365ba16 | 514 | typedef PermutationBase<PermutationWrapper> Base; |
ykuroda | 0:13a5d365ba16 | 515 | typedef internal::traits<PermutationWrapper> Traits; |
ykuroda | 0:13a5d365ba16 | 516 | public: |
ykuroda | 0:13a5d365ba16 | 517 | |
ykuroda | 0:13a5d365ba16 | 518 | #ifndef EIGEN_PARSED_BY_DOXYGEN |
ykuroda | 0:13a5d365ba16 | 519 | typedef typename Traits::IndicesType IndicesType; |
ykuroda | 0:13a5d365ba16 | 520 | #endif |
ykuroda | 0:13a5d365ba16 | 521 | |
ykuroda | 0:13a5d365ba16 | 522 | inline PermutationWrapper(const IndicesType& a_indices) |
ykuroda | 0:13a5d365ba16 | 523 | : m_indices(a_indices) |
ykuroda | 0:13a5d365ba16 | 524 | {} |
ykuroda | 0:13a5d365ba16 | 525 | |
ykuroda | 0:13a5d365ba16 | 526 | /** const version of indices(). */ |
ykuroda | 0:13a5d365ba16 | 527 | const typename internal::remove_all<typename IndicesType::Nested>::type& |
ykuroda | 0:13a5d365ba16 | 528 | indices() const { return m_indices; } |
ykuroda | 0:13a5d365ba16 | 529 | |
ykuroda | 0:13a5d365ba16 | 530 | protected: |
ykuroda | 0:13a5d365ba16 | 531 | |
ykuroda | 0:13a5d365ba16 | 532 | typename IndicesType::Nested m_indices; |
ykuroda | 0:13a5d365ba16 | 533 | }; |
ykuroda | 0:13a5d365ba16 | 534 | |
ykuroda | 0:13a5d365ba16 | 535 | /** \returns the matrix with the permutation applied to the columns. |
ykuroda | 0:13a5d365ba16 | 536 | */ |
ykuroda | 0:13a5d365ba16 | 537 | template<typename Derived, typename PermutationDerived> |
ykuroda | 0:13a5d365ba16 | 538 | inline const internal::permut_matrix_product_retval<PermutationDerived, Derived, OnTheRight> |
ykuroda | 0:13a5d365ba16 | 539 | operator*(const MatrixBase<Derived>& matrix, |
ykuroda | 0:13a5d365ba16 | 540 | const PermutationBase<PermutationDerived> &permutation) |
ykuroda | 0:13a5d365ba16 | 541 | { |
ykuroda | 0:13a5d365ba16 | 542 | return internal::permut_matrix_product_retval |
ykuroda | 0:13a5d365ba16 | 543 | <PermutationDerived, Derived, OnTheRight> |
ykuroda | 0:13a5d365ba16 | 544 | (permutation.derived(), matrix.derived()); |
ykuroda | 0:13a5d365ba16 | 545 | } |
ykuroda | 0:13a5d365ba16 | 546 | |
ykuroda | 0:13a5d365ba16 | 547 | /** \returns the matrix with the permutation applied to the rows. |
ykuroda | 0:13a5d365ba16 | 548 | */ |
ykuroda | 0:13a5d365ba16 | 549 | template<typename Derived, typename PermutationDerived> |
ykuroda | 0:13a5d365ba16 | 550 | inline const internal::permut_matrix_product_retval |
ykuroda | 0:13a5d365ba16 | 551 | <PermutationDerived, Derived, OnTheLeft> |
ykuroda | 0:13a5d365ba16 | 552 | operator*(const PermutationBase<PermutationDerived> &permutation, |
ykuroda | 0:13a5d365ba16 | 553 | const MatrixBase<Derived>& matrix) |
ykuroda | 0:13a5d365ba16 | 554 | { |
ykuroda | 0:13a5d365ba16 | 555 | return internal::permut_matrix_product_retval |
ykuroda | 0:13a5d365ba16 | 556 | <PermutationDerived, Derived, OnTheLeft> |
ykuroda | 0:13a5d365ba16 | 557 | (permutation.derived(), matrix.derived()); |
ykuroda | 0:13a5d365ba16 | 558 | } |
ykuroda | 0:13a5d365ba16 | 559 | |
ykuroda | 0:13a5d365ba16 | 560 | namespace internal { |
ykuroda | 0:13a5d365ba16 | 561 | |
ykuroda | 0:13a5d365ba16 | 562 | template<typename PermutationType, typename MatrixType, int Side, bool Transposed> |
ykuroda | 0:13a5d365ba16 | 563 | struct traits<permut_matrix_product_retval<PermutationType, MatrixType, Side, Transposed> > |
ykuroda | 0:13a5d365ba16 | 564 | { |
ykuroda | 0:13a5d365ba16 | 565 | typedef typename MatrixType::PlainObject ReturnType; |
ykuroda | 0:13a5d365ba16 | 566 | }; |
ykuroda | 0:13a5d365ba16 | 567 | |
ykuroda | 0:13a5d365ba16 | 568 | template<typename PermutationType, typename MatrixType, int Side, bool Transposed> |
ykuroda | 0:13a5d365ba16 | 569 | struct permut_matrix_product_retval |
ykuroda | 0:13a5d365ba16 | 570 | : public ReturnByValue<permut_matrix_product_retval<PermutationType, MatrixType, Side, Transposed> > |
ykuroda | 0:13a5d365ba16 | 571 | { |
ykuroda | 0:13a5d365ba16 | 572 | typedef typename remove_all<typename MatrixType::Nested>::type MatrixTypeNestedCleaned; |
ykuroda | 0:13a5d365ba16 | 573 | typedef typename MatrixType::Index Index; |
ykuroda | 0:13a5d365ba16 | 574 | |
ykuroda | 0:13a5d365ba16 | 575 | permut_matrix_product_retval(const PermutationType& perm, const MatrixType& matrix) |
ykuroda | 0:13a5d365ba16 | 576 | : m_permutation(perm), m_matrix(matrix) |
ykuroda | 0:13a5d365ba16 | 577 | {} |
ykuroda | 0:13a5d365ba16 | 578 | |
ykuroda | 0:13a5d365ba16 | 579 | inline Index rows() const { return m_matrix.rows(); } |
ykuroda | 0:13a5d365ba16 | 580 | inline Index cols() const { return m_matrix.cols(); } |
ykuroda | 0:13a5d365ba16 | 581 | |
ykuroda | 0:13a5d365ba16 | 582 | template<typename Dest> inline void evalTo(Dest& dst) const |
ykuroda | 0:13a5d365ba16 | 583 | { |
ykuroda | 0:13a5d365ba16 | 584 | const Index n = Side==OnTheLeft ? rows() : cols(); |
ykuroda | 0:13a5d365ba16 | 585 | // FIXME we need an is_same for expression that is not sensitive to constness. For instance |
ykuroda | 0:13a5d365ba16 | 586 | // is_same_xpr<Block<const Matrix>, Block<Matrix> >::value should be true. |
ykuroda | 0:13a5d365ba16 | 587 | if( is_same<MatrixTypeNestedCleaned,Dest>::value |
ykuroda | 0:13a5d365ba16 | 588 | && blas_traits<MatrixTypeNestedCleaned>::HasUsableDirectAccess |
ykuroda | 0:13a5d365ba16 | 589 | && blas_traits<Dest>::HasUsableDirectAccess |
ykuroda | 0:13a5d365ba16 | 590 | && extract_data(dst) == extract_data(m_matrix)) |
ykuroda | 0:13a5d365ba16 | 591 | { |
ykuroda | 0:13a5d365ba16 | 592 | // apply the permutation inplace |
ykuroda | 0:13a5d365ba16 | 593 | Matrix<bool,PermutationType::RowsAtCompileTime,1,0,PermutationType::MaxRowsAtCompileTime> mask(m_permutation.size()); |
ykuroda | 0:13a5d365ba16 | 594 | mask.fill(false); |
ykuroda | 0:13a5d365ba16 | 595 | Index r = 0; |
ykuroda | 0:13a5d365ba16 | 596 | while(r < m_permutation.size()) |
ykuroda | 0:13a5d365ba16 | 597 | { |
ykuroda | 0:13a5d365ba16 | 598 | // search for the next seed |
ykuroda | 0:13a5d365ba16 | 599 | while(r<m_permutation.size() && mask[r]) r++; |
ykuroda | 0:13a5d365ba16 | 600 | if(r>=m_permutation.size()) |
ykuroda | 0:13a5d365ba16 | 601 | break; |
ykuroda | 0:13a5d365ba16 | 602 | // we got one, let's follow it until we are back to the seed |
ykuroda | 0:13a5d365ba16 | 603 | Index k0 = r++; |
ykuroda | 0:13a5d365ba16 | 604 | Index kPrev = k0; |
ykuroda | 0:13a5d365ba16 | 605 | mask.coeffRef(k0) = true; |
ykuroda | 0:13a5d365ba16 | 606 | for(Index k=m_permutation.indices().coeff(k0); k!=k0; k=m_permutation.indices().coeff(k)) |
ykuroda | 0:13a5d365ba16 | 607 | { |
ykuroda | 0:13a5d365ba16 | 608 | Block<Dest, Side==OnTheLeft ? 1 : Dest::RowsAtCompileTime, Side==OnTheRight ? 1 : Dest::ColsAtCompileTime>(dst, k) |
ykuroda | 0:13a5d365ba16 | 609 | .swap(Block<Dest, Side==OnTheLeft ? 1 : Dest::RowsAtCompileTime, Side==OnTheRight ? 1 : Dest::ColsAtCompileTime> |
ykuroda | 0:13a5d365ba16 | 610 | (dst,((Side==OnTheLeft) ^ Transposed) ? k0 : kPrev)); |
ykuroda | 0:13a5d365ba16 | 611 | |
ykuroda | 0:13a5d365ba16 | 612 | mask.coeffRef(k) = true; |
ykuroda | 0:13a5d365ba16 | 613 | kPrev = k; |
ykuroda | 0:13a5d365ba16 | 614 | } |
ykuroda | 0:13a5d365ba16 | 615 | } |
ykuroda | 0:13a5d365ba16 | 616 | } |
ykuroda | 0:13a5d365ba16 | 617 | else |
ykuroda | 0:13a5d365ba16 | 618 | { |
ykuroda | 0:13a5d365ba16 | 619 | for(int i = 0; i < n; ++i) |
ykuroda | 0:13a5d365ba16 | 620 | { |
ykuroda | 0:13a5d365ba16 | 621 | Block<Dest, Side==OnTheLeft ? 1 : Dest::RowsAtCompileTime, Side==OnTheRight ? 1 : Dest::ColsAtCompileTime> |
ykuroda | 0:13a5d365ba16 | 622 | (dst, ((Side==OnTheLeft) ^ Transposed) ? m_permutation.indices().coeff(i) : i) |
ykuroda | 0:13a5d365ba16 | 623 | |
ykuroda | 0:13a5d365ba16 | 624 | = |
ykuroda | 0:13a5d365ba16 | 625 | |
ykuroda | 0:13a5d365ba16 | 626 | Block<const MatrixTypeNestedCleaned,Side==OnTheLeft ? 1 : MatrixType::RowsAtCompileTime,Side==OnTheRight ? 1 : MatrixType::ColsAtCompileTime> |
ykuroda | 0:13a5d365ba16 | 627 | (m_matrix, ((Side==OnTheRight) ^ Transposed) ? m_permutation.indices().coeff(i) : i); |
ykuroda | 0:13a5d365ba16 | 628 | } |
ykuroda | 0:13a5d365ba16 | 629 | } |
ykuroda | 0:13a5d365ba16 | 630 | } |
ykuroda | 0:13a5d365ba16 | 631 | |
ykuroda | 0:13a5d365ba16 | 632 | protected: |
ykuroda | 0:13a5d365ba16 | 633 | const PermutationType& m_permutation; |
ykuroda | 0:13a5d365ba16 | 634 | typename MatrixType::Nested m_matrix; |
ykuroda | 0:13a5d365ba16 | 635 | }; |
ykuroda | 0:13a5d365ba16 | 636 | |
ykuroda | 0:13a5d365ba16 | 637 | /* Template partial specialization for transposed/inverse permutations */ |
ykuroda | 0:13a5d365ba16 | 638 | |
ykuroda | 0:13a5d365ba16 | 639 | template<typename Derived> |
ykuroda | 0:13a5d365ba16 | 640 | struct traits<Transpose<PermutationBase<Derived> > > |
ykuroda | 0:13a5d365ba16 | 641 | : traits<Derived> |
ykuroda | 0:13a5d365ba16 | 642 | {}; |
ykuroda | 0:13a5d365ba16 | 643 | |
ykuroda | 0:13a5d365ba16 | 644 | } // end namespace internal |
ykuroda | 0:13a5d365ba16 | 645 | |
ykuroda | 0:13a5d365ba16 | 646 | template<typename Derived> |
ykuroda | 0:13a5d365ba16 | 647 | class Transpose<PermutationBase<Derived> > |
ykuroda | 0:13a5d365ba16 | 648 | : public EigenBase<Transpose<PermutationBase<Derived> > > |
ykuroda | 0:13a5d365ba16 | 649 | { |
ykuroda | 0:13a5d365ba16 | 650 | typedef Derived PermutationType; |
ykuroda | 0:13a5d365ba16 | 651 | typedef typename PermutationType::IndicesType IndicesType; |
ykuroda | 0:13a5d365ba16 | 652 | typedef typename PermutationType::PlainPermutationType PlainPermutationType; |
ykuroda | 0:13a5d365ba16 | 653 | public: |
ykuroda | 0:13a5d365ba16 | 654 | |
ykuroda | 0:13a5d365ba16 | 655 | #ifndef EIGEN_PARSED_BY_DOXYGEN |
ykuroda | 0:13a5d365ba16 | 656 | typedef internal::traits<PermutationType> Traits; |
ykuroda | 0:13a5d365ba16 | 657 | typedef typename Derived::DenseMatrixType DenseMatrixType; |
ykuroda | 0:13a5d365ba16 | 658 | enum { |
ykuroda | 0:13a5d365ba16 | 659 | Flags = Traits::Flags, |
ykuroda | 0:13a5d365ba16 | 660 | CoeffReadCost = Traits::CoeffReadCost, |
ykuroda | 0:13a5d365ba16 | 661 | RowsAtCompileTime = Traits::RowsAtCompileTime, |
ykuroda | 0:13a5d365ba16 | 662 | ColsAtCompileTime = Traits::ColsAtCompileTime, |
ykuroda | 0:13a5d365ba16 | 663 | MaxRowsAtCompileTime = Traits::MaxRowsAtCompileTime, |
ykuroda | 0:13a5d365ba16 | 664 | MaxColsAtCompileTime = Traits::MaxColsAtCompileTime |
ykuroda | 0:13a5d365ba16 | 665 | }; |
ykuroda | 0:13a5d365ba16 | 666 | typedef typename Traits::Scalar Scalar; |
ykuroda | 0:13a5d365ba16 | 667 | #endif |
ykuroda | 0:13a5d365ba16 | 668 | |
ykuroda | 0:13a5d365ba16 | 669 | Transpose(const PermutationType& p) : m_permutation(p) {} |
ykuroda | 0:13a5d365ba16 | 670 | |
ykuroda | 0:13a5d365ba16 | 671 | inline int rows() const { return m_permutation.rows(); } |
ykuroda | 0:13a5d365ba16 | 672 | inline int cols() const { return m_permutation.cols(); } |
ykuroda | 0:13a5d365ba16 | 673 | |
ykuroda | 0:13a5d365ba16 | 674 | #ifndef EIGEN_PARSED_BY_DOXYGEN |
ykuroda | 0:13a5d365ba16 | 675 | template<typename DenseDerived> |
ykuroda | 0:13a5d365ba16 | 676 | void evalTo(MatrixBase<DenseDerived>& other) const |
ykuroda | 0:13a5d365ba16 | 677 | { |
ykuroda | 0:13a5d365ba16 | 678 | other.setZero(); |
ykuroda | 0:13a5d365ba16 | 679 | for (int i=0; i<rows();++i) |
ykuroda | 0:13a5d365ba16 | 680 | other.coeffRef(i, m_permutation.indices().coeff(i)) = typename DenseDerived::Scalar(1); |
ykuroda | 0:13a5d365ba16 | 681 | } |
ykuroda | 0:13a5d365ba16 | 682 | #endif |
ykuroda | 0:13a5d365ba16 | 683 | |
ykuroda | 0:13a5d365ba16 | 684 | /** \return the equivalent permutation matrix */ |
ykuroda | 0:13a5d365ba16 | 685 | PlainPermutationType eval() const { return *this; } |
ykuroda | 0:13a5d365ba16 | 686 | |
ykuroda | 0:13a5d365ba16 | 687 | DenseMatrixType toDenseMatrix() const { return *this; } |
ykuroda | 0:13a5d365ba16 | 688 | |
ykuroda | 0:13a5d365ba16 | 689 | /** \returns the matrix with the inverse permutation applied to the columns. |
ykuroda | 0:13a5d365ba16 | 690 | */ |
ykuroda | 0:13a5d365ba16 | 691 | template<typename OtherDerived> friend |
ykuroda | 0:13a5d365ba16 | 692 | inline const internal::permut_matrix_product_retval<PermutationType, OtherDerived, OnTheRight, true> |
ykuroda | 0:13a5d365ba16 | 693 | operator*(const MatrixBase<OtherDerived>& matrix, const Transpose& trPerm) |
ykuroda | 0:13a5d365ba16 | 694 | { |
ykuroda | 0:13a5d365ba16 | 695 | return internal::permut_matrix_product_retval<PermutationType, OtherDerived, OnTheRight, true>(trPerm.m_permutation, matrix.derived()); |
ykuroda | 0:13a5d365ba16 | 696 | } |
ykuroda | 0:13a5d365ba16 | 697 | |
ykuroda | 0:13a5d365ba16 | 698 | /** \returns the matrix with the inverse permutation applied to the rows. |
ykuroda | 0:13a5d365ba16 | 699 | */ |
ykuroda | 0:13a5d365ba16 | 700 | template<typename OtherDerived> |
ykuroda | 0:13a5d365ba16 | 701 | inline const internal::permut_matrix_product_retval<PermutationType, OtherDerived, OnTheLeft, true> |
ykuroda | 0:13a5d365ba16 | 702 | operator*(const MatrixBase<OtherDerived>& matrix) const |
ykuroda | 0:13a5d365ba16 | 703 | { |
ykuroda | 0:13a5d365ba16 | 704 | return internal::permut_matrix_product_retval<PermutationType, OtherDerived, OnTheLeft, true>(m_permutation, matrix.derived()); |
ykuroda | 0:13a5d365ba16 | 705 | } |
ykuroda | 0:13a5d365ba16 | 706 | |
ykuroda | 0:13a5d365ba16 | 707 | const PermutationType& nestedPermutation() const { return m_permutation; } |
ykuroda | 0:13a5d365ba16 | 708 | |
ykuroda | 0:13a5d365ba16 | 709 | protected: |
ykuroda | 0:13a5d365ba16 | 710 | const PermutationType& m_permutation; |
ykuroda | 0:13a5d365ba16 | 711 | }; |
ykuroda | 0:13a5d365ba16 | 712 | |
ykuroda | 0:13a5d365ba16 | 713 | template<typename Derived> |
ykuroda | 0:13a5d365ba16 | 714 | const PermutationWrapper<const Derived> MatrixBase<Derived>::asPermutation() const |
ykuroda | 0:13a5d365ba16 | 715 | { |
ykuroda | 0:13a5d365ba16 | 716 | return derived(); |
ykuroda | 0:13a5d365ba16 | 717 | } |
ykuroda | 0:13a5d365ba16 | 718 | |
ykuroda | 0:13a5d365ba16 | 719 | } // end namespace Eigen |
ykuroda | 0:13a5d365ba16 | 720 | |
ykuroda | 0:13a5d365ba16 | 721 | #endif // EIGEN_PERMUTATIONMATRIX_H |