Transpose.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. // This file is part of Eigen, a lightweight C++ template library
  2. // for linear algebra.
  3. //
  4. // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
  5. // Copyright (C) 2009-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
  6. //
  7. // This Source Code Form is subject to the terms of the Mozilla
  8. // Public License v. 2.0. If a copy of the MPL was not distributed
  9. // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
  10. #ifndef EIGEN_TRANSPOSE_H
  11. #define EIGEN_TRANSPOSE_H
  12. namespace Eigen {
  13. namespace internal {
  14. template<typename MatrixType>
  15. struct traits<Transpose<MatrixType> > : public traits<MatrixType>
  16. {
  17. typedef typename ref_selector<MatrixType>::type MatrixTypeNested;
  18. typedef typename remove_reference<MatrixTypeNested>::type MatrixTypeNestedPlain;
  19. enum {
  20. RowsAtCompileTime = MatrixType::ColsAtCompileTime,
  21. ColsAtCompileTime = MatrixType::RowsAtCompileTime,
  22. MaxRowsAtCompileTime = MatrixType::MaxColsAtCompileTime,
  23. MaxColsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
  24. FlagsLvalueBit = is_lvalue<MatrixType>::value ? LvalueBit : 0,
  25. Flags0 = traits<MatrixTypeNestedPlain>::Flags & ~(LvalueBit | NestByRefBit),
  26. Flags1 = Flags0 | FlagsLvalueBit,
  27. Flags = Flags1 ^ RowMajorBit,
  28. InnerStrideAtCompileTime = inner_stride_at_compile_time<MatrixType>::ret,
  29. OuterStrideAtCompileTime = outer_stride_at_compile_time<MatrixType>::ret
  30. };
  31. };
  32. }
  33. template<typename MatrixType, typename StorageKind> class TransposeImpl;
  34. /** \class Transpose
  35. * \ingroup Core_Module
  36. *
  37. * \brief Expression of the transpose of a matrix
  38. *
  39. * \tparam MatrixType the type of the object of which we are taking the transpose
  40. *
  41. * This class represents an expression of the transpose of a matrix.
  42. * It is the return type of MatrixBase::transpose() and MatrixBase::adjoint()
  43. * and most of the time this is the only way it is used.
  44. *
  45. * \sa MatrixBase::transpose(), MatrixBase::adjoint()
  46. */
  47. template<typename MatrixType> class Transpose
  48. : public TransposeImpl<MatrixType,typename internal::traits<MatrixType>::StorageKind>
  49. {
  50. public:
  51. typedef typename internal::ref_selector<MatrixType>::non_const_type MatrixTypeNested;
  52. typedef typename TransposeImpl<MatrixType,typename internal::traits<MatrixType>::StorageKind>::Base Base;
  53. EIGEN_GENERIC_PUBLIC_INTERFACE(Transpose)
  54. typedef typename internal::remove_all<MatrixType>::type NestedExpression;
  55. EIGEN_DEVICE_FUNC
  56. explicit inline Transpose(MatrixType& matrix) : m_matrix(matrix) {}
  57. EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Transpose)
  58. EIGEN_DEVICE_FUNC inline Index rows() const { return m_matrix.cols(); }
  59. EIGEN_DEVICE_FUNC inline Index cols() const { return m_matrix.rows(); }
  60. /** \returns the nested expression */
  61. EIGEN_DEVICE_FUNC
  62. const typename internal::remove_all<MatrixTypeNested>::type&
  63. nestedExpression() const { return m_matrix; }
  64. /** \returns the nested expression */
  65. EIGEN_DEVICE_FUNC
  66. typename internal::remove_reference<MatrixTypeNested>::type&
  67. nestedExpression() { return m_matrix; }
  68. /** \internal */
  69. void resize(Index nrows, Index ncols) {
  70. m_matrix.resize(ncols,nrows);
  71. }
  72. protected:
  73. typename internal::ref_selector<MatrixType>::non_const_type m_matrix;
  74. };
  75. namespace internal {
  76. template<typename MatrixType, bool HasDirectAccess = has_direct_access<MatrixType>::ret>
  77. struct TransposeImpl_base
  78. {
  79. typedef typename dense_xpr_base<Transpose<MatrixType> >::type type;
  80. };
  81. template<typename MatrixType>
  82. struct TransposeImpl_base<MatrixType, false>
  83. {
  84. typedef typename dense_xpr_base<Transpose<MatrixType> >::type type;
  85. };
  86. } // end namespace internal
  87. // Generic API dispatcher
  88. template<typename XprType, typename StorageKind>
  89. class TransposeImpl
  90. : public internal::generic_xpr_base<Transpose<XprType> >::type
  91. {
  92. public:
  93. typedef typename internal::generic_xpr_base<Transpose<XprType> >::type Base;
  94. };
  95. template<typename MatrixType> class TransposeImpl<MatrixType,Dense>
  96. : public internal::TransposeImpl_base<MatrixType>::type
  97. {
  98. public:
  99. typedef typename internal::TransposeImpl_base<MatrixType>::type Base;
  100. using Base::coeffRef;
  101. EIGEN_DENSE_PUBLIC_INTERFACE(Transpose<MatrixType>)
  102. EIGEN_INHERIT_ASSIGNMENT_OPERATORS(TransposeImpl)
  103. EIGEN_DEVICE_FUNC inline Index innerStride() const { return derived().nestedExpression().innerStride(); }
  104. EIGEN_DEVICE_FUNC inline Index outerStride() const { return derived().nestedExpression().outerStride(); }
  105. typedef typename internal::conditional<
  106. internal::is_lvalue<MatrixType>::value,
  107. Scalar,
  108. const Scalar
  109. >::type ScalarWithConstIfNotLvalue;
  110. EIGEN_DEVICE_FUNC inline ScalarWithConstIfNotLvalue* data() { return derived().nestedExpression().data(); }
  111. EIGEN_DEVICE_FUNC inline const Scalar* data() const { return derived().nestedExpression().data(); }
  112. // FIXME: shall we keep the const version of coeffRef?
  113. EIGEN_DEVICE_FUNC
  114. inline const Scalar& coeffRef(Index rowId, Index colId) const
  115. {
  116. return derived().nestedExpression().coeffRef(colId, rowId);
  117. }
  118. EIGEN_DEVICE_FUNC
  119. inline const Scalar& coeffRef(Index index) const
  120. {
  121. return derived().nestedExpression().coeffRef(index);
  122. }
  123. protected:
  124. EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(TransposeImpl)
  125. };
  126. /** \returns an expression of the transpose of *this.
  127. *
  128. * Example: \include MatrixBase_transpose.cpp
  129. * Output: \verbinclude MatrixBase_transpose.out
  130. *
  131. * \warning If you want to replace a matrix by its own transpose, do \b NOT do this:
  132. * \code
  133. * m = m.transpose(); // bug!!! caused by aliasing effect
  134. * \endcode
  135. * Instead, use the transposeInPlace() method:
  136. * \code
  137. * m.transposeInPlace();
  138. * \endcode
  139. * which gives Eigen good opportunities for optimization, or alternatively you can also do:
  140. * \code
  141. * m = m.transpose().eval();
  142. * \endcode
  143. *
  144. * \sa transposeInPlace(), adjoint() */
  145. template<typename Derived>
  146. inline Transpose<Derived>
  147. DenseBase<Derived>::transpose()
  148. {
  149. return TransposeReturnType(derived());
  150. }
  151. /** This is the const version of transpose().
  152. *
  153. * Make sure you read the warning for transpose() !
  154. *
  155. * \sa transposeInPlace(), adjoint() */
  156. template<typename Derived>
  157. inline typename DenseBase<Derived>::ConstTransposeReturnType
  158. DenseBase<Derived>::transpose() const
  159. {
  160. return ConstTransposeReturnType(derived());
  161. }
  162. /** \returns an expression of the adjoint (i.e. conjugate transpose) of *this.
  163. *
  164. * Example: \include MatrixBase_adjoint.cpp
  165. * Output: \verbinclude MatrixBase_adjoint.out
  166. *
  167. * \warning If you want to replace a matrix by its own adjoint, do \b NOT do this:
  168. * \code
  169. * m = m.adjoint(); // bug!!! caused by aliasing effect
  170. * \endcode
  171. * Instead, use the adjointInPlace() method:
  172. * \code
  173. * m.adjointInPlace();
  174. * \endcode
  175. * which gives Eigen good opportunities for optimization, or alternatively you can also do:
  176. * \code
  177. * m = m.adjoint().eval();
  178. * \endcode
  179. *
  180. * \sa adjointInPlace(), transpose(), conjugate(), class Transpose, class internal::scalar_conjugate_op */
  181. template<typename Derived>
  182. inline const typename MatrixBase<Derived>::AdjointReturnType
  183. MatrixBase<Derived>::adjoint() const
  184. {
  185. return AdjointReturnType(this->transpose());
  186. }
  187. /***************************************************************************
  188. * "in place" transpose implementation
  189. ***************************************************************************/
  190. namespace internal {
  191. template<typename MatrixType,
  192. bool IsSquare = (MatrixType::RowsAtCompileTime == MatrixType::ColsAtCompileTime) && MatrixType::RowsAtCompileTime!=Dynamic,
  193. bool MatchPacketSize =
  194. (int(MatrixType::RowsAtCompileTime) == int(internal::packet_traits<typename MatrixType::Scalar>::size))
  195. && (internal::evaluator<MatrixType>::Flags&PacketAccessBit) >
  196. struct inplace_transpose_selector;
  197. template<typename MatrixType>
  198. struct inplace_transpose_selector<MatrixType,true,false> { // square matrix
  199. static void run(MatrixType& m) {
  200. m.matrix().template triangularView<StrictlyUpper>().swap(m.matrix().transpose());
  201. }
  202. };
  203. // TODO: vectorized path is currently limited to LargestPacketSize x LargestPacketSize cases only.
  204. template<typename MatrixType>
  205. struct inplace_transpose_selector<MatrixType,true,true> { // PacketSize x PacketSize
  206. static void run(MatrixType& m) {
  207. typedef typename MatrixType::Scalar Scalar;
  208. typedef typename internal::packet_traits<typename MatrixType::Scalar>::type Packet;
  209. const Index PacketSize = internal::packet_traits<Scalar>::size;
  210. const Index Alignment = internal::evaluator<MatrixType>::Alignment;
  211. PacketBlock<Packet> A;
  212. for (Index i=0; i<PacketSize; ++i)
  213. A.packet[i] = m.template packetByOuterInner<Alignment>(i,0);
  214. internal::ptranspose(A);
  215. for (Index i=0; i<PacketSize; ++i)
  216. m.template writePacket<Alignment>(m.rowIndexByOuterInner(i,0), m.colIndexByOuterInner(i,0), A.packet[i]);
  217. }
  218. };
  219. template<typename MatrixType,bool MatchPacketSize>
  220. struct inplace_transpose_selector<MatrixType,false,MatchPacketSize> { // non square matrix
  221. static void run(MatrixType& m) {
  222. if (m.rows()==m.cols())
  223. m.matrix().template triangularView<StrictlyUpper>().swap(m.matrix().transpose());
  224. else
  225. m = m.transpose().eval();
  226. }
  227. };
  228. } // end namespace internal
  229. /** This is the "in place" version of transpose(): it replaces \c *this by its own transpose.
  230. * Thus, doing
  231. * \code
  232. * m.transposeInPlace();
  233. * \endcode
  234. * has the same effect on m as doing
  235. * \code
  236. * m = m.transpose().eval();
  237. * \endcode
  238. * and is faster and also safer because in the latter line of code, forgetting the eval() results
  239. * in a bug caused by \ref TopicAliasing "aliasing".
  240. *
  241. * Notice however that this method is only useful if you want to replace a matrix by its own transpose.
  242. * If you just need the transpose of a matrix, use transpose().
  243. *
  244. * \note if the matrix is not square, then \c *this must be a resizable matrix.
  245. * This excludes (non-square) fixed-size matrices, block-expressions and maps.
  246. *
  247. * \sa transpose(), adjoint(), adjointInPlace() */
  248. template<typename Derived>
  249. inline void DenseBase<Derived>::transposeInPlace()
  250. {
  251. eigen_assert((rows() == cols() || (RowsAtCompileTime == Dynamic && ColsAtCompileTime == Dynamic))
  252. && "transposeInPlace() called on a non-square non-resizable matrix");
  253. internal::inplace_transpose_selector<Derived>::run(derived());
  254. }
  255. /***************************************************************************
  256. * "in place" adjoint implementation
  257. ***************************************************************************/
  258. /** This is the "in place" version of adjoint(): it replaces \c *this by its own transpose.
  259. * Thus, doing
  260. * \code
  261. * m.adjointInPlace();
  262. * \endcode
  263. * has the same effect on m as doing
  264. * \code
  265. * m = m.adjoint().eval();
  266. * \endcode
  267. * and is faster and also safer because in the latter line of code, forgetting the eval() results
  268. * in a bug caused by aliasing.
  269. *
  270. * Notice however that this method is only useful if you want to replace a matrix by its own adjoint.
  271. * If you just need the adjoint of a matrix, use adjoint().
  272. *
  273. * \note if the matrix is not square, then \c *this must be a resizable matrix.
  274. * This excludes (non-square) fixed-size matrices, block-expressions and maps.
  275. *
  276. * \sa transpose(), adjoint(), transposeInPlace() */
  277. template<typename Derived>
  278. inline void MatrixBase<Derived>::adjointInPlace()
  279. {
  280. derived() = adjoint().eval();
  281. }
  282. #ifndef EIGEN_NO_DEBUG
  283. // The following is to detect aliasing problems in most common cases.
  284. namespace internal {
  285. template<bool DestIsTransposed, typename OtherDerived>
  286. struct check_transpose_aliasing_compile_time_selector
  287. {
  288. enum { ret = bool(blas_traits<OtherDerived>::IsTransposed) != DestIsTransposed };
  289. };
  290. template<bool DestIsTransposed, typename BinOp, typename DerivedA, typename DerivedB>
  291. struct check_transpose_aliasing_compile_time_selector<DestIsTransposed,CwiseBinaryOp<BinOp,DerivedA,DerivedB> >
  292. {
  293. enum { ret = bool(blas_traits<DerivedA>::IsTransposed) != DestIsTransposed
  294. || bool(blas_traits<DerivedB>::IsTransposed) != DestIsTransposed
  295. };
  296. };
  297. template<typename Scalar, bool DestIsTransposed, typename OtherDerived>
  298. struct check_transpose_aliasing_run_time_selector
  299. {
  300. static bool run(const Scalar* dest, const OtherDerived& src)
  301. {
  302. return (bool(blas_traits<OtherDerived>::IsTransposed) != DestIsTransposed) && (dest!=0 && dest==(const Scalar*)extract_data(src));
  303. }
  304. };
  305. template<typename Scalar, bool DestIsTransposed, typename BinOp, typename DerivedA, typename DerivedB>
  306. struct check_transpose_aliasing_run_time_selector<Scalar,DestIsTransposed,CwiseBinaryOp<BinOp,DerivedA,DerivedB> >
  307. {
  308. static bool run(const Scalar* dest, const CwiseBinaryOp<BinOp,DerivedA,DerivedB>& src)
  309. {
  310. return ((blas_traits<DerivedA>::IsTransposed != DestIsTransposed) && (dest!=0 && dest==(const Scalar*)extract_data(src.lhs())))
  311. || ((blas_traits<DerivedB>::IsTransposed != DestIsTransposed) && (dest!=0 && dest==(const Scalar*)extract_data(src.rhs())));
  312. }
  313. };
  314. // the following selector, checkTransposeAliasing_impl, based on MightHaveTransposeAliasing,
  315. // is because when the condition controlling the assert is known at compile time, ICC emits a warning.
  316. // This is actually a good warning: in expressions that don't have any transposing, the condition is
  317. // known at compile time to be false, and using that, we can avoid generating the code of the assert again
  318. // and again for all these expressions that don't need it.
  319. template<typename Derived, typename OtherDerived,
  320. bool MightHaveTransposeAliasing
  321. = check_transpose_aliasing_compile_time_selector
  322. <blas_traits<Derived>::IsTransposed,OtherDerived>::ret
  323. >
  324. struct checkTransposeAliasing_impl
  325. {
  326. static void run(const Derived& dst, const OtherDerived& other)
  327. {
  328. eigen_assert((!check_transpose_aliasing_run_time_selector
  329. <typename Derived::Scalar,blas_traits<Derived>::IsTransposed,OtherDerived>
  330. ::run(extract_data(dst), other))
  331. && "aliasing detected during transposition, use transposeInPlace() "
  332. "or evaluate the rhs into a temporary using .eval()");
  333. }
  334. };
  335. template<typename Derived, typename OtherDerived>
  336. struct checkTransposeAliasing_impl<Derived, OtherDerived, false>
  337. {
  338. static void run(const Derived&, const OtherDerived&)
  339. {
  340. }
  341. };
  342. template<typename Dst, typename Src>
  343. void check_for_aliasing(const Dst &dst, const Src &src)
  344. {
  345. internal::checkTransposeAliasing_impl<Dst, Src>::run(dst, src);
  346. }
  347. } // end namespace internal
  348. #endif // EIGEN_NO_DEBUG
  349. } // end namespace Eigen
  350. #endif // EIGEN_TRANSPOSE_H