![]() |
Eigen
3.3.3
|
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-2014 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 namespace internal { 00017 template<typename MatrixType> 00018 struct traits<Transpose<MatrixType> > : public traits<MatrixType> 00019 { 00020 typedef typename ref_selector<MatrixType>::type MatrixTypeNested; 00021 typedef typename remove_reference<MatrixTypeNested>::type MatrixTypeNestedPlain; 00022 enum { 00023 RowsAtCompileTime = MatrixType::ColsAtCompileTime, 00024 ColsAtCompileTime = MatrixType::RowsAtCompileTime, 00025 MaxRowsAtCompileTime = MatrixType::MaxColsAtCompileTime, 00026 MaxColsAtCompileTime = MatrixType::MaxRowsAtCompileTime, 00027 FlagsLvalueBit = is_lvalue<MatrixType>::value ? LvalueBit : 0, 00028 Flags0 = traits<MatrixTypeNestedPlain>::Flags & ~(LvalueBit | NestByRefBit), 00029 Flags1 = Flags0 | FlagsLvalueBit, 00030 Flags = Flags1 ^ RowMajorBit, 00031 InnerStrideAtCompileTime = inner_stride_at_compile_time<MatrixType>::ret, 00032 OuterStrideAtCompileTime = outer_stride_at_compile_time<MatrixType>::ret 00033 }; 00034 }; 00035 } 00036 00037 template<typename MatrixType, typename StorageKind> class TransposeImpl; 00038 00052 template<typename MatrixType> class Transpose 00053 : public TransposeImpl<MatrixType,typename internal::traits<MatrixType>::StorageKind> 00054 { 00055 public: 00056 00057 typedef typename internal::ref_selector<MatrixType>::non_const_type MatrixTypeNested; 00058 00059 typedef typename TransposeImpl<MatrixType,typename internal::traits<MatrixType>::StorageKind>::Base Base; 00060 EIGEN_GENERIC_PUBLIC_INTERFACE(Transpose) 00061 typedef typename internal::remove_all<MatrixType>::type NestedExpression; 00062 00063 EIGEN_DEVICE_FUNC 00064 explicit inline Transpose(MatrixType& matrix) : m_matrix(matrix) {} 00065 00066 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Transpose) 00067 00068 EIGEN_DEVICE_FUNC inline Index rows() const { return m_matrix.cols(); } 00069 EIGEN_DEVICE_FUNC inline Index cols() const { return m_matrix.rows(); } 00070 00072 EIGEN_DEVICE_FUNC 00073 const typename internal::remove_all<MatrixTypeNested>::type& 00074 nestedExpression() const { return m_matrix; } 00075 00077 EIGEN_DEVICE_FUNC 00078 typename internal::remove_reference<MatrixTypeNested>::type& 00079 nestedExpression() { return m_matrix; } 00080 00082 void resize(Index nrows, Index ncols) { 00083 m_matrix.resize(ncols,nrows); 00084 } 00085 00086 protected: 00087 typename internal::ref_selector<MatrixType>::non_const_type m_matrix; 00088 }; 00089 00090 namespace internal { 00091 00092 template<typename MatrixType, bool HasDirectAccess = has_direct_access<MatrixType>::ret> 00093 struct TransposeImpl_base 00094 { 00095 typedef typename dense_xpr_base<Transpose<MatrixType> >::type type; 00096 }; 00097 00098 template<typename MatrixType> 00099 struct TransposeImpl_base<MatrixType, false> 00100 { 00101 typedef typename dense_xpr_base<Transpose<MatrixType> >::type type; 00102 }; 00103 00104 } // end namespace internal 00105 00106 // Generic API dispatcher 00107 template<typename XprType, typename StorageKind> 00108 class TransposeImpl 00109 : public internal::generic_xpr_base<Transpose<XprType> >::type 00110 { 00111 public: 00112 typedef typename internal::generic_xpr_base<Transpose<XprType> >::type Base; 00113 }; 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 using Base::coeffRef; 00122 EIGEN_DENSE_PUBLIC_INTERFACE(Transpose<MatrixType>) 00123 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(TransposeImpl) 00124 00125 EIGEN_DEVICE_FUNC inline Index innerStride() const { return derived().nestedExpression().innerStride(); } 00126 EIGEN_DEVICE_FUNC inline Index outerStride() const { return derived().nestedExpression().outerStride(); } 00127 00128 typedef typename internal::conditional< 00129 internal::is_lvalue<MatrixType>::value, 00130 Scalar, 00131 const Scalar 00132 >::type ScalarWithConstIfNotLvalue; 00133 00134 EIGEN_DEVICE_FUNC inline ScalarWithConstIfNotLvalue* data() { return derived().nestedExpression().data(); } 00135 EIGEN_DEVICE_FUNC inline const Scalar* data() const { return derived().nestedExpression().data(); } 00136 00137 // FIXME: shall we keep the const version of coeffRef? 00138 EIGEN_DEVICE_FUNC 00139 inline const Scalar& coeffRef(Index rowId, Index colId) const 00140 { 00141 return derived().nestedExpression().coeffRef(colId, rowId); 00142 } 00143 00144 EIGEN_DEVICE_FUNC 00145 inline const Scalar& coeffRef(Index index) const 00146 { 00147 return derived().nestedExpression().coeffRef(index); 00148 } 00149 }; 00150 00170 template<typename Derived> 00171 inline Transpose<Derived> 00172 DenseBase<Derived>::transpose() 00173 { 00174 return TransposeReturnType(derived()); 00175 } 00176 00182 template<typename Derived> 00183 inline typename DenseBase<Derived>::ConstTransposeReturnType 00184 DenseBase<Derived>::transpose() const 00185 { 00186 return ConstTransposeReturnType(derived()); 00187 } 00188 00208 template<typename Derived> 00209 inline const typename MatrixBase<Derived>::AdjointReturnType 00210 MatrixBase<Derived>::adjoint() const 00211 { 00212 return AdjointReturnType(this->transpose()); 00213 } 00214 00215 /*************************************************************************** 00216 * "in place" transpose implementation 00217 ***************************************************************************/ 00218 00219 namespace internal { 00220 00221 template<typename MatrixType, 00222 bool IsSquare = (MatrixType::RowsAtCompileTime == MatrixType::ColsAtCompileTime) && MatrixType::RowsAtCompileTime!=Dynamic, 00223 bool MatchPacketSize = 00224 (int(MatrixType::RowsAtCompileTime) == int(internal::packet_traits<typename MatrixType::Scalar>::size)) 00225 && (internal::evaluator<MatrixType>::Flags&PacketAccessBit) > 00226 struct inplace_transpose_selector; 00227 00228 template<typename MatrixType> 00229 struct inplace_transpose_selector<MatrixType,true,false> { // square matrix 00230 static void run(MatrixType& m) { 00231 m.matrix().template triangularView<StrictlyUpper>().swap(m.matrix().transpose()); 00232 } 00233 }; 00234 00235 // TODO: vectorized path is currently limited to LargestPacketSize x LargestPacketSize cases only. 00236 template<typename MatrixType> 00237 struct inplace_transpose_selector<MatrixType,true,true> { // PacketSize x PacketSize 00238 static void run(MatrixType& m) { 00239 typedef typename MatrixType::Scalar Scalar; 00240 typedef typename internal::packet_traits<typename MatrixType::Scalar>::type Packet; 00241 const Index PacketSize = internal::packet_traits<Scalar>::size; 00242 const Index Alignment = internal::evaluator<MatrixType>::Alignment; 00243 PacketBlock<Packet> A; 00244 for (Index i=0; i<PacketSize; ++i) 00245 A.packet[i] = m.template packetByOuterInner<Alignment>(i,0); 00246 internal::ptranspose(A); 00247 for (Index i=0; i<PacketSize; ++i) 00248 m.template writePacket<Alignment>(m.rowIndexByOuterInner(i,0), m.colIndexByOuterInner(i,0), A.packet[i]); 00249 } 00250 }; 00251 00252 template<typename MatrixType,bool MatchPacketSize> 00253 struct inplace_transpose_selector<MatrixType,false,MatchPacketSize> { // non square matrix 00254 static void run(MatrixType& m) { 00255 if (m.rows()==m.cols()) 00256 m.matrix().template triangularView<StrictlyUpper>().swap(m.matrix().transpose()); 00257 else 00258 m = m.transpose().eval(); 00259 } 00260 }; 00261 00262 } // end namespace internal 00263 00283 template<typename Derived> 00284 inline void DenseBase<Derived>::transposeInPlace() 00285 { 00286 eigen_assert((rows() == cols() || (RowsAtCompileTime == Dynamic && ColsAtCompileTime == Dynamic)) 00287 && "transposeInPlace() called on a non-square non-resizable matrix"); 00288 internal::inplace_transpose_selector<Derived>::run(derived()); 00289 } 00290 00291 /*************************************************************************** 00292 * "in place" adjoint implementation 00293 ***************************************************************************/ 00294 00314 template<typename Derived> 00315 inline void MatrixBase<Derived>::adjointInPlace() 00316 { 00317 derived() = adjoint().eval(); 00318 } 00319 00320 #ifndef EIGEN_NO_DEBUG 00321 00322 // The following is to detect aliasing problems in most common cases. 00323 00324 namespace internal { 00325 00326 template<bool DestIsTransposed, typename OtherDerived> 00327 struct check_transpose_aliasing_compile_time_selector 00328 { 00329 enum { ret = bool(blas_traits<OtherDerived>::IsTransposed) != DestIsTransposed }; 00330 }; 00331 00332 template<bool DestIsTransposed, typename BinOp, typename DerivedA, typename DerivedB> 00333 struct check_transpose_aliasing_compile_time_selector<DestIsTransposed,CwiseBinaryOp<BinOp,DerivedA,DerivedB> > 00334 { 00335 enum { ret = bool(blas_traits<DerivedA>::IsTransposed) != DestIsTransposed 00336 || bool(blas_traits<DerivedB>::IsTransposed) != DestIsTransposed 00337 }; 00338 }; 00339 00340 template<typename Scalar, bool DestIsTransposed, typename OtherDerived> 00341 struct check_transpose_aliasing_run_time_selector 00342 { 00343 static bool run(const Scalar* dest, const OtherDerived& src) 00344 { 00345 return (bool(blas_traits<OtherDerived>::IsTransposed) != DestIsTransposed) && (dest!=0 && dest==(const Scalar*)extract_data(src)); 00346 } 00347 }; 00348 00349 template<typename Scalar, bool DestIsTransposed, typename BinOp, typename DerivedA, typename DerivedB> 00350 struct check_transpose_aliasing_run_time_selector<Scalar,DestIsTransposed,CwiseBinaryOp<BinOp,DerivedA,DerivedB> > 00351 { 00352 static bool run(const Scalar* dest, const CwiseBinaryOp<BinOp,DerivedA,DerivedB>& src) 00353 { 00354 return ((blas_traits<DerivedA>::IsTransposed != DestIsTransposed) && (dest!=0 && dest==(const Scalar*)extract_data(src.lhs()))) 00355 || ((blas_traits<DerivedB>::IsTransposed != DestIsTransposed) && (dest!=0 && dest==(const Scalar*)extract_data(src.rhs()))); 00356 } 00357 }; 00358 00359 // the following selector, checkTransposeAliasing_impl, based on MightHaveTransposeAliasing, 00360 // is because when the condition controlling the assert is known at compile time, ICC emits a warning. 00361 // This is actually a good warning: in expressions that don't have any transposing, the condition is 00362 // known at compile time to be false, and using that, we can avoid generating the code of the assert again 00363 // and again for all these expressions that don't need it. 00364 00365 template<typename Derived, typename OtherDerived, 00366 bool MightHaveTransposeAliasing 00367 = check_transpose_aliasing_compile_time_selector 00368 <blas_traits<Derived>::IsTransposed,OtherDerived>::ret 00369 > 00370 struct checkTransposeAliasing_impl 00371 { 00372 static void run(const Derived& dst, const OtherDerived& other) 00373 { 00374 eigen_assert((!check_transpose_aliasing_run_time_selector 00375 <typename Derived::Scalar,blas_traits<Derived>::IsTransposed,OtherDerived> 00376 ::run(extract_data(dst), other)) 00377 && "aliasing detected during transposition, use transposeInPlace() " 00378 "or evaluate the rhs into a temporary using .eval()"); 00379 00380 } 00381 }; 00382 00383 template<typename Derived, typename OtherDerived> 00384 struct checkTransposeAliasing_impl<Derived, OtherDerived, false> 00385 { 00386 static void run(const Derived&, const OtherDerived&) 00387 { 00388 } 00389 }; 00390 00391 template<typename Dst, typename Src> 00392 void check_for_aliasing(const Dst &dst, const Src &src) 00393 { 00394 internal::checkTransposeAliasing_impl<Dst, Src>::run(dst, src); 00395 } 00396 00397 } // end namespace internal 00398 00399 #endif // EIGEN_NO_DEBUG 00400 00401 } // end namespace Eigen 00402 00403 #endif // EIGEN_TRANSPOSE_H