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-2010 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
14namespace Eigen {
15
29
30namespace internal {
31template<typename MatrixType>
32struct traits<Transpose<MatrixType> > : traits<MatrixType>
33{
34 typedef typename MatrixType::Scalar Scalar;
35 typedef typename nested<MatrixType>::type MatrixTypeNested;
36 typedef typename remove_reference<MatrixTypeNested>::type MatrixTypeNestedPlain;
37 typedef typename traits<MatrixType>::StorageKind StorageKind;
38 typedef typename traits<MatrixType>::XprKind XprKind;
39 enum {
40 RowsAtCompileTime = MatrixType::ColsAtCompileTime,
41 ColsAtCompileTime = MatrixType::RowsAtCompileTime,
42 MaxRowsAtCompileTime = MatrixType::MaxColsAtCompileTime,
43 MaxColsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
44 FlagsLvalueBit = is_lvalue<MatrixType>::value ? LvalueBit : 0,
45 Flags0 = MatrixTypeNestedPlain::Flags & ~(LvalueBit | NestByRefBit),
46 Flags1 = Flags0 | FlagsLvalueBit,
47 Flags = Flags1 ^ RowMajorBit,
48 CoeffReadCost = MatrixTypeNestedPlain::CoeffReadCost,
49 InnerStrideAtCompileTime = inner_stride_at_compile_time<MatrixType>::ret,
50 OuterStrideAtCompileTime = outer_stride_at_compile_time<MatrixType>::ret
51 };
52};
53}
54
55template<typename MatrixType, typename StorageKind> class TransposeImpl;
56
57template<typename MatrixType> class Transpose
58 : public TransposeImpl<MatrixType,typename internal::traits<MatrixType>::StorageKind>
59{
60 public:
61
62 typedef typename TransposeImpl<MatrixType,typename internal::traits<MatrixType>::StorageKind>::Base Base;
63 EIGEN_GENERIC_PUBLIC_INTERFACE(Transpose)
64
65 inline Transpose(MatrixType& matrix) : m_matrix(matrix) {}
66
67 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Transpose)
68
69 inline Index rows() const { return m_matrix.cols(); }
70 inline Index cols() const { return m_matrix.rows(); }
71
73 const typename internal::remove_all<typename MatrixType::Nested>::type&
74 nestedExpression() const { return m_matrix; }
75
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
84namespace internal {
85
86template<typename MatrixType, bool HasDirectAccess = has_direct_access<MatrixType>::ret>
87struct TransposeImpl_base
88{
89 typedef typename dense_xpr_base<Transpose<MatrixType> >::type type;
90};
91
92template<typename MatrixType>
93struct TransposeImpl_base<MatrixType, false>
94{
95 typedef typename dense_xpr_base<Transpose<MatrixType> >::type type;
96};
97
98} // end namespace internal
99
100template<typename MatrixType> class TransposeImpl<MatrixType,Dense>
101 : public internal::TransposeImpl_base<MatrixType>::type
102{
103 public:
104
105 typedef typename internal::TransposeImpl_base<MatrixType>::type Base;
106 EIGEN_DENSE_PUBLIC_INTERFACE(Transpose<MatrixType>)
107 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(TransposeImpl)
108
109 inline Index innerStride() const { return derived().nestedExpression().innerStride(); }
110 inline Index outerStride() const { return derived().nestedExpression().outerStride(); }
111
112 typedef typename internal::conditional<
113 internal::is_lvalue<MatrixType>::value,
114 Scalar,
115 const Scalar
116 >::type ScalarWithConstIfNotLvalue;
117
118 inline ScalarWithConstIfNotLvalue* data() { return derived().nestedExpression().data(); }
119 inline const Scalar* data() const { return derived().nestedExpression().data(); }
120
121 inline ScalarWithConstIfNotLvalue& coeffRef(Index row, Index col)
122 {
123 EIGEN_STATIC_ASSERT_LVALUE(MatrixType)
124 return derived().nestedExpression().const_cast_derived().coeffRef(col, row);
125 }
126
127 inline ScalarWithConstIfNotLvalue& coeffRef(Index index)
128 {
129 EIGEN_STATIC_ASSERT_LVALUE(MatrixType)
130 return derived().nestedExpression().const_cast_derived().coeffRef(index);
131 }
132
133 inline const Scalar& coeffRef(Index row, Index col) const
134 {
135 return derived().nestedExpression().coeffRef(col, row);
136 }
137
138 inline const Scalar& coeffRef(Index index) const
139 {
140 return derived().nestedExpression().coeffRef(index);
141 }
142
143 inline CoeffReturnType coeff(Index row, Index col) const
144 {
145 return derived().nestedExpression().coeff(col, row);
146 }
147
148 inline CoeffReturnType coeff(Index index) const
149 {
150 return derived().nestedExpression().coeff(index);
151 }
152
153 template<int LoadMode>
154 inline const PacketScalar packet(Index row, Index col) const
155 {
156 return derived().nestedExpression().template packet<LoadMode>(col, row);
157 }
158
159 template<int LoadMode>
160 inline void writePacket(Index row, Index col, const PacketScalar& x)
161 {
162 derived().nestedExpression().const_cast_derived().template writePacket<LoadMode>(col, row, x);
163 }
164
165 template<int LoadMode>
166 inline const PacketScalar packet(Index index) const
167 {
168 return derived().nestedExpression().template packet<LoadMode>(index);
169 }
170
171 template<int LoadMode>
172 inline void writePacket(Index index, const PacketScalar& x)
173 {
174 derived().nestedExpression().const_cast_derived().template writePacket<LoadMode>(index, x);
175 }
176};
177
197template<typename Derived>
201 return derived();
202}
203
209template<typename Derived>
210inline const typename DenseBase<Derived>::ConstTransposeReturnType
212{
213 return ConstTransposeReturnType(derived());
214}
215
235template<typename Derived>
236inline const typename MatrixBase<Derived>::AdjointReturnType
238{
239 return this->transpose(); // in the complex case, the .conjugate() is be implicit here
240 // due to implicit conversion to return type
241}
242
243/***************************************************************************
244* "in place" transpose implementation
245***************************************************************************/
246
247namespace internal {
248
249template<typename MatrixType,
250 bool IsSquare = (MatrixType::RowsAtCompileTime == MatrixType::ColsAtCompileTime) && MatrixType::RowsAtCompileTime!=Dynamic>
251struct inplace_transpose_selector;
252
253template<typename MatrixType>
254struct inplace_transpose_selector<MatrixType,true> { // square matrix
255 static void run(MatrixType& m) {
256 m.matrix().template triangularView<StrictlyUpper>().swap(m.matrix().transpose());
257 }
258};
259
260template<typename MatrixType>
261struct inplace_transpose_selector<MatrixType,false> { // non square matrix
262 static void run(MatrixType& m) {
263 if (m.rows()==m.cols())
264 m.matrix().template triangularView<StrictlyUpper>().swap(m.matrix().transpose());
265 else
266 m = m.transpose().eval();
267 }
268};
269
270} // end namespace internal
271
273 * Thus, doing
274 * \code
275 * m.transposeInPlace();
276 * \endcode
277 * has the same effect on m as doing
278 * \code
279 * m = m.transpose().eval();
280 * \endcode
281 * and is faster and also safer because in the latter line of code, forgetting the eval() results
282 * in a bug caused by aliasing.
283 *
284 * Notice however that this method is only useful if you want to replace a matrix by its own transpose.
285 * If you just need the transpose of a matrix, use transpose().
286 *
287 * \note if the matrix is not square, then \c *this must be a resizable matrix.
288 *
289 * \sa transpose(), adjoint(), adjointInPlace() */
290template<typename Derived>
292{
293 internal::inplace_transpose_selector<Derived>::run(derived());
294}
295
296/***************************************************************************
297* "in place" adjoint implementation
298***************************************************************************/
299
318template<typename Derived>
320{
321 derived() = adjoint().eval();
322}
323
324#ifndef EIGEN_NO_DEBUG
325
326// The following is to detect aliasing problems in most common cases.
327
328namespace internal {
329
330template<typename BinOp,typename NestedXpr,typename Rhs>
331struct blas_traits<SelfCwiseBinaryOp<BinOp,NestedXpr,Rhs> >
332 : blas_traits<NestedXpr>
333{
334 typedef SelfCwiseBinaryOp<BinOp,NestedXpr,Rhs> XprType;
335 static inline const XprType extract(const XprType& x) { return x; }
336};
337
338template<bool DestIsTransposed, typename OtherDerived>
339struct check_transpose_aliasing_compile_time_selector
340{
341 enum { ret = bool(blas_traits<OtherDerived>::IsTransposed) != DestIsTransposed };
342};
343
344template<bool DestIsTransposed, typename BinOp, typename DerivedA, typename DerivedB>
345struct check_transpose_aliasing_compile_time_selector<DestIsTransposed,CwiseBinaryOp<BinOp,DerivedA,DerivedB> >
346{
347 enum { ret = bool(blas_traits<DerivedA>::IsTransposed) != DestIsTransposed
348 || bool(blas_traits<DerivedB>::IsTransposed) != DestIsTransposed
349 };
350};
351
352template<typename Scalar, bool DestIsTransposed, typename OtherDerived>
353struct check_transpose_aliasing_run_time_selector
354{
355 static bool run(const Scalar* dest, const OtherDerived& src)
356 {
357 return (bool(blas_traits<OtherDerived>::IsTransposed) != DestIsTransposed) && (dest!=0 && dest==(const Scalar*)extract_data(src));
358 }
359};
360
361template<typename Scalar, bool DestIsTransposed, typename BinOp, typename DerivedA, typename DerivedB>
362struct check_transpose_aliasing_run_time_selector<Scalar,DestIsTransposed,CwiseBinaryOp<BinOp,DerivedA,DerivedB> >
363{
364 static bool run(const Scalar* dest, const CwiseBinaryOp<BinOp,DerivedA,DerivedB>& src)
365 {
366 return ((blas_traits<DerivedA>::IsTransposed != DestIsTransposed) && (dest!=0 && dest==(const Scalar*)extract_data(src.lhs())))
367 || ((blas_traits<DerivedB>::IsTransposed != DestIsTransposed) && (dest!=0 && dest==(const Scalar*)extract_data(src.rhs())));
368 }
369};
370
371// the following selector, checkTransposeAliasing_impl, based on MightHaveTransposeAliasing,
372// is because when the condition controlling the assert is known at compile time, ICC emits a warning.
373// This is actually a good warning: in expressions that don't have any transposing, the condition is
374// known at compile time to be false, and using that, we can avoid generating the code of the assert again
375// and again for all these expressions that don't need it.
376
377template<typename Derived, typename OtherDerived,
378 bool MightHaveTransposeAliasing
379 = check_transpose_aliasing_compile_time_selector
380 <blas_traits<Derived>::IsTransposed,OtherDerived>::ret
381 >
382struct checkTransposeAliasing_impl
383{
384 static void run(const Derived& dst, const OtherDerived& other)
385 {
386 eigen_assert((!check_transpose_aliasing_run_time_selector
387 <typename Derived::Scalar,blas_traits<Derived>::IsTransposed,OtherDerived>
388 ::run(extract_data(dst), other))
389 && "aliasing detected during tranposition, use transposeInPlace() "
390 "or evaluate the rhs into a temporary using .eval()");
391
392 }
393};
394
395template<typename Derived, typename OtherDerived>
396struct checkTransposeAliasing_impl<Derived, OtherDerived, false>
397{
398 static void run(const Derived&, const OtherDerived&)
399 {
400 }
401};
402
403} // end namespace internal
404
405template<typename Derived>
406template<typename OtherDerived>
407void DenseBase<Derived>::checkTransposeAliasing(const OtherDerived& other) const
408{
409 internal::checkTransposeAliasing_impl<Derived, OtherDerived>::run(derived(), other);
410}
411#endif
412
413} // end namespace Eigen
414
415#endif // EIGEN_TRANSPOSE_H
Generic expression where a coefficient-wise binary operator is applied to two expressions.
Definition CwiseBinaryOp.h:111
void transposeInPlace()
Definition Transpose.h:291
Eigen::Transpose< Derived > transpose()
Definition Transpose.h:199
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:50
void adjointInPlace()
Definition Transpose.h:319
const AdjointReturnType adjoint() const
Definition Transpose.h:237
const MatrixType & matrix() const
Definition Transform.h:367
Expression of the transpose of a matrix.
Definition Transpose.h:59
internal::remove_all< typenameMatrixType::Nested >::type & nestedExpression()
Definition Transpose.h:78
const internal::remove_all< typenameMatrixType::Nested >::type & nestedExpression() const
Definition Transpose.h:74
const unsigned int LvalueBit
Definition Constants.h:126
const unsigned int RowMajorBit
Definition Constants.h:48
Definition LDLT.h:18
Definition Constants.h:421