Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Transpose.h
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 // This Source Code Form is subject to the terms of the Mozilla 00008 // Public License v. 2.0. If a copy of the MPL was not distributed 00009 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 00010 00011 #ifndef EIGEN_TRANSPOSE_H 00012 #define EIGEN_TRANSPOSE_H 00013 00014 namespace Eigen { 00015 00016 /** \class Transpose 00017 * \ingroup Core_Module 00018 * 00019 * \brief Expression of the transpose of a matrix 00020 * 00021 * \param MatrixType the type of the object of which we are taking the transpose 00022 * 00023 * This class represents an expression of the transpose of a matrix. 00024 * It is the return type of MatrixBase::transpose() and MatrixBase::adjoint() 00025 * and most of the time this is the only way it is used. 00026 * 00027 * \sa MatrixBase::transpose(), MatrixBase::adjoint() 00028 */ 00029 00030 namespace internal { 00031 template<typename MatrixType> 00032 struct traits<Transpose<MatrixType> > : traits<MatrixType> 00033 { 00034 typedef typename MatrixType::Scalar Scalar; 00035 typedef typename nested<MatrixType>::type MatrixTypeNested; 00036 typedef typename remove_reference<MatrixTypeNested>::type MatrixTypeNestedPlain; 00037 typedef typename traits<MatrixType>::StorageKind StorageKind; 00038 typedef typename traits<MatrixType>::XprKind XprKind; 00039 enum { 00040 RowsAtCompileTime = MatrixType::ColsAtCompileTime, 00041 ColsAtCompileTime = MatrixType::RowsAtCompileTime, 00042 MaxRowsAtCompileTime = MatrixType::MaxColsAtCompileTime, 00043 MaxColsAtCompileTime = MatrixType::MaxRowsAtCompileTime, 00044 FlagsLvalueBit = is_lvalue<MatrixType>::value ? LvalueBit : 0, 00045 Flags0 = MatrixTypeNestedPlain::Flags & ~(LvalueBit | NestByRefBit), 00046 Flags1 = Flags0 | FlagsLvalueBit, 00047 Flags = Flags1 ^ RowMajorBit, 00048 CoeffReadCost = MatrixTypeNestedPlain::CoeffReadCost, 00049 InnerStrideAtCompileTime = inner_stride_at_compile_time<MatrixType>::ret, 00050 OuterStrideAtCompileTime = outer_stride_at_compile_time<MatrixType>::ret 00051 }; 00052 }; 00053 } 00054 00055 template<typename MatrixType, typename StorageKind> class TransposeImpl; 00056 00057 template<typename MatrixType> class Transpose 00058 : public TransposeImpl<MatrixType,typename internal::traits<MatrixType>::StorageKind> 00059 { 00060 public: 00061 00062 typedef typename TransposeImpl<MatrixType,typename internal::traits<MatrixType>::StorageKind>::Base Base; 00063 EIGEN_GENERIC_PUBLIC_INTERFACE(Transpose) 00064 00065 inline Transpose(MatrixType& a_matrix) : m_matrix(a_matrix) {} 00066 00067 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Transpose) 00068 00069 inline Index rows() const { return m_matrix.cols(); } 00070 inline Index cols() const { return m_matrix.rows(); } 00071 00072 /** \returns the nested expression */ 00073 const typename internal::remove_all<typename MatrixType::Nested>::type& 00074 nestedExpression () const { return m_matrix; } 00075 00076 /** \returns the nested expression */ 00077 typename internal::remove_all<typename MatrixType::Nested>::type& 00078 nestedExpression () { return m_matrix.const_cast_derived(); } 00079 00080 protected: 00081 typename MatrixType::Nested m_matrix; 00082 }; 00083 00084 namespace internal { 00085 00086 template<typename MatrixType, bool HasDirectAccess = has_direct_access<MatrixType>::ret> 00087 struct TransposeImpl_base 00088 { 00089 typedef typename dense_xpr_base<Transpose<MatrixType> >::type type; 00090 }; 00091 00092 template<typename MatrixType> 00093 struct TransposeImpl_base<MatrixType, false> 00094 { 00095 typedef typename dense_xpr_base<Transpose<MatrixType> >::type type; 00096 }; 00097 00098 } // end namespace internal 00099 00100 template<typename MatrixType> class TransposeImpl<MatrixType,Dense> 00101 : public internal::TransposeImpl_base<MatrixType>::type 00102 { 00103 public: 00104 00105 typedef typename internal::TransposeImpl_base<MatrixType>::type Base; 00106 EIGEN_DENSE_PUBLIC_INTERFACE(Transpose<MatrixType>) 00107 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(TransposeImpl) 00108 00109 inline Index innerStride() const { return derived().nestedExpression().innerStride(); } 00110 inline Index outerStride() const { return derived().nestedExpression().outerStride(); } 00111 00112 typedef typename internal::conditional< 00113 internal::is_lvalue<MatrixType>::value, 00114 Scalar, 00115 const Scalar 00116 >::type ScalarWithConstIfNotLvalue; 00117 00118 inline ScalarWithConstIfNotLvalue* data() { return derived().nestedExpression().data(); } 00119 inline const Scalar* data() const { return derived().nestedExpression().data(); } 00120 00121 inline ScalarWithConstIfNotLvalue& coeffRef(Index rowId, Index colId) 00122 { 00123 EIGEN_STATIC_ASSERT_LVALUE(MatrixType) 00124 return derived().nestedExpression().const_cast_derived().coeffRef(colId, rowId); 00125 } 00126 00127 inline ScalarWithConstIfNotLvalue& coeffRef(Index index) 00128 { 00129 EIGEN_STATIC_ASSERT_LVALUE(MatrixType) 00130 return derived().nestedExpression().const_cast_derived().coeffRef(index); 00131 } 00132 00133 inline const Scalar& coeffRef(Index rowId, Index colId) const 00134 { 00135 return derived().nestedExpression().coeffRef(colId, rowId); 00136 } 00137 00138 inline const Scalar& coeffRef(Index index) const 00139 { 00140 return derived().nestedExpression().coeffRef(index); 00141 } 00142 00143 inline CoeffReturnType coeff(Index rowId, Index colId) const 00144 { 00145 return derived().nestedExpression().coeff(colId, rowId); 00146 } 00147 00148 inline CoeffReturnType coeff(Index index) const 00149 { 00150 return derived().nestedExpression().coeff(index); 00151 } 00152 00153 template<int LoadMode> 00154 inline const PacketScalar packet(Index rowId, Index colId) const 00155 { 00156 return derived().nestedExpression().template packet<LoadMode>(colId, rowId); 00157 } 00158 00159 template<int LoadMode> 00160 inline void writePacket(Index rowId, Index colId, const PacketScalar& x) 00161 { 00162 derived().nestedExpression().const_cast_derived().template writePacket<LoadMode>(colId, rowId, x); 00163 } 00164 00165 template<int LoadMode> 00166 inline const PacketScalar packet(Index index) const 00167 { 00168 return derived().nestedExpression().template packet<LoadMode>(index); 00169 } 00170 00171 template<int LoadMode> 00172 inline void writePacket(Index index, const PacketScalar& x) 00173 { 00174 derived().nestedExpression().const_cast_derived().template writePacket<LoadMode>(index, x); 00175 } 00176 }; 00177 00178 /** \returns an expression of the transpose of *this. 00179 * 00180 * Example: \include MatrixBase_transpose.cpp 00181 * Output: \verbinclude MatrixBase_transpose.out 00182 * 00183 * \warning If you want to replace a matrix by its own transpose, do \b NOT do this: 00184 * \code 00185 * m = m.transpose(); // bug!!! caused by aliasing effect 00186 * \endcode 00187 * Instead, use the transposeInPlace() method: 00188 * \code 00189 * m.transposeInPlace(); 00190 * \endcode 00191 * which gives Eigen good opportunities for optimization, or alternatively you can also do: 00192 * \code 00193 * m = m.transpose().eval(); 00194 * \endcode 00195 * 00196 * \sa transposeInPlace(), adjoint() */ 00197 template<typename Derived> 00198 inline Transpose<Derived> 00199 DenseBase<Derived>::transpose() 00200 { 00201 return derived(); 00202 } 00203 00204 /** This is the const version of transpose(). 00205 * 00206 * Make sure you read the warning for transpose() ! 00207 * 00208 * \sa transposeInPlace(), adjoint() */ 00209 template<typename Derived> 00210 inline typename DenseBase<Derived>::ConstTransposeReturnType 00211 DenseBase<Derived>::transpose() const 00212 { 00213 return ConstTransposeReturnType(derived()); 00214 } 00215 00216 /** \returns an expression of the adjoint (i.e. conjugate transpose) of *this. 00217 * 00218 * Example: \include MatrixBase_adjoint.cpp 00219 * Output: \verbinclude MatrixBase_adjoint.out 00220 * 00221 * \warning If you want to replace a matrix by its own adjoint, do \b NOT do this: 00222 * \code 00223 * m = m.adjoint(); // bug!!! caused by aliasing effect 00224 * \endcode 00225 * Instead, use the adjointInPlace() method: 00226 * \code 00227 * m.adjointInPlace(); 00228 * \endcode 00229 * which gives Eigen good opportunities for optimization, or alternatively you can also do: 00230 * \code 00231 * m = m.adjoint().eval(); 00232 * \endcode 00233 * 00234 * \sa adjointInPlace(), transpose(), conjugate(), class Transpose, class internal::scalar_conjugate_op */ 00235 template<typename Derived> 00236 inline const typename MatrixBase<Derived>::AdjointReturnType 00237 MatrixBase<Derived>::adjoint() const 00238 { 00239 return this->transpose(); // in the complex case, the .conjugate() is be implicit here 00240 // due to implicit conversion to return type 00241 } 00242 00243 /*************************************************************************** 00244 * "in place" transpose implementation 00245 ***************************************************************************/ 00246 00247 namespace internal { 00248 00249 template<typename MatrixType, 00250 bool IsSquare = (MatrixType::RowsAtCompileTime == MatrixType::ColsAtCompileTime) && MatrixType::RowsAtCompileTime!=Dynamic> 00251 struct inplace_transpose_selector; 00252 00253 template<typename MatrixType> 00254 struct inplace_transpose_selector<MatrixType,true> { // square matrix 00255 static void run(MatrixType& m) { 00256 m.matrix().template triangularView<StrictlyUpper>().swap(m.matrix().transpose()); 00257 } 00258 }; 00259 00260 template<typename MatrixType> 00261 struct inplace_transpose_selector<MatrixType,false> { // non square matrix 00262 static void run(MatrixType& m) { 00263 if (m.rows()==m.cols()) 00264 m.matrix().template triangularView<StrictlyUpper>().swap(m.matrix().transpose()); 00265 else 00266 m = m.transpose().eval(); 00267 } 00268 }; 00269 00270 } // end namespace internal 00271 00272 /** This is the "in place" version of transpose(): it replaces \c *this by its own transpose. 00273 * Thus, doing 00274 * \code 00275 * m.transposeInPlace(); 00276 * \endcode 00277 * has the same effect on m as doing 00278 * \code 00279 * m = m.transpose().eval(); 00280 * \endcode 00281 * and is faster and also safer because in the latter line of code, forgetting the eval() results 00282 * in a bug caused by \ref TopicAliasing "aliasing". 00283 * 00284 * Notice however that this method is only useful if you want to replace a matrix by its own transpose. 00285 * If you just need the transpose of a matrix, use transpose(). 00286 * 00287 * \note if the matrix is not square, then \c *this must be a resizable matrix. 00288 * This excludes (non-square) fixed-size matrices, block-expressions and maps. 00289 * 00290 * \sa transpose(), adjoint(), adjointInPlace() */ 00291 template<typename Derived> 00292 inline void DenseBase<Derived>::transposeInPlace() 00293 { 00294 eigen_assert((rows() == cols() || (RowsAtCompileTime == Dynamic && ColsAtCompileTime == Dynamic)) 00295 && "transposeInPlace() called on a non-square non-resizable matrix"); 00296 internal::inplace_transpose_selector<Derived>::run(derived()); 00297 } 00298 00299 /*************************************************************************** 00300 * "in place" adjoint implementation 00301 ***************************************************************************/ 00302 00303 /** This is the "in place" version of adjoint(): it replaces \c *this by its own transpose. 00304 * Thus, doing 00305 * \code 00306 * m.adjointInPlace(); 00307 * \endcode 00308 * has the same effect on m as doing 00309 * \code 00310 * m = m.adjoint().eval(); 00311 * \endcode 00312 * and is faster and also safer because in the latter line of code, forgetting the eval() results 00313 * in a bug caused by aliasing. 00314 * 00315 * Notice however that this method is only useful if you want to replace a matrix by its own adjoint. 00316 * If you just need the adjoint of a matrix, use adjoint(). 00317 * 00318 * \note if the matrix is not square, then \c *this must be a resizable matrix. 00319 * This excludes (non-square) fixed-size matrices, block-expressions and maps. 00320 * 00321 * \sa transpose(), adjoint(), transposeInPlace() */ 00322 template<typename Derived> 00323 inline void MatrixBase<Derived>::adjointInPlace() 00324 { 00325 derived() = adjoint().eval(); 00326 } 00327 00328 #ifndef EIGEN_NO_DEBUG 00329 00330 // The following is to detect aliasing problems in most common cases. 00331 00332 namespace internal { 00333 00334 template<typename BinOp,typename NestedXpr,typename Rhs> 00335 struct blas_traits<SelfCwiseBinaryOp<BinOp,NestedXpr,Rhs> > 00336 : blas_traits<NestedXpr> 00337 { 00338 typedef SelfCwiseBinaryOp<BinOp,NestedXpr,Rhs> XprType; 00339 static inline const XprType extract(const XprType& x) { return x; } 00340 }; 00341 00342 template<bool DestIsTransposed, typename OtherDerived> 00343 struct check_transpose_aliasing_compile_time_selector 00344 { 00345 enum { ret = bool(blas_traits<OtherDerived>::IsTransposed) != DestIsTransposed }; 00346 }; 00347 00348 template<bool DestIsTransposed, typename BinOp, typename DerivedA, typename DerivedB> 00349 struct check_transpose_aliasing_compile_time_selector<DestIsTransposed,CwiseBinaryOp<BinOp,DerivedA,DerivedB> > 00350 { 00351 enum { ret = bool(blas_traits<DerivedA>::IsTransposed) != DestIsTransposed 00352 || bool(blas_traits<DerivedB>::IsTransposed) != DestIsTransposed 00353 }; 00354 }; 00355 00356 template<typename Scalar, bool DestIsTransposed, typename OtherDerived> 00357 struct check_transpose_aliasing_run_time_selector 00358 { 00359 static bool run(const Scalar* dest, const OtherDerived& src) 00360 { 00361 return (bool(blas_traits<OtherDerived>::IsTransposed) != DestIsTransposed) && (dest!=0 && dest==(const Scalar*)extract_data(src)); 00362 } 00363 }; 00364 00365 template<typename Scalar, bool DestIsTransposed, typename BinOp, typename DerivedA, typename DerivedB> 00366 struct check_transpose_aliasing_run_time_selector<Scalar,DestIsTransposed,CwiseBinaryOp<BinOp,DerivedA,DerivedB> > 00367 { 00368 static bool run(const Scalar* dest, const CwiseBinaryOp<BinOp,DerivedA,DerivedB>& src) 00369 { 00370 return ((blas_traits<DerivedA>::IsTransposed != DestIsTransposed) && (dest!=0 && dest==(const Scalar*)extract_data(src.lhs()))) 00371 || ((blas_traits<DerivedB>::IsTransposed != DestIsTransposed) && (dest!=0 && dest==(const Scalar*)extract_data(src.rhs()))); 00372 } 00373 }; 00374 00375 // the following selector, checkTransposeAliasing_impl, based on MightHaveTransposeAliasing, 00376 // is because when the condition controlling the assert is known at compile time, ICC emits a warning. 00377 // This is actually a good warning: in expressions that don't have any transposing, the condition is 00378 // known at compile time to be false, and using that, we can avoid generating the code of the assert again 00379 // and again for all these expressions that don't need it. 00380 00381 template<typename Derived, typename OtherDerived, 00382 bool MightHaveTransposeAliasing 00383 = check_transpose_aliasing_compile_time_selector 00384 <blas_traits<Derived>::IsTransposed,OtherDerived>::ret 00385 > 00386 struct checkTransposeAliasing_impl 00387 { 00388 static void run(const Derived& dst, const OtherDerived& other) 00389 { 00390 eigen_assert((!check_transpose_aliasing_run_time_selector 00391 <typename Derived::Scalar,blas_traits<Derived>::IsTransposed,OtherDerived> 00392 ::run(extract_data(dst), other)) 00393 && "aliasing detected during transposition, use transposeInPlace() " 00394 "or evaluate the rhs into a temporary using .eval()"); 00395 00396 } 00397 }; 00398 00399 template<typename Derived, typename OtherDerived> 00400 struct checkTransposeAliasing_impl<Derived, OtherDerived, false> 00401 { 00402 static void run(const Derived&, const OtherDerived&) 00403 { 00404 } 00405 }; 00406 00407 } // end namespace internal 00408 00409 template<typename Derived> 00410 template<typename OtherDerived> 00411 void DenseBase<Derived>::checkTransposeAliasing(const OtherDerived& other) const 00412 { 00413 internal::checkTransposeAliasing_impl<Derived, OtherDerived>::run(derived(), other); 00414 } 00415 #endif 00416 00417 } // end namespace Eigen 00418 00419 #endif // EIGEN_TRANSPOSE_H
Generated on Thu Nov 17 2022 22:01:30 by
1.7.2