add transposeInPlace (not optimized yet for rectangular matrix)

This commit is contained in:
Gael Guennebaud 2008-10-29 15:24:08 +00:00
parent 48137e28d8
commit ebe14aae7d
4 changed files with 66 additions and 6 deletions

View File

@ -337,6 +337,7 @@ template<typename Derived> class MatrixBase
Transpose<Derived> transpose(); Transpose<Derived> transpose();
const Transpose<Derived> transpose() const; const Transpose<Derived> transpose() const;
void transposeInPlace();
const AdjointReturnType adjoint() const; const AdjointReturnType adjoint() const;

View File

@ -119,6 +119,12 @@ template<typename MatrixType, unsigned int Mode> class Part
const Block<Part, RowsAtCompileTime, 1> col(int i) { return Base::col(i); } const Block<Part, RowsAtCompileTime, 1> col(int i) { return Base::col(i); }
const Block<Part, RowsAtCompileTime, 1> col(int i) const { return Base::col(i); } const Block<Part, RowsAtCompileTime, 1> col(int i) const { return Base::col(i); }
template<typename OtherDerived/*, int OtherMode*/>
void swap(const MatrixBase<OtherDerived>& other)
{
Part<SwapWrapper<MatrixType>,Mode>(SwapWrapper<MatrixType>(const_cast<MatrixType&>(m_matrix))).lazyAssign(other.derived());
}
protected: protected:
const typename MatrixType::Nested m_matrix; const typename MatrixType::Nested m_matrix;
@ -184,7 +190,7 @@ struct ei_part_assignment_impl
|| (Mode == Lower && row >= col) || (Mode == Lower && row >= col)
|| (Mode == StrictlyUpper && row < col) || (Mode == StrictlyUpper && row < col)
|| (Mode == StrictlyLower && row > col)) || (Mode == StrictlyLower && row > col))
dst.coeffRef(row, col) = src.coeff(row, col); dst.copyCoeff(row, col, src);
} }
} }
}; };
@ -195,7 +201,7 @@ struct ei_part_assignment_impl<Derived1, Derived2, Mode, 1>
inline static void run(Derived1 &dst, const Derived2 &src) inline static void run(Derived1 &dst, const Derived2 &src)
{ {
if(!(Mode & ZeroDiagBit)) if(!(Mode & ZeroDiagBit))
dst.coeffRef(0, 0) = src.coeff(0, 0); dst.copyCoeff(0, 0, src);
} }
}; };
@ -213,7 +219,7 @@ struct ei_part_assignment_impl<Derived1, Derived2, Upper, Dynamic>
{ {
for(int j = 0; j < dst.cols(); j++) for(int j = 0; j < dst.cols(); j++)
for(int i = 0; i <= j; i++) for(int i = 0; i <= j; i++)
dst.coeffRef(i, j) = src.coeff(i, j); dst.copyCoeff(i, j, src);
} }
}; };
@ -224,7 +230,7 @@ struct ei_part_assignment_impl<Derived1, Derived2, Lower, Dynamic>
{ {
for(int j = 0; j < dst.cols(); j++) for(int j = 0; j < dst.cols(); j++)
for(int i = j; i < dst.rows(); i++) for(int i = j; i < dst.rows(); i++)
dst.coeffRef(i, j) = src.coeff(i, j); dst.copyCoeff(i, j, src);
} }
}; };
@ -235,7 +241,7 @@ struct ei_part_assignment_impl<Derived1, Derived2, StrictlyUpper, Dynamic>
{ {
for(int j = 0; j < dst.cols(); j++) for(int j = 0; j < dst.cols(); j++)
for(int i = 0; i < j; i++) for(int i = 0; i < j; i++)
dst.coeffRef(i, j) = src.coeff(i, j); dst.copyCoeff(i, j, src);
} }
}; };
template<typename Derived1, typename Derived2> template<typename Derived1, typename Derived2>
@ -245,7 +251,7 @@ struct ei_part_assignment_impl<Derived1, Derived2, StrictlyLower, Dynamic>
{ {
for(int j = 0; j < dst.cols(); j++) for(int j = 0; j < dst.cols(); j++)
for(int i = j+1; i < dst.rows(); i++) for(int i = j+1; i < dst.rows(); i++)
dst.coeffRef(i, j) = src.coeff(i, j); dst.copyCoeff(i, j, src);
} }
}; };
template<typename Derived1, typename Derived2> template<typename Derived1, typename Derived2>

View File

@ -156,4 +156,49 @@ MatrixBase<Derived>::adjoint() const
return conjugate().nestByValue(); return conjugate().nestByValue();
} }
/***************************************************************************
* "in place" transpose implementation
***************************************************************************/
template<typename MatrixType,
bool IsSquare = (MatrixType::RowsAtCompileTime == MatrixType::ColsAtCompileTime) && MatrixType::RowsAtCompileTime!=Dynamic>
struct ei_inplace_transpose_selector;
template<typename MatrixType>
struct ei_inplace_transpose_selector<MatrixType,true> { // square matrix
static void run(MatrixType& m) {
m.template part<StrictlyUpper>().swap(m.transpose());
}
};
template<typename MatrixType>
struct ei_inplace_transpose_selector<MatrixType,false> { // non square matrix
static void run(MatrixType& m) {
if (m.rows()==m.cols())
m.template part<StrictlyUpper>().swap(m.transpose());
else
m.set(m.transpose().eval());
}
};
/** This is the "in place" version of transpose: it transposes \c *this.
*
* In most cases it is probably better to simply use the transposed expression
* of a matrix. However, when transposing the matrix data itself is really needed,
* then this "in-place" version is probably the right choice because it provides
* the following additional features:
* - less error prone: doing the same operation with .transpose() requires special care:
* \code m.set(m.transpose().eval()); \endcode
* - no temporary object is created (currently only for squared matrices)
* - it allows future optimizations (cache friendliness, etc.)
*
* \note if the matrix is not square, then \c *this must be a resizable matrix.
*
* \sa transpose(), adjoint() */
template<typename Derived>
inline void MatrixBase<Derived>::transposeInPlace()
{
ei_inplace_transpose_selector<Derived>::run(derived());
}
#endif // EIGEN_TRANSPOSE_H #endif // EIGEN_TRANSPOSE_H

View File

@ -90,6 +90,14 @@ template<typename MatrixType> void adjoint(const MatrixType& m)
// normalized() in order to produce a consistent result. // normalized() in order to produce a consistent result.
VERIFY_IS_APPROX(VectorType::Random(rows).normalized().norm(), RealScalar(1)); VERIFY_IS_APPROX(VectorType::Random(rows).normalized().norm(), RealScalar(1));
} }
// check inplace transpose
m3 = m1;
m3.transposeInPlace();
VERIFY_IS_APPROX(m3,m1.transpose());
m3.transposeInPlace();
VERIFY_IS_APPROX(m3,m1);
} }
void test_adjoint() void test_adjoint()