Main MRPT website > C++ reference
MRPT logo

Transpositions.h

Go to the documentation of this file.
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
00005 //
00006 // Eigen is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 3 of the License, or (at your option) any later version.
00010 //
00011 // Alternatively, you can redistribute it and/or
00012 // modify it under the terms of the GNU General Public License as
00013 // published by the Free Software Foundation; either version 2 of
00014 // the License, or (at your option) any later version.
00015 //
00016 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
00017 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00018 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
00019 // GNU General Public License for more details.
00020 //
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License and a copy of the GNU General Public License along with
00023 // Eigen. If not, see <http://www.gnu.org/licenses/>.
00024 
00025 #ifndef EIGEN_TRANSPOSITIONS_H
00026 #define EIGEN_TRANSPOSITIONS_H
00027 
00028 /** \class Transpositions
00029   * \ingroup Core_Module
00030   *
00031   * \brief Represents a sequence of transpositions (row/column interchange)
00032   *
00033   * \param SizeAtCompileTime the number of transpositions, or Dynamic
00034   * \param MaxSizeAtCompileTime the maximum number of transpositions, or Dynamic. This optional parameter defaults to SizeAtCompileTime. Most of the time, you should not have to specify it.
00035   *
00036   * This class represents a permutation transformation as a sequence of \em n transpositions
00037   * \f$[T_{n-1} \ldots T_{i} \ldots T_{0}]\f$. It is internally stored as a vector of integers \c indices.
00038   * Each transposition \f$ T_{i} \f$ applied on the left of a matrix (\f$ T_{i} M\f$) interchanges
00039   * the rows \c i and \c indices[i] of the matrix \c M.
00040   * A transposition applied on the right (e.g., \f$ M T_{i}\f$) yields a column interchange.
00041   *
00042   * Compared to the class PermutationMatrix, such a sequence of transpositions is what is
00043   * computed during a decomposition with pivoting, and it is faster when applying the permutation in-place.
00044   * 
00045   * To apply a sequence of transpositions to a matrix, simply use the operator * as in the following example:
00046   * \code
00047   * Transpositions tr;
00048   * MatrixXf mat;
00049   * mat = tr * mat;
00050   * \endcode
00051   * In this example, we detect that the matrix appears on both side, and so the transpositions
00052   * are applied in-place without any temporary or extra copy.
00053   *
00054   * \sa class PermutationMatrix
00055   */
00056 
00057 namespace internal {
00058 template<typename TranspositionType, typename MatrixType, int Side, bool Transposed=false> struct transposition_matrix_product_retval;
00059 }
00060 
00061 template<int SizeAtCompileTime, int MaxSizeAtCompileTime>
00062 class Transpositions
00063 {
00064   public:
00065 
00066     typedef Matrix<DenseIndex, SizeAtCompileTime, 1, 0, MaxSizeAtCompileTime, 1> IndicesType;
00067     typedef typename IndicesType::Index Index;
00068 
00069     inline Transpositions() {}
00070 
00071     /** Copy constructor. */
00072     template<int OtherSize, int OtherMaxSize>
00073     inline Transpositions(const Transpositions<OtherSize, OtherMaxSize>& other)
00074       : m_indices(other.indices()) {}
00075 
00076     #ifndef EIGEN_PARSED_BY_DOXYGEN
00077     /** Standard copy constructor. Defined only to prevent a default copy constructor
00078       * from hiding the other templated constructor */
00079     inline Transpositions(const Transpositions& other) : m_indices(other.indices()) {}
00080     #endif
00081 
00082     /** Generic constructor from expression of the transposition indices. */
00083     template<typename Other>
00084     explicit inline Transpositions(const MatrixBase<Other>& indices) : m_indices(indices)
00085     {}
00086 
00087     /** Copies the \a other transpositions into \c *this */
00088     template<int OtherSize, int OtherMaxSize>
00089     Transpositions& operator=(const Transpositions<OtherSize, OtherMaxSize>& other)
00090     {
00091       m_indices = other.indices();
00092       return *this;
00093     }
00094 
00095     #ifndef EIGEN_PARSED_BY_DOXYGEN
00096     /** This is a special case of the templated operator=. Its purpose is to
00097       * prevent a default operator= from hiding the templated operator=.
00098       */
00099     Transpositions& operator=(const Transpositions& other)
00100     {
00101       m_indices = other.m_indices;
00102       return *this;
00103     }
00104     #endif
00105 
00106     /** Constructs an uninitialized permutation matrix of given size.
00107       */
00108     inline Transpositions(Index size) : m_indices(size)
00109     {}
00110 
00111     /** \returns the number of transpositions */
00112     inline Index size() const { return m_indices.size(); }
00113 
00114     /** Direct access to the underlying index vector */
00115     inline const Index& coeff(Index i) const { return m_indices.coeff(i); }
00116     /** Direct access to the underlying index vector */
00117     inline Index& coeffRef(Index i) { return m_indices.coeffRef(i); }
00118     /** Direct access to the underlying index vector */
00119     inline const Index& operator()(Index i) const { return m_indices(i); }
00120     /** Direct access to the underlying index vector */
00121     inline Index& operator()(Index i) { return m_indices(i); }
00122     /** Direct access to the underlying index vector */
00123     inline const Index& operator[](Index i) const { return m_indices(i); }
00124     /** Direct access to the underlying index vector */
00125     inline Index& operator[](Index i) { return m_indices(i); }
00126 
00127     /** const version of indices(). */
00128     const IndicesType& indices() const { return m_indices; }
00129     /** \returns a reference to the stored array representing the transpositions. */
00130     IndicesType& indices() { return m_indices; }
00131 
00132     /** Resizes to given size. */
00133     inline void resize(int size)
00134     {
00135       m_indices.resize(size);
00136     }
00137 
00138     /** Sets \c *this to represents an identity transformation */
00139     void setIdentity()
00140     {
00141       for(int i = 0; i < m_indices.size(); ++i)
00142         m_indices.coeffRef(i) = i;
00143     }
00144 
00145     // FIXME: do we want such methods ?
00146     // might be usefull when the target matrix expression is complex, e.g.:
00147     // object.matrix().block(..,..,..,..) = trans * object.matrix().block(..,..,..,..);
00148     /*
00149     template<typename MatrixType>
00150     void applyForwardToRows(MatrixType& mat) const
00151     {
00152       for(Index k=0 ; k<size() ; ++k)
00153         if(m_indices(k)!=k)
00154           mat.row(k).swap(mat.row(m_indices(k)));
00155     }
00156 
00157     template<typename MatrixType>
00158     void applyBackwardToRows(MatrixType& mat) const
00159     {
00160       for(Index k=size()-1 ; k>=0 ; --k)
00161         if(m_indices(k)!=k)
00162           mat.row(k).swap(mat.row(m_indices(k)));
00163     }
00164     */
00165 
00166     /** \returns the inverse transformation */
00167     inline Transpose<Transpositions> inverse() const
00168     { return *this; }
00169 
00170     /** \returns the tranpose transformation */
00171     inline Transpose<Transpositions> transpose() const
00172     { return *this; }
00173 
00174 #ifndef EIGEN_PARSED_BY_DOXYGEN
00175     template<int OtherSize, int OtherMaxSize>
00176     Transpositions(const Transpose<Transpositions<OtherSize,OtherMaxSize> >& other)
00177       : m_indices(other.size())
00178     {
00179       Index n = size();
00180       Index j = size-1;
00181       for(Index i=0; i<n;++i,--j)
00182         m_indices.coeffRef(j) = other.nestedTranspositions().indices().coeff(i);
00183     }
00184 #endif
00185 
00186   protected:
00187 
00188     IndicesType m_indices;
00189 };
00190 
00191 /** \returns the \a matrix with the \a transpositions applied to the columns.
00192   */
00193 template<typename Derived, int SizeAtCompileTime, int MaxSizeAtCompileTime>
00194 inline const internal::transposition_matrix_product_retval<Transpositions<SizeAtCompileTime, MaxSizeAtCompileTime>, Derived, OnTheRight>
00195 operator*(const MatrixBase<Derived>& matrix,
00196           const Transpositions<SizeAtCompileTime, MaxSizeAtCompileTime> &transpositions)
00197 {
00198   return internal::transposition_matrix_product_retval
00199            <Transpositions<SizeAtCompileTime, MaxSizeAtCompileTime>, Derived, OnTheRight>
00200            (transpositions, matrix.derived());
00201 }
00202 
00203 /** \returns the \a matrix with the \a transpositions applied to the rows.
00204   */
00205 template<typename Derived, int SizeAtCompileTime, int MaxSizeAtCompileTime>
00206 inline const internal::transposition_matrix_product_retval
00207                <Transpositions<SizeAtCompileTime, MaxSizeAtCompileTime>, Derived, OnTheLeft>
00208 operator*(const Transpositions<SizeAtCompileTime, MaxSizeAtCompileTime> &transpositions,
00209           const MatrixBase<Derived>& matrix)
00210 {
00211   return internal::transposition_matrix_product_retval
00212            <Transpositions<SizeAtCompileTime, MaxSizeAtCompileTime>, Derived, OnTheLeft>
00213            (transpositions, matrix.derived());
00214 }
00215 
00216 namespace internal {
00217 
00218 template<typename TranspositionType, typename MatrixType, int Side, bool Transposed>
00219 struct traits<transposition_matrix_product_retval<TranspositionType, MatrixType, Side, Transposed> >
00220 {
00221   typedef typename MatrixType::PlainObject ReturnType;
00222 };
00223 
00224 template<typename TranspositionType, typename MatrixType, int Side, bool Transposed>
00225 struct transposition_matrix_product_retval
00226  : public ReturnByValue<transposition_matrix_product_retval<TranspositionType, MatrixType, Side, Transposed> >
00227 {
00228     typedef typename remove_all<typename MatrixType::Nested>::type MatrixTypeNestedCleaned;
00229     typedef typename TranspositionType::Index Index;
00230 
00231     transposition_matrix_product_retval(const TranspositionType& tr, const MatrixType& matrix)
00232       : m_transpositions(tr), m_matrix(matrix)
00233     {}
00234 
00235     inline int rows() const { return m_matrix.rows(); }
00236     inline int cols() const { return m_matrix.cols(); }
00237 
00238     template<typename Dest> inline void evalTo(Dest& dst) const
00239     {
00240       const int size = m_transpositions.size();
00241       Index j = 0;
00242 
00243       if(!(is_same<MatrixTypeNestedCleaned,Dest>::value && extract_data(dst) == extract_data(m_matrix)))
00244         dst = m_matrix;
00245 
00246       for(int k=(Transposed?size-1:0) ; Transposed?k>=0:k<size ; Transposed?--k:++k)
00247         if((j=m_transpositions.coeff(k))!=k)
00248         {
00249           if(Side==OnTheLeft)
00250             dst.row(k).swap(dst.row(j));
00251           else if(Side==OnTheRight)
00252             dst.col(k).swap(dst.col(j));
00253         }
00254     }
00255 
00256   protected:
00257     const TranspositionType& m_transpositions;
00258     const typename MatrixType::Nested m_matrix;
00259 };
00260 
00261 } // end namespace internal
00262 
00263 /* Template partial specialization for transposed/inverse transpositions */
00264 
00265 template<int SizeAtCompileTime, int MaxSizeAtCompileTime>
00266 class Transpose<Transpositions<SizeAtCompileTime, MaxSizeAtCompileTime> >
00267 {
00268     typedef Transpositions<SizeAtCompileTime, MaxSizeAtCompileTime> TranspositionType;
00269     typedef typename TranspositionType::IndicesType IndicesType;
00270   public:
00271 
00272     Transpose(const TranspositionType& t) : m_transpositions(t) {}
00273 
00274     inline int size() const { return m_transpositions.size(); }
00275 
00276     /** \returns the \a matrix with the inverse transpositions applied to the columns.
00277       */
00278     template<typename Derived> friend
00279     inline const internal::transposition_matrix_product_retval<TranspositionType, Derived, OnTheRight, true>
00280     operator*(const MatrixBase<Derived>& matrix, const Transpose& trt)
00281     {
00282       return internal::transposition_matrix_product_retval<TranspositionType, Derived, OnTheRight, true>(trt.m_transpositions, matrix.derived());
00283     }
00284 
00285     /** \returns the \a matrix with the inverse transpositions applied to the rows.
00286       */
00287     template<typename Derived>
00288     inline const internal::transposition_matrix_product_retval<TranspositionType, Derived, OnTheLeft, true>
00289     operator*(const MatrixBase<Derived>& matrix) const
00290     {
00291       return internal::transposition_matrix_product_retval<TranspositionType, Derived, OnTheLeft, true>(m_transpositions, matrix.derived());
00292     }
00293 
00294     const TranspositionType& nestedTranspositions() const { return m_transpositions; }
00295 
00296   protected:
00297     const TranspositionType& m_transpositions;
00298 };
00299 
00300 #endif // EIGEN_TRANSPOSITIONS_H



Page generated by Doxygen 1.7.3 for MRPT 0.9.4 SVN: at Sat Mar 26 06:40:17 UTC 2011