Transpose.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) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
00005 // Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
00006 //
00007 // Eigen is free software; you can redistribute it and/or
00008 // modify it under the terms of the GNU Lesser General Public
00009 // License as published by the Free Software Foundation; either
00010 // version 3 of the License, or (at your option) any later version.
00011 //
00012 // Alternatively, you can redistribute it and/or
00013 // modify it under the terms of the GNU General Public License as
00014 // published by the Free Software Foundation; either version 2 of
00015 // the License, or (at your option) any later version.
00016 //
00017 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
00018 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00019 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
00020 // GNU General Public License for more details.
00021 //
00022 // You should have received a copy of the GNU Lesser General Public
00023 // License and a copy of the GNU General Public License along with
00024 // Eigen. If not, see <http://www.gnu.org/licenses/>.
00025 
00026 #ifndef EIGEN_TRANSPOSE_H
00027 #define EIGEN_TRANSPOSE_H
00028 
00029 namespace Eigen { 
00030 
00045 namespace internal {
00046 template<typename MatrixType>
00047 struct traits<Transpose<MatrixType> > : traits<MatrixType>
00048 {
00049   typedef typename MatrixType::Scalar Scalar;
00050   typedef typename nested<MatrixType>::type MatrixTypeNested;
00051   typedef typename remove_reference<MatrixTypeNested>::type MatrixTypeNestedPlain;
00052   typedef typename traits<MatrixType>::StorageKind StorageKind;
00053   typedef typename traits<MatrixType>::XprKind XprKind;
00054   enum {
00055     RowsAtCompileTime = MatrixType::ColsAtCompileTime,
00056     ColsAtCompileTime = MatrixType::RowsAtCompileTime,
00057     MaxRowsAtCompileTime = MatrixType::MaxColsAtCompileTime,
00058     MaxColsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
00059     FlagsLvalueBit = is_lvalue<MatrixType>::value ? LvalueBit : 0,
00060     Flags0 = MatrixTypeNestedPlain::Flags & ~(LvalueBit | NestByRefBit),
00061     Flags1 = Flags0 | FlagsLvalueBit,
00062     Flags = Flags1 ^ RowMajorBit,
00063     CoeffReadCost = MatrixTypeNestedPlain::CoeffReadCost,
00064     InnerStrideAtCompileTime = inner_stride_at_compile_time<MatrixType>::ret,
00065     OuterStrideAtCompileTime = outer_stride_at_compile_time<MatrixType>::ret
00066   };
00067 };
00068 }
00069 
00070 template<typename MatrixType, typename StorageKind> class TransposeImpl;
00071 
00072 template<typename MatrixType> class Transpose
00073   : public TransposeImpl<MatrixType,typename internal::traits<MatrixType>::StorageKind>
00074 {
00075   public:
00076 
00077     typedef typename TransposeImpl<MatrixType,typename internal::traits<MatrixType>::StorageKind>::Base Base;
00078     EIGEN_GENERIC_PUBLIC_INTERFACE(Transpose)
00079 
00080     inline Transpose(MatrixType& matrix) : m_matrix(matrix) {}
00081 
00082     EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Transpose)
00083 
00084     inline Index rows() const { return m_matrix.cols(); }
00085     inline Index cols() const { return m_matrix.rows(); }
00086 
00088     const typename internal::remove_all<typename MatrixType::Nested>::type&
00089     nestedExpression() const { return m_matrix; }
00090 
00092     typename internal::remove_all<typename MatrixType::Nested>::type&
00093     nestedExpression() { return m_matrix.const_cast_derived(); }
00094 
00095   protected:
00096     typename MatrixType::Nested m_matrix;
00097 };
00098 
00099 namespace internal {
00100 
00101 template<typename MatrixType, bool HasDirectAccess = has_direct_access<MatrixType>::ret>
00102 struct TransposeImpl_base
00103 {
00104   typedef typename dense_xpr_base<Transpose<MatrixType> >::type type;
00105 };
00106 
00107 template<typename MatrixType>
00108 struct TransposeImpl_base<MatrixType, false>
00109 {
00110   typedef typename dense_xpr_base<Transpose<MatrixType> >::type type;
00111 };
00112 
00113 } // end namespace internal
00114 
00115 template<typename MatrixType> class TransposeImpl<MatrixType,Dense>
00116   : public internal::TransposeImpl_base<MatrixType>::type
00117 {
00118   public:
00119 
00120     typedef typename internal::TransposeImpl_base<MatrixType>::type Base;
00121     EIGEN_DENSE_PUBLIC_INTERFACE(Transpose<MatrixType>)
00122 
00123     inline Index innerStride() const { return derived().nestedExpression().innerStride(); }
00124     inline Index outerStride() const { return derived().nestedExpression().outerStride(); }
00125 
00126     typedef typename internal::conditional<
00127                        internal::is_lvalue<MatrixType>::value,
00128                        Scalar,
00129                        const Scalar
00130                      >::type ScalarWithConstIfNotLvalue;
00131 
00132     inline ScalarWithConstIfNotLvalue* data() { return derived().nestedExpression().data(); }
00133     inline const Scalar* data() const { return derived().nestedExpression().data(); }
00134 
00135     inline ScalarWithConstIfNotLvalue& coeffRef(Index row, Index col)
00136     {
00137       EIGEN_STATIC_ASSERT_LVALUE(MatrixType)
00138       return derived().nestedExpression().const_cast_derived().coeffRef(col, row);
00139     }
00140 
00141     inline ScalarWithConstIfNotLvalue& coeffRef(Index index)
00142     {
00143       EIGEN_STATIC_ASSERT_LVALUE(MatrixType)
00144       return derived().nestedExpression().const_cast_derived().coeffRef(index);
00145     }
00146 
00147     inline const Scalar& coeffRef(Index row, Index col) const
00148     {
00149       return derived().nestedExpression().coeffRef(col, row);
00150     }
00151 
00152     inline const Scalar& coeffRef(Index index) const
00153     {
00154       return derived().nestedExpression().coeffRef(index);
00155     }
00156 
00157     inline CoeffReturnType coeff(Index row, Index col) const
00158     {
00159       return derived().nestedExpression().coeff(col, row);
00160     }
00161 
00162     inline CoeffReturnType coeff(Index index) const
00163     {
00164       return derived().nestedExpression().coeff(index);
00165     }
00166 
00167     template<int LoadMode>
00168     inline const PacketScalar packet(Index row, Index col) const
00169     {
00170       return derived().nestedExpression().template packet<LoadMode>(col, row);
00171     }
00172 
00173     template<int LoadMode>
00174     inline void writePacket(Index row, Index col, const PacketScalar& x)
00175     {
00176       derived().nestedExpression().const_cast_derived().template writePacket<LoadMode>(col, row, x);
00177     }
00178 
00179     template<int LoadMode>
00180     inline const PacketScalar packet(Index index) const
00181     {
00182       return derived().nestedExpression().template packet<LoadMode>(index);
00183     }
00184 
00185     template<int LoadMode>
00186     inline void writePacket(Index index, const PacketScalar& x)
00187     {
00188       derived().nestedExpression().const_cast_derived().template writePacket<LoadMode>(index, x);
00189     }
00190 };
00191 
00211 template<typename Derived>
00212 inline Transpose<Derived>
00213 DenseBase<Derived>::transpose()
00214 {
00215   return derived();
00216 }
00217 
00223 template<typename Derived>
00224 inline const typename DenseBase<Derived>::ConstTransposeReturnType
00225 DenseBase<Derived>::transpose() const
00226 {
00227   return ConstTransposeReturnType(derived());
00228 }
00229 
00249 template<typename Derived>
00250 inline const typename MatrixBase<Derived>::AdjointReturnType
00251 MatrixBase<Derived>::adjoint() const
00252 {
00253   return this->transpose(); // in the complex case, the .conjugate() is be implicit here
00254                             // due to implicit conversion to return type
00255 }
00256 
00257 /***************************************************************************
00258 * "in place" transpose implementation
00259 ***************************************************************************/
00260 
00261 namespace internal {
00262 
00263 template<typename MatrixType,
00264   bool IsSquare = (MatrixType::RowsAtCompileTime == MatrixType::ColsAtCompileTime) && MatrixType::RowsAtCompileTime!=Dynamic>
00265 struct inplace_transpose_selector;
00266 
00267 template<typename MatrixType>
00268 struct inplace_transpose_selector<MatrixType,true> { // square matrix
00269   static void run(MatrixType& m) {
00270     m.template triangularView<StrictlyUpper>().swap(m.transpose());
00271   }
00272 };
00273 
00274 template<typename MatrixType>
00275 struct inplace_transpose_selector<MatrixType,false> { // non square matrix
00276   static void run(MatrixType& m) {
00277     if (m.rows()==m.cols())
00278       m.template triangularView<StrictlyUpper>().swap(m.transpose());
00279     else
00280       m = m.transpose().eval();
00281   }
00282 };
00283 
00284 } // end namespace internal
00285 
00304 template<typename Derived>
00305 inline void DenseBase<Derived>::transposeInPlace()
00306 {
00307   internal::inplace_transpose_selector<Derived>::run(derived());
00308 }
00309 
00310 /***************************************************************************
00311 * "in place" adjoint implementation
00312 ***************************************************************************/
00313 
00332 template<typename Derived>
00333 inline void MatrixBase<Derived>::adjointInPlace()
00334 {
00335   derived() = adjoint().eval();
00336 }
00337 
00338 #ifndef EIGEN_NO_DEBUG
00339 
00340 // The following is to detect aliasing problems in most common cases.
00341 
00342 namespace internal {
00343 
00344 template<typename BinOp,typename NestedXpr,typename Rhs>
00345 struct blas_traits<SelfCwiseBinaryOp<BinOp,NestedXpr,Rhs> >
00346  : blas_traits<NestedXpr>
00347 {
00348   typedef SelfCwiseBinaryOp<BinOp,NestedXpr,Rhs> XprType;
00349   static inline const XprType extract(const XprType& x) { return x; }
00350 };
00351 
00352 template<bool DestIsTransposed, typename OtherDerived>
00353 struct check_transpose_aliasing_compile_time_selector
00354 {
00355   enum { ret = bool(blas_traits<OtherDerived>::IsTransposed) != DestIsTransposed };
00356 };
00357 
00358 template<bool DestIsTransposed, typename BinOp, typename DerivedA, typename DerivedB>
00359 struct check_transpose_aliasing_compile_time_selector<DestIsTransposed,CwiseBinaryOp<BinOp,DerivedA,DerivedB> >
00360 {
00361   enum { ret =    bool(blas_traits<DerivedA>::IsTransposed) != DestIsTransposed
00362                || bool(blas_traits<DerivedB>::IsTransposed) != DestIsTransposed
00363   };
00364 };
00365 
00366 template<typename Scalar, bool DestIsTransposed, typename OtherDerived>
00367 struct check_transpose_aliasing_run_time_selector
00368 {
00369   static bool run(const Scalar* dest, const OtherDerived& src)
00370   {
00371     return (bool(blas_traits<OtherDerived>::IsTransposed) != DestIsTransposed) && (dest!=0 && dest==(Scalar*)extract_data(src));
00372   }
00373 };
00374 
00375 template<typename Scalar, bool DestIsTransposed, typename BinOp, typename DerivedA, typename DerivedB>
00376 struct check_transpose_aliasing_run_time_selector<Scalar,DestIsTransposed,CwiseBinaryOp<BinOp,DerivedA,DerivedB> >
00377 {
00378   static bool run(const Scalar* dest, const CwiseBinaryOp<BinOp,DerivedA,DerivedB>& src)
00379   {
00380     return ((blas_traits<DerivedA>::IsTransposed != DestIsTransposed) && (dest!=0 && dest==(Scalar*)extract_data(src.lhs())))
00381         || ((blas_traits<DerivedB>::IsTransposed != DestIsTransposed) && (dest!=0 && dest==(Scalar*)extract_data(src.rhs())));
00382   }
00383 };
00384 
00385 // the following selector, checkTransposeAliasing_impl, based on MightHaveTransposeAliasing,
00386 // is because when the condition controlling the assert is known at compile time, ICC emits a warning.
00387 // This is actually a good warning: in expressions that don't have any transposing, the condition is
00388 // known at compile time to be false, and using that, we can avoid generating the code of the assert again
00389 // and again for all these expressions that don't need it.
00390 
00391 template<typename Derived, typename OtherDerived,
00392          bool MightHaveTransposeAliasing
00393                  = check_transpose_aliasing_compile_time_selector
00394                      <blas_traits<Derived>::IsTransposed,OtherDerived>::ret
00395         >
00396 struct checkTransposeAliasing_impl
00397 {
00398     static void run(const Derived& dst, const OtherDerived& other)
00399     {
00400         eigen_assert((!check_transpose_aliasing_run_time_selector
00401                       <typename Derived::Scalar,blas_traits<Derived>::IsTransposed,OtherDerived>
00402                       ::run(extract_data(dst), other))
00403           && "aliasing detected during tranposition, use transposeInPlace() "
00404              "or evaluate the rhs into a temporary using .eval()");
00405 
00406     }
00407 };
00408 
00409 template<typename Derived, typename OtherDerived>
00410 struct checkTransposeAliasing_impl<Derived, OtherDerived, false>
00411 {
00412     static void run(const Derived&, const OtherDerived&)
00413     {
00414     }
00415 };
00416 
00417 } // end namespace internal
00418 
00419 template<typename Derived>
00420 template<typename OtherDerived>
00421 void DenseBase<Derived>::checkTransposeAliasing(const OtherDerived& other) const
00422 {
00423     internal::checkTransposeAliasing_impl<Derived, OtherDerived>::run(derived(), other);
00424 }
00425 #endif
00426 
00427 } // end namespace Eigen
00428 
00429 #endif // EIGEN_TRANSPOSE_H