From 88bb2087c100d21f40546829759ebd58d14947ff Mon Sep 17 00:00:00 2001 From: Benoit Jacob Date: Tue, 5 Aug 2008 21:55:57 +0000 Subject: [PATCH] New implementation of Swap as discussed, reusing Assign. Makes LU run 10% faster overall. --- Eigen/src/Core/Swap.h | 136 ++++++++++++++-------- Eigen/src/Core/util/ForwardDeclarations.h | 1 + 2 files changed, 90 insertions(+), 47 deletions(-) diff --git a/Eigen/src/Core/Swap.h b/Eigen/src/Core/Swap.h index 3b864789e..0ee57017e 100644 --- a/Eigen/src/Core/Swap.h +++ b/Eigen/src/Core/Swap.h @@ -25,8 +25,94 @@ #ifndef EIGEN_SWAP_H #define EIGEN_SWAP_H -template -struct ei_swap_selector; +/** \class SwapWrapper + * + * \brief Expression which must be nested by value + * + * \param ExpressionType the type of the object of which we are requiring nesting-by-value + * + * This class is the return type of MatrixBase::nestByValue() + * and most of the time this is the only way it is used. + * + * \sa MatrixBase::nestByValue() + */ +template +struct ei_traits > +{ + typedef typename ExpressionType::Scalar Scalar; + enum { + RowsAtCompileTime = ExpressionType::RowsAtCompileTime, + ColsAtCompileTime = ExpressionType::ColsAtCompileTime, + MaxRowsAtCompileTime = ExpressionType::MaxRowsAtCompileTime, + MaxColsAtCompileTime = ExpressionType::MaxColsAtCompileTime, + Flags = ExpressionType::Flags, + CoeffReadCost = ExpressionType::CoeffReadCost + }; +}; + +template class SwapWrapper + : public MatrixBase > +{ + public: + + EIGEN_GENERIC_PUBLIC_INTERFACE(SwapWrapper) + typedef typename ei_packet_traits::type Packet; + + inline SwapWrapper(ExpressionType& matrix) : m_expression(matrix) {} + + inline int rows() const { return m_expression.rows(); } + inline int cols() const { return m_expression.cols(); } + inline int stride() const { return m_expression.stride(); } + + template + void copyCoeff(int row, int col, const MatrixBase& other) + { + OtherDerived& _other = other.const_cast_derived(); + ei_internal_assert(row >= 0 && row < rows() + && col >= 0 && col < cols()); + Scalar tmp = m_expression.coeff(row, col); + m_expression.coeffRef(row, col) = _other.coeff(row, col); + _other.coeffRef(row, col) = tmp; + } + + template + void copyCoeff(int index, const MatrixBase& other) + { + OtherDerived& _other = other.const_cast_derived(); + ei_internal_assert(index >= 0 && index < m_expression.size()); + Scalar tmp = m_expression.coeff(index); + m_expression.coeffRef(index) = _other.coeff(index); + _other.coeffRef(index) = tmp; + } + + template + void copyPacket(int row, int col, const MatrixBase& other) + { + OtherDerived& _other = other.const_cast_derived(); + ei_internal_assert(row >= 0 && row < rows() + && col >= 0 && col < cols()); + Packet tmp = m_expression.template packet(row, col); + m_expression.template writePacket(row, col, + _other.template packet(row, col) + ); + _other.template writePacket(row, col, tmp); + } + + template + void copyPacket(int index, const MatrixBase& other) + { + OtherDerived& _other = other.const_cast_derived(); + ei_internal_assert(index >= 0 && index < m_expression.size()); + Packet tmp = m_expression.template packet(index); + m_expression.template writePacket(index, + _other.template packet(index) + ); + _other.template writePacket(index, tmp); + } + + protected: + ExpressionType m_expression; +}; /** swaps *this with the expression \a other. * @@ -41,51 +127,7 @@ template template void MatrixBase::swap(const MatrixBase& other) { - MatrixBase *_other = const_cast*>(&other); - - // disable that path: it makes LU decomposition fail ! I can't see the bug though. - if(false /*SizeAtCompileTime == Dynamic*/) - { - ei_swap_selector::run(derived(),other.const_cast_derived()); - } - else // SizeAtCompileTime != Dynamic - { - typename Derived::Eval buf(*this); - *this = other; - *_other = buf; - } + SwapWrapper(derived()).lazyAssign(other); } -template -struct ei_swap_selector -{ - inline static void run(Derived& src, OtherDerived& other) - { - typename Derived::Scalar tmp; - ei_assert(OtherDerived::IsVectorAtCompileTime && src.size() == other.size()); - for(int i = 0; i < src.size(); i++) - { - tmp = src.coeff(i); - src.coeffRef(i) = other.coeff(i); - other.coeffRef(i) = tmp; - } - } -}; - -template -struct ei_swap_selector -{ - inline static void run(Derived& src, OtherDerived& other) - { - typename Derived::Scalar tmp; - for(int j = 0; j < src.cols(); j++) - for(int i = 0; i < src.rows(); i++) - { - tmp = src.coeff(i, j); - src.coeffRef(i, j) = other.coeff(i, j); - other.coeffRef(i, j) = tmp; - } - } -}; - #endif // EIGEN_SWAP_H diff --git a/Eigen/src/Core/util/ForwardDeclarations.h b/Eigen/src/Core/util/ForwardDeclarations.h index 067ccd0b0..a886a90d0 100644 --- a/Eigen/src/Core/util/ForwardDeclarations.h +++ b/Eigen/src/Core/util/ForwardDeclarations.h @@ -41,6 +41,7 @@ class Matrix; template class Flagged; template class NestByValue; +template class SwapWrapper; template class Minor; template::Flags&DirectAccessBit> class Block;