Transpose.h
Go to the documentation of this file.
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-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
6 //
7 // Eigen is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Lesser General Public
9 // License as published by the Free Software Foundation; either
10 // version 3 of the License, or (at your option) any later version.
11 //
12 // Alternatively, you can redistribute it and/or
13 // modify it under the terms of the GNU General Public License as
14 // published by the Free Software Foundation; either version 2 of
15 // the License, or (at your option) any later version.
16 //
17 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
20 // GNU General Public License for more details.
21 //
22 // You should have received a copy of the GNU Lesser General Public
23 // License and a copy of the GNU General Public License along with
24 // Eigen. If not, see <http://www.gnu.org/licenses/>.
25 
26 #ifndef EIGEN_TRANSPOSE_H
27 #define EIGEN_TRANSPOSE_H
28 
29 namespace Eigen {
30 
45 namespace internal {
46 template<typename MatrixType>
47 struct traits<Transpose<MatrixType> > : traits<MatrixType>
48 {
49  typedef typename MatrixType::Scalar Scalar;
50  typedef typename nested<MatrixType>::type MatrixTypeNested;
51  typedef typename remove_reference<MatrixTypeNested>::type MatrixTypeNestedPlain;
52  typedef typename traits<MatrixType>::StorageKind StorageKind;
53  typedef typename traits<MatrixType>::XprKind XprKind;
54  enum {
55  RowsAtCompileTime = MatrixType::ColsAtCompileTime,
56  ColsAtCompileTime = MatrixType::RowsAtCompileTime,
57  MaxRowsAtCompileTime = MatrixType::MaxColsAtCompileTime,
58  MaxColsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
59  FlagsLvalueBit = is_lvalue<MatrixType>::value ? LvalueBit : 0,
60  Flags0 = MatrixTypeNestedPlain::Flags & ~(LvalueBit | NestByRefBit),
61  Flags1 = Flags0 | FlagsLvalueBit,
62  Flags = Flags1 ^ RowMajorBit,
63  CoeffReadCost = MatrixTypeNestedPlain::CoeffReadCost,
64  InnerStrideAtCompileTime = inner_stride_at_compile_time<MatrixType>::ret,
65  OuterStrideAtCompileTime = outer_stride_at_compile_time<MatrixType>::ret
66  };
67 };
68 }
69 
70 template<typename MatrixType, typename StorageKind> class TransposeImpl;
71 
72 template<typename MatrixType> class Transpose
73  : public TransposeImpl<MatrixType,typename internal::traits<MatrixType>::StorageKind>
74 {
75  public:
76 
79 
80  inline Transpose(MatrixType& matrix) : m_matrix(matrix) {}
81 
83 
84  inline Index rows() const { return m_matrix.cols(); }
85  inline Index cols() const { return m_matrix.rows(); }
86 
88  const typename internal::remove_all<typename MatrixType::Nested>::type&
89  nestedExpression() const { return m_matrix; }
90 
92  typename internal::remove_all<typename MatrixType::Nested>::type&
93  nestedExpression() { return m_matrix.const_cast_derived(); }
94 
95  protected:
96  typename MatrixType::Nested m_matrix;
97 };
98 
99 namespace internal {
100 
101 template<typename MatrixType, bool HasDirectAccess = has_direct_access<MatrixType>::ret>
102 struct TransposeImpl_base
103 {
104  typedef typename dense_xpr_base<Transpose<MatrixType> >::type type;
105 };
106 
107 template<typename MatrixType>
108 struct TransposeImpl_base<MatrixType, false>
109 {
110  typedef typename dense_xpr_base<Transpose<MatrixType> >::type type;
111 };
112 
113 } // end namespace internal
114 
115 template<typename MatrixType> class TransposeImpl<MatrixType,Dense>
116  : public internal::TransposeImpl_base<MatrixType>::type
117 {
118  public:
119 
120  typedef typename internal::TransposeImpl_base<MatrixType>::type Base;
122 
123  inline Index innerStride() const { return derived().nestedExpression().innerStride(); }
124  inline Index outerStride() const { return derived().nestedExpression().outerStride(); }
125 
126  typedef typename internal::conditional<
127  internal::is_lvalue<MatrixType>::value,
128  Scalar,
129  const Scalar
131 
132  inline ScalarWithConstIfNotLvalue* data() { return derived().nestedExpression().data(); }
133  inline const Scalar* data() const { return derived().nestedExpression().data(); }
134 
135  inline ScalarWithConstIfNotLvalue& coeffRef(Index row, Index col)
136  {
137  EIGEN_STATIC_ASSERT_LVALUE(MatrixType)
138  return derived().nestedExpression().const_cast_derived().coeffRef(col, row);
139  }
140 
141  inline ScalarWithConstIfNotLvalue& coeffRef(Index index)
142  {
143  EIGEN_STATIC_ASSERT_LVALUE(MatrixType)
144  return derived().nestedExpression().const_cast_derived().coeffRef(index);
145  }
146 
147  inline const Scalar& coeffRef(Index row, Index col) const
148  {
149  return derived().nestedExpression().coeffRef(col, row);
150  }
151 
152  inline const Scalar& coeffRef(Index index) const
153  {
154  return derived().nestedExpression().coeffRef(index);
155  }
156 
157  inline CoeffReturnType coeff(Index row, Index col) const
158  {
159  return derived().nestedExpression().coeff(col, row);
160  }
161 
162  inline CoeffReturnType coeff(Index index) const
163  {
164  return derived().nestedExpression().coeff(index);
165  }
166 
167  template<int LoadMode>
168  inline const PacketScalar packet(Index row, Index col) const
169  {
170  return derived().nestedExpression().template packet<LoadMode>(col, row);
171  }
172 
173  template<int LoadMode>
174  inline void writePacket(Index row, Index col, const PacketScalar& x)
175  {
176  derived().nestedExpression().const_cast_derived().template writePacket<LoadMode>(col, row, x);
177  }
178 
179  template<int LoadMode>
180  inline const PacketScalar packet(Index index) const
181  {
182  return derived().nestedExpression().template packet<LoadMode>(index);
183  }
184 
185  template<int LoadMode>
186  inline void writePacket(Index index, const PacketScalar& x)
187  {
188  derived().nestedExpression().const_cast_derived().template writePacket<LoadMode>(index, x);
189  }
190 };
191 
211 template<typename Derived>
212 inline Transpose<Derived>
214 {
215  return derived();
216 }
217 
223 template<typename Derived>
226 {
227  return ConstTransposeReturnType(derived());
228 }
229 
249 template<typename Derived>
250 inline const typename MatrixBase<Derived>::AdjointReturnType
252 {
253  return this->transpose(); // in the complex case, the .conjugate() is be implicit here
254  // due to implicit conversion to return type
255 }
256 
257 /***************************************************************************
258 * "in place" transpose implementation
259 ***************************************************************************/
260 
261 namespace internal {
262 
263 template<typename MatrixType,
264  bool IsSquare = (MatrixType::RowsAtCompileTime == MatrixType::ColsAtCompileTime) && MatrixType::RowsAtCompileTime!=Dynamic>
265 struct inplace_transpose_selector;
266 
267 template<typename MatrixType>
268 struct inplace_transpose_selector<MatrixType,true> { // square matrix
269  static void run(MatrixType& m) {
270  m.template triangularView<StrictlyUpper>().swap(m.transpose());
271  }
272 };
273 
274 template<typename MatrixType>
275 struct inplace_transpose_selector<MatrixType,false> { // non square matrix
276  static void run(MatrixType& m) {
277  if (m.rows()==m.cols())
278  m.template triangularView<StrictlyUpper>().swap(m.transpose());
279  else
280  m = m.transpose().eval();
281  }
282 };
283 
284 } // end namespace internal
285 
304 template<typename Derived>
306 {
307  internal::inplace_transpose_selector<Derived>::run(derived());
308 }
309 
310 /***************************************************************************
311 * "in place" adjoint implementation
312 ***************************************************************************/
313 
332 template<typename Derived>
334 {
335  derived() = adjoint().eval();
336 }
337 
338 #ifndef EIGEN_NO_DEBUG
339 
340 // The following is to detect aliasing problems in most common cases.
341 
342 namespace internal {
343 
344 template<typename BinOp,typename NestedXpr,typename Rhs>
345 struct blas_traits<SelfCwiseBinaryOp<BinOp,NestedXpr,Rhs> >
346  : blas_traits<NestedXpr>
347 {
349  static inline const XprType extract(const XprType& x) { return x; }
350 };
351 
352 template<bool DestIsTransposed, typename OtherDerived>
353 struct check_transpose_aliasing_compile_time_selector
354 {
355  enum { ret = bool(blas_traits<OtherDerived>::IsTransposed) != DestIsTransposed };
356 };
357 
358 template<bool DestIsTransposed, typename BinOp, typename DerivedA, typename DerivedB>
359 struct check_transpose_aliasing_compile_time_selector<DestIsTransposed,CwiseBinaryOp<BinOp,DerivedA,DerivedB> >
360 {
361  enum { ret = bool(blas_traits<DerivedA>::IsTransposed) != DestIsTransposed
362  || bool(blas_traits<DerivedB>::IsTransposed) != DestIsTransposed
363  };
364 };
365 
366 template<typename Scalar, bool DestIsTransposed, typename OtherDerived>
367 struct check_transpose_aliasing_run_time_selector
368 {
369  static bool run(const Scalar* dest, const OtherDerived& src)
370  {
371  return (bool(blas_traits<OtherDerived>::IsTransposed) != DestIsTransposed) && (dest!=0 && dest==(Scalar*)extract_data(src));
372  }
373 };
374 
375 template<typename Scalar, bool DestIsTransposed, typename BinOp, typename DerivedA, typename DerivedB>
376 struct check_transpose_aliasing_run_time_selector<Scalar,DestIsTransposed,CwiseBinaryOp<BinOp,DerivedA,DerivedB> >
377 {
378  static bool run(const Scalar* dest, const CwiseBinaryOp<BinOp,DerivedA,DerivedB>& src)
379  {
380  return ((blas_traits<DerivedA>::IsTransposed != DestIsTransposed) && (dest!=0 && dest==(Scalar*)extract_data(src.lhs())))
381  || ((blas_traits<DerivedB>::IsTransposed != DestIsTransposed) && (dest!=0 && dest==(Scalar*)extract_data(src.rhs())));
382  }
383 };
384 
385 // the following selector, checkTransposeAliasing_impl, based on MightHaveTransposeAliasing,
386 // is because when the condition controlling the assert is known at compile time, ICC emits a warning.
387 // This is actually a good warning: in expressions that don't have any transposing, the condition is
388 // known at compile time to be false, and using that, we can avoid generating the code of the assert again
389 // and again for all these expressions that don't need it.
390 
391 template<typename Derived, typename OtherDerived,
392  bool MightHaveTransposeAliasing
393  = check_transpose_aliasing_compile_time_selector
394  <blas_traits<Derived>::IsTransposed,OtherDerived>::ret
395  >
396 struct checkTransposeAliasing_impl
397 {
398  static void run(const Derived& dst, const OtherDerived& other)
399  {
400  eigen_assert((!check_transpose_aliasing_run_time_selector
401  <typename Derived::Scalar,blas_traits<Derived>::IsTransposed,OtherDerived>
402  ::run(extract_data(dst), other))
403  && "aliasing detected during tranposition, use transposeInPlace() "
404  "or evaluate the rhs into a temporary using .eval()");
405 
406  }
407 };
408 
409 template<typename Derived, typename OtherDerived>
410 struct checkTransposeAliasing_impl<Derived, OtherDerived, false>
411 {
412  static void run(const Derived&, const OtherDerived&)
413  {
414  }
415 };
416 
417 } // end namespace internal
418 
419 template<typename Derived>
420 template<typename OtherDerived>
421 void DenseBase<Derived>::checkTransposeAliasing(const OtherDerived& other) const
422 {
423  internal::checkTransposeAliasing_impl<Derived, OtherDerived>::run(derived(), other);
424 }
425 #endif
426 
427 } // end namespace Eigen
428 
429 #endif // EIGEN_TRANSPOSE_H