Eigen  3.2.91
Transpose.h
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 
11 #ifndef EIGEN_TRANSPOSE_H
12 #define EIGEN_TRANSPOSE_H
13 
14 namespace Eigen {
15 
30 namespace internal {
31 template<typename MatrixType>
32 struct traits<Transpose<MatrixType> > : public traits<MatrixType>
33 {
34  typedef typename ref_selector<MatrixType>::type MatrixTypeNested;
35  typedef typename remove_reference<MatrixTypeNested>::type MatrixTypeNestedPlain;
36  enum {
37  RowsAtCompileTime = MatrixType::ColsAtCompileTime,
38  ColsAtCompileTime = MatrixType::RowsAtCompileTime,
39  MaxRowsAtCompileTime = MatrixType::MaxColsAtCompileTime,
40  MaxColsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
41  FlagsLvalueBit = is_lvalue<MatrixType>::value ? LvalueBit : 0,
42  Flags0 = MatrixTypeNestedPlain::Flags & ~(LvalueBit | NestByRefBit),
43  Flags1 = Flags0 | FlagsLvalueBit,
44  Flags = Flags1 ^ RowMajorBit,
45  InnerStrideAtCompileTime = inner_stride_at_compile_time<MatrixType>::ret,
46  OuterStrideAtCompileTime = outer_stride_at_compile_time<MatrixType>::ret
47  };
48 };
49 }
50 
51 template<typename MatrixType, typename StorageKind> class TransposeImpl;
52 
53 template<typename MatrixType> class Transpose
54  : public TransposeImpl<MatrixType,typename internal::traits<MatrixType>::StorageKind>
55 {
56  public:
57 
58  typedef typename TransposeImpl<MatrixType,typename internal::traits<MatrixType>::StorageKind>::Base Base;
59  EIGEN_GENERIC_PUBLIC_INTERFACE(Transpose)
60  typedef typename internal::remove_all<MatrixType>::type NestedExpression;
61 
62  EIGEN_DEVICE_FUNC
63  explicit inline Transpose(MatrixType& matrix) : m_matrix(matrix) {}
64 
65  EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Transpose)
66 
67  EIGEN_DEVICE_FUNC inline Index rows() const { return m_matrix.cols(); }
68  EIGEN_DEVICE_FUNC inline Index cols() const { return m_matrix.rows(); }
69 
71  EIGEN_DEVICE_FUNC
72  const typename internal::remove_all<typename MatrixType::Nested>::type&
73  nestedExpression() const { return m_matrix; }
74 
76  EIGEN_DEVICE_FUNC
77  typename internal::remove_all<typename MatrixType::Nested>::type&
78  nestedExpression() { return m_matrix.const_cast_derived(); }
79 
80  protected:
81  typename MatrixType::Nested m_matrix;
82 };
83 
84 namespace internal {
85 
86 template<typename MatrixType, bool HasDirectAccess = has_direct_access<MatrixType>::ret>
87 struct TransposeImpl_base
88 {
89  typedef typename dense_xpr_base<Transpose<MatrixType> >::type type;
90 };
91 
92 template<typename MatrixType>
93 struct TransposeImpl_base<MatrixType, false>
94 {
95  typedef typename dense_xpr_base<Transpose<MatrixType> >::type type;
96 };
97 
98 } // end namespace internal
99 
100 // Generic API dispatcher
101 template<typename XprType, typename StorageKind>
102 class TransposeImpl
103  : public internal::generic_xpr_base<Transpose<XprType> >::type
104 {
105 public:
106  typedef typename internal::generic_xpr_base<Transpose<XprType> >::type Base;
107 };
108 
109 template<typename MatrixType> class TransposeImpl<MatrixType,Dense>
110  : public internal::TransposeImpl_base<MatrixType>::type
111 {
112  public:
113 
114  typedef typename internal::TransposeImpl_base<MatrixType>::type Base;
115  using Base::coeffRef;
116  EIGEN_DENSE_PUBLIC_INTERFACE(Transpose<MatrixType>)
117  EIGEN_INHERIT_ASSIGNMENT_OPERATORS(TransposeImpl)
118 
119  EIGEN_DEVICE_FUNC inline Index innerStride() const { return derived().nestedExpression().innerStride(); }
120  EIGEN_DEVICE_FUNC inline Index outerStride() const { return derived().nestedExpression().outerStride(); }
121 
122  typedef typename internal::conditional<
123  internal::is_lvalue<MatrixType>::value,
124  Scalar,
125  const Scalar
126  >::type ScalarWithConstIfNotLvalue;
127 
128  EIGEN_DEVICE_FUNC inline ScalarWithConstIfNotLvalue* data() { return derived().nestedExpression().data(); }
129  EIGEN_DEVICE_FUNC inline const Scalar* data() const { return derived().nestedExpression().data(); }
130 
131  // FIXME: shall we keep the const version of coeffRef?
132  EIGEN_DEVICE_FUNC
133  inline const Scalar& coeffRef(Index rowId, Index colId) const
134  {
135  return derived().nestedExpression().coeffRef(colId, rowId);
136  }
137 
138  EIGEN_DEVICE_FUNC
139  inline const Scalar& coeffRef(Index index) const
140  {
141  return derived().nestedExpression().coeffRef(index);
142  }
143 };
144 
164 template<typename Derived>
165 inline Transpose<Derived>
167 {
168  return TransposeReturnType(derived());
169 }
170 
176 template<typename Derived>
179 {
180  return ConstTransposeReturnType(derived());
181 }
182 
202 template<typename Derived>
203 inline const typename MatrixBase<Derived>::AdjointReturnType
205 {
206  return AdjointReturnType(this->transpose());
207 }
208 
209 /***************************************************************************
210 * "in place" transpose implementation
211 ***************************************************************************/
212 
213 namespace internal {
214 
215 template<typename MatrixType,
216  bool IsSquare = (MatrixType::RowsAtCompileTime == MatrixType::ColsAtCompileTime) && MatrixType::RowsAtCompileTime!=Dynamic,
217  bool MatchPacketSize =
218  (int(MatrixType::RowsAtCompileTime) == int(internal::packet_traits<typename MatrixType::Scalar>::size))
219  && (internal::evaluator<MatrixType>::Flags&PacketAccessBit) >
220 struct inplace_transpose_selector;
221 
222 template<typename MatrixType>
223 struct inplace_transpose_selector<MatrixType,true,false> { // square matrix
224  static void run(MatrixType& m) {
225  m.matrix().template triangularView<StrictlyUpper>().swap(m.matrix().transpose());
226  }
227 };
228 
229 // TODO: vectorized path is currently limited to LargestPacketSize x LargestPacketSize cases only.
230 template<typename MatrixType>
231 struct inplace_transpose_selector<MatrixType,true,true> { // PacketSize x PacketSize
232  static void run(MatrixType& m) {
233  typedef typename MatrixType::Scalar Scalar;
234  typedef typename internal::packet_traits<typename MatrixType::Scalar>::type Packet;
235  const Index PacketSize = internal::packet_traits<Scalar>::size;
236  const Index Alignment = internal::evaluator<MatrixType>::Alignment;
237  PacketBlock<Packet> A;
238  for (Index i=0; i<PacketSize; ++i)
239  A.packet[i] = m.template packetByOuterInner<Alignment>(i,0);
240  internal::ptranspose(A);
241  for (Index i=0; i<PacketSize; ++i)
242  m.template writePacket<Alignment>(m.rowIndexByOuterInner(i,0), m.colIndexByOuterInner(i,0), A.packet[i]);
243  }
244 };
245 
246 template<typename MatrixType,bool MatchPacketSize>
247 struct inplace_transpose_selector<MatrixType,false,MatchPacketSize> { // non square matrix
248  static void run(MatrixType& m) {
249  if (m.rows()==m.cols())
250  m.matrix().template triangularView<StrictlyUpper>().swap(m.matrix().transpose());
251  else
252  m = m.transpose().eval();
253  }
254 };
255 
256 } // end namespace internal
257 
277 template<typename Derived>
279 {
280  eigen_assert((rows() == cols() || (RowsAtCompileTime == Dynamic && ColsAtCompileTime == Dynamic))
281  && "transposeInPlace() called on a non-square non-resizable matrix");
282  internal::inplace_transpose_selector<Derived>::run(derived());
283 }
284 
285 /***************************************************************************
286 * "in place" adjoint implementation
287 ***************************************************************************/
288 
308 template<typename Derived>
310 {
311  derived() = adjoint().eval();
312 }
313 
314 #ifndef EIGEN_NO_DEBUG
315 
316 // The following is to detect aliasing problems in most common cases.
317 
318 namespace internal {
319 
320 template<bool DestIsTransposed, typename OtherDerived>
321 struct check_transpose_aliasing_compile_time_selector
322 {
323  enum { ret = bool(blas_traits<OtherDerived>::IsTransposed) != DestIsTransposed };
324 };
325 
326 template<bool DestIsTransposed, typename BinOp, typename DerivedA, typename DerivedB>
327 struct check_transpose_aliasing_compile_time_selector<DestIsTransposed,CwiseBinaryOp<BinOp,DerivedA,DerivedB> >
328 {
329  enum { ret = bool(blas_traits<DerivedA>::IsTransposed) != DestIsTransposed
330  || bool(blas_traits<DerivedB>::IsTransposed) != DestIsTransposed
331  };
332 };
333 
334 template<typename Scalar, bool DestIsTransposed, typename OtherDerived>
335 struct check_transpose_aliasing_run_time_selector
336 {
337  static bool run(const Scalar* dest, const OtherDerived& src)
338  {
339  return (bool(blas_traits<OtherDerived>::IsTransposed) != DestIsTransposed) && (dest!=0 && dest==(const Scalar*)extract_data(src));
340  }
341 };
342 
343 template<typename Scalar, bool DestIsTransposed, typename BinOp, typename DerivedA, typename DerivedB>
344 struct check_transpose_aliasing_run_time_selector<Scalar,DestIsTransposed,CwiseBinaryOp<BinOp,DerivedA,DerivedB> >
345 {
346  static bool run(const Scalar* dest, const CwiseBinaryOp<BinOp,DerivedA,DerivedB>& src)
347  {
348  return ((blas_traits<DerivedA>::IsTransposed != DestIsTransposed) && (dest!=0 && dest==(const Scalar*)extract_data(src.lhs())))
349  || ((blas_traits<DerivedB>::IsTransposed != DestIsTransposed) && (dest!=0 && dest==(const Scalar*)extract_data(src.rhs())));
350  }
351 };
352 
353 // the following selector, checkTransposeAliasing_impl, based on MightHaveTransposeAliasing,
354 // is because when the condition controlling the assert is known at compile time, ICC emits a warning.
355 // This is actually a good warning: in expressions that don't have any transposing, the condition is
356 // known at compile time to be false, and using that, we can avoid generating the code of the assert again
357 // and again for all these expressions that don't need it.
358 
359 template<typename Derived, typename OtherDerived,
360  bool MightHaveTransposeAliasing
361  = check_transpose_aliasing_compile_time_selector
362  <blas_traits<Derived>::IsTransposed,OtherDerived>::ret
363  >
364 struct checkTransposeAliasing_impl
365 {
366  static void run(const Derived& dst, const OtherDerived& other)
367  {
368  eigen_assert((!check_transpose_aliasing_run_time_selector
369  <typename Derived::Scalar,blas_traits<Derived>::IsTransposed,OtherDerived>
370  ::run(extract_data(dst), other))
371  && "aliasing detected during transposition, use transposeInPlace() "
372  "or evaluate the rhs into a temporary using .eval()");
373 
374  }
375 };
376 
377 template<typename Derived, typename OtherDerived>
378 struct checkTransposeAliasing_impl<Derived, OtherDerived, false>
379 {
380  static void run(const Derived&, const OtherDerived&)
381  {
382  }
383 };
384 
385 template<typename Dst, typename Src>
386 void check_for_aliasing(const Dst &dst, const Src &src)
387 {
388  internal::checkTransposeAliasing_impl<Dst, Src>::run(dst, src);
389 }
390 
391 } // end namespace internal
392 
393 #endif // EIGEN_NO_DEBUG
394 
395 } // end namespace Eigen
396 
397 #endif // EIGEN_TRANSPOSE_H
Expression of the transpose of a matrix.
Definition: Transpose.h:53
const unsigned int LvalueBit
Definition: Constants.h:130
Definition: LDLT.h:16
const unsigned int RowMajorBit
Definition: Constants.h:53
internal::remove_all< typename MatrixType::Nested >::type & nestedExpression()
Definition: Transpose.h:78
TransposeReturnType transpose()
Definition: Transpose.h:166
const unsigned int PacketAccessBit
Definition: Constants.h:80
void adjointInPlace()
Definition: Transpose.h:309
Definition: Eigen_Colamd.h:54
void transposeInPlace()
Definition: Transpose.h:278
const AdjointReturnType adjoint() const
Definition: Transpose.h:204
const internal::remove_all< typename MatrixType::Nested >::type & nestedExpression() const
Definition: Transpose.h:73
Base class for all dense matrices, vectors, and expressions.
Definition: MatrixBase.h:48