MOAB
4.9.3pre
|
00001 // This file is part of Eigen, a lightweight C++ template library 00002 // for linear algebra. 00003 // 00004 // Copyright (C) 2006-2008 Benoit Jacob <[email protected]> 00005 // Copyright (C) 2009-2014 Gael Guennebaud <[email protected]> 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 00081 protected: 00082 typename internal::ref_selector<MatrixType>::non_const_type m_matrix; 00083 }; 00084 00085 namespace internal { 00086 00087 template<typename MatrixType, bool HasDirectAccess = has_direct_access<MatrixType>::ret> 00088 struct TransposeImpl_base 00089 { 00090 typedef typename dense_xpr_base<Transpose<MatrixType> >::type type; 00091 }; 00092 00093 template<typename MatrixType> 00094 struct TransposeImpl_base<MatrixType, false> 00095 { 00096 typedef typename dense_xpr_base<Transpose<MatrixType> >::type type; 00097 }; 00098 00099 } // end namespace internal 00100 00101 // Generic API dispatcher 00102 template<typename XprType, typename StorageKind> 00103 class TransposeImpl 00104 : public internal::generic_xpr_base<Transpose<XprType> >::type 00105 { 00106 public: 00107 typedef typename internal::generic_xpr_base<Transpose<XprType> >::type Base; 00108 }; 00109 00110 template<typename MatrixType> class TransposeImpl<MatrixType,Dense> 00111 : public internal::TransposeImpl_base<MatrixType>::type 00112 { 00113 public: 00114 00115 typedef typename internal::TransposeImpl_base<MatrixType>::type Base; 00116 using Base::coeffRef; 00117 EIGEN_DENSE_PUBLIC_INTERFACE(Transpose<MatrixType>) 00118 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(TransposeImpl) 00119 00120 EIGEN_DEVICE_FUNC inline Index innerStride() const { return derived().nestedExpression().innerStride(); } 00121 EIGEN_DEVICE_FUNC inline Index outerStride() const { return derived().nestedExpression().outerStride(); } 00122 00123 typedef typename internal::conditional< 00124 internal::is_lvalue<MatrixType>::value, 00125 Scalar, 00126 const Scalar 00127 >::type ScalarWithConstIfNotLvalue; 00128 00129 EIGEN_DEVICE_FUNC inline ScalarWithConstIfNotLvalue* data() { return derived().nestedExpression().data(); } 00130 EIGEN_DEVICE_FUNC inline const Scalar* data() const { return derived().nestedExpression().data(); } 00131 00132 // FIXME: shall we keep the const version of coeffRef? 00133 EIGEN_DEVICE_FUNC 00134 inline const Scalar& coeffRef(Index rowId, Index colId) const 00135 { 00136 return derived().nestedExpression().coeffRef(colId, rowId); 00137 } 00138 00139 EIGEN_DEVICE_FUNC 00140 inline const Scalar& coeffRef(Index index) const 00141 { 00142 return derived().nestedExpression().coeffRef(index); 00143 } 00144 }; 00145 00165 template<typename Derived> 00166 inline Transpose<Derived> 00167 DenseBase<Derived>::transpose() 00168 { 00169 return TransposeReturnType(derived()); 00170 } 00171 00177 template<typename Derived> 00178 inline typename DenseBase<Derived>::ConstTransposeReturnType 00179 DenseBase<Derived>::transpose() const 00180 { 00181 return ConstTransposeReturnType(derived()); 00182 } 00183 00203 template<typename Derived> 00204 inline const typename MatrixBase<Derived>::AdjointReturnType 00205 MatrixBase<Derived>::adjoint() const 00206 { 00207 return AdjointReturnType(this->transpose()); 00208 } 00209 00210 /*************************************************************************** 00211 * "in place" transpose implementation 00212 ***************************************************************************/ 00213 00214 namespace internal { 00215 00216 template<typename MatrixType, 00217 bool IsSquare = (MatrixType::RowsAtCompileTime == MatrixType::ColsAtCompileTime) && MatrixType::RowsAtCompileTime!=Dynamic, 00218 bool MatchPacketSize = 00219 (int(MatrixType::RowsAtCompileTime) == int(internal::packet_traits<typename MatrixType::Scalar>::size)) 00220 && (internal::evaluator<MatrixType>::Flags&PacketAccessBit) > 00221 struct inplace_transpose_selector; 00222 00223 template<typename MatrixType> 00224 struct inplace_transpose_selector<MatrixType,true,false> { // square matrix 00225 static void run(MatrixType& m) { 00226 m.matrix().template triangularView<StrictlyUpper>().swap(m.matrix().transpose()); 00227 } 00228 }; 00229 00230 // TODO: vectorized path is currently limited to LargestPacketSize x LargestPacketSize cases only. 00231 template<typename MatrixType> 00232 struct inplace_transpose_selector<MatrixType,true,true> { // PacketSize x PacketSize 00233 static void run(MatrixType& m) { 00234 typedef typename MatrixType::Scalar Scalar; 00235 typedef typename internal::packet_traits<typename MatrixType::Scalar>::type Packet; 00236 const Index PacketSize = internal::packet_traits<Scalar>::size; 00237 const Index Alignment = internal::evaluator<MatrixType>::Alignment; 00238 PacketBlock<Packet> A; 00239 for (Index i=0; i<PacketSize; ++i) 00240 A.packet[i] = m.template packetByOuterInner<Alignment>(i,0); 00241 internal::ptranspose(A); 00242 for (Index i=0; i<PacketSize; ++i) 00243 m.template writePacket<Alignment>(m.rowIndexByOuterInner(i,0), m.colIndexByOuterInner(i,0), A.packet[i]); 00244 } 00245 }; 00246 00247 template<typename MatrixType,bool MatchPacketSize> 00248 struct inplace_transpose_selector<MatrixType,false,MatchPacketSize> { // non square matrix 00249 static void run(MatrixType& m) { 00250 if (m.rows()==m.cols()) 00251 m.matrix().template triangularView<StrictlyUpper>().swap(m.matrix().transpose()); 00252 else 00253 m = m.transpose().eval(); 00254 } 00255 }; 00256 00257 } // end namespace internal 00258 00278 template<typename Derived> 00279 inline void DenseBase<Derived>::transposeInPlace() 00280 { 00281 eigen_assert((rows() == cols() || (RowsAtCompileTime == Dynamic && ColsAtCompileTime == Dynamic)) 00282 && "transposeInPlace() called on a non-square non-resizable matrix"); 00283 internal::inplace_transpose_selector<Derived>::run(derived()); 00284 } 00285 00286 /*************************************************************************** 00287 * "in place" adjoint implementation 00288 ***************************************************************************/ 00289 00309 template<typename Derived> 00310 inline void MatrixBase<Derived>::adjointInPlace() 00311 { 00312 derived() = adjoint().eval(); 00313 } 00314 00315 #ifndef EIGEN_NO_DEBUG 00316 00317 // The following is to detect aliasing problems in most common cases. 00318 00319 namespace internal { 00320 00321 template<bool DestIsTransposed, typename OtherDerived> 00322 struct check_transpose_aliasing_compile_time_selector 00323 { 00324 enum { ret = bool(blas_traits<OtherDerived>::IsTransposed) != DestIsTransposed }; 00325 }; 00326 00327 template<bool DestIsTransposed, typename BinOp, typename DerivedA, typename DerivedB> 00328 struct check_transpose_aliasing_compile_time_selector<DestIsTransposed,CwiseBinaryOp<BinOp,DerivedA,DerivedB> > 00329 { 00330 enum { ret = bool(blas_traits<DerivedA>::IsTransposed) != DestIsTransposed 00331 || bool(blas_traits<DerivedB>::IsTransposed) != DestIsTransposed 00332 }; 00333 }; 00334 00335 template<typename Scalar, bool DestIsTransposed, typename OtherDerived> 00336 struct check_transpose_aliasing_run_time_selector 00337 { 00338 static bool run(const Scalar* dest, const OtherDerived& src) 00339 { 00340 return (bool(blas_traits<OtherDerived>::IsTransposed) != DestIsTransposed) && (dest!=0 && dest==(const Scalar*)extract_data(src)); 00341 } 00342 }; 00343 00344 template<typename Scalar, bool DestIsTransposed, typename BinOp, typename DerivedA, typename DerivedB> 00345 struct check_transpose_aliasing_run_time_selector<Scalar,DestIsTransposed,CwiseBinaryOp<BinOp,DerivedA,DerivedB> > 00346 { 00347 static bool run(const Scalar* dest, const CwiseBinaryOp<BinOp,DerivedA,DerivedB>& src) 00348 { 00349 return ((blas_traits<DerivedA>::IsTransposed != DestIsTransposed) && (dest!=0 && dest==(const Scalar*)extract_data(src.lhs()))) 00350 || ((blas_traits<DerivedB>::IsTransposed != DestIsTransposed) && (dest!=0 && dest==(const Scalar*)extract_data(src.rhs()))); 00351 } 00352 }; 00353 00354 // the following selector, checkTransposeAliasing_impl, based on MightHaveTransposeAliasing, 00355 // is because when the condition controlling the assert is known at compile time, ICC emits a warning. 00356 // This is actually a good warning: in expressions that don't have any transposing, the condition is 00357 // known at compile time to be false, and using that, we can avoid generating the code of the assert again 00358 // and again for all these expressions that don't need it. 00359 00360 template<typename Derived, typename OtherDerived, 00361 bool MightHaveTransposeAliasing 00362 = check_transpose_aliasing_compile_time_selector 00363 <blas_traits<Derived>::IsTransposed,OtherDerived>::ret 00364 > 00365 struct checkTransposeAliasing_impl 00366 { 00367 static void run(const Derived& dst, const OtherDerived& other) 00368 { 00369 eigen_assert((!check_transpose_aliasing_run_time_selector 00370 <typename Derived::Scalar,blas_traits<Derived>::IsTransposed,OtherDerived> 00371 ::run(extract_data(dst), other)) 00372 && "aliasing detected during transposition, use transposeInPlace() " 00373 "or evaluate the rhs into a temporary using .eval()"); 00374 00375 } 00376 }; 00377 00378 template<typename Derived, typename OtherDerived> 00379 struct checkTransposeAliasing_impl<Derived, OtherDerived, false> 00380 { 00381 static void run(const Derived&, const OtherDerived&) 00382 { 00383 } 00384 }; 00385 00386 template<typename Dst, typename Src> 00387 void check_for_aliasing(const Dst &dst, const Src &src) 00388 { 00389 internal::checkTransposeAliasing_impl<Dst, Src>::run(dst, src); 00390 } 00391 00392 } // end namespace internal 00393 00394 #endif // EIGEN_NO_DEBUG 00395 00396 } // end namespace Eigen 00397 00398 #endif // EIGEN_TRANSPOSE_H