add a generic mechanism to copy a special matrix to a dense matrix so that

we don't need to add other specialization of MatrixBase::operator=, Matrix::=,
and Matrix::Matrix(...)
This commit is contained in:
Gael Guennebaud
2009-07-07 09:05:20 +02:00
parent 1aea45335f
commit 544888e342
6 changed files with 54 additions and 113 deletions

View File

@@ -50,6 +50,8 @@ class DiagonalBase : public MultiplierBase<Derived>
#endif // not EIGEN_PARSED_BY_DOXYGEN
DenseMatrixType toDenseMatrix() const { return derived(); }
template<typename DenseDerived>
void evalToDense(MatrixBase<DenseDerived> &other) const;
inline const DiagonalVectorType& diagonal() const { return derived().diagonal(); }
inline DiagonalVectorType& diagonal() { return derived().diagonal(); }
@@ -63,12 +65,11 @@ class DiagonalBase : public MultiplierBase<Derived>
};
template<typename Derived>
template<typename DiagonalDerived>
Derived& MatrixBase<Derived>::operator=(const DiagonalBase<DiagonalDerived> &other)
template<typename DenseDerived>
void DiagonalBase<Derived>::evalToDense(MatrixBase<DenseDerived> &other) const
{
setZero();
diagonal() = other.diagonal();
return derived();
other.setZero();
other.diagonal() = diagonal();
}
/** \class DiagonalMatrix

View File

@@ -439,34 +439,20 @@ class Matrix
{ other.evalTo(*this); }
/** Destructor */
inline ~Matrix() {}
template<typename DiagonalDerived>
EIGEN_STRONG_INLINE Matrix& operator=(const DiagonalBase<DiagonalDerived> &other)
/** \sa MatrixBase::operator=(const AnyMatrixBase<OtherDerived>&) */
template<typename OtherDerived>
EIGEN_STRONG_INLINE Matrix& operator=(const AnyMatrixBase<OtherDerived> &other)
{
resize(other.diagonal().size(), other.diagonal().size());
Base::operator=(other);
return *this;
}
template<typename DiagonalDerived>
EIGEN_STRONG_INLINE Matrix(const DiagonalBase<DiagonalDerived> &other)
: m_storage(other.diagonal().size() * other.diagonal().size(), other.diagonal().size(), other.diagonal().size())
{
*this = other;
}
template<typename TriangularDerived>
EIGEN_STRONG_INLINE Matrix& operator=(const TriangularBase<TriangularDerived> &other)
{
resize(other.rows(), other.cols());
resize(other.derived().rows(), other.derived().cols());
Base::operator=(other.derived());
return *this;
}
template<typename TriangularDerived>
EIGEN_STRONG_INLINE Matrix(const TriangularBase<TriangularDerived> &other)
: m_storage(other.rows() * other.cols(), other.rows(), other.cols())
/** \sa MatrixBase::operator=(const AnyMatrixBase<OtherDerived>&) */
template<typename OtherDerived>
EIGEN_STRONG_INLINE Matrix(const AnyMatrixBase<OtherDerived> &other)
: m_storage(other.derived().rows() * other.derived().cols(), other.derived().rows(), other.derived().cols())
{
*this = other;
}

View File

@@ -284,6 +284,17 @@ template<typename Derived> class MatrixBase
*/
Derived& operator=(const MatrixBase& other);
/** Copies the generic expression \a other into *this. \returns a reference to *this.
* The expression must provide a (templated) evalToDense(Derived& dst) const function
* which does the actual job. In practice, this allows any user to write its own
* special matrix without having to modify MatrixBase */
template<typename OtherDerived>
Derived& operator=(const AnyMatrixBase<OtherDerived> &other)
{ other.derived().evalToDense(derived()); return derived(); }
template<typename OtherDerived,typename OtherEvalType>
Derived& operator=(const ReturnByValue<OtherDerived,OtherEvalType>& func);
#ifndef EIGEN_PARSED_BY_DOXYGEN
/** Copies \a other into *this without evaluating other. \returns a reference to *this. */
template<typename OtherDerived>
@@ -297,10 +308,6 @@ template<typename Derived> class MatrixBase
template<typename OtherDerived>
Derived& lazyAssign(const Flagged<OtherDerived, 0, EvalBeforeNestingBit | EvalBeforeAssigningBit>& other)
{ return lazyAssign(other._expression()); }
/** Overloaded for fast triangular part to dense matrix evaluation */
template<typename TriangularDerived>
Derived& lazyAssign(const TriangularBase<TriangularDerived> &other);
#endif // not EIGEN_PARSED_BY_DOXYGEN
CommaInitializer<Derived> operator<< (const Scalar& s);
@@ -403,12 +410,6 @@ template<typename Derived> class MatrixBase
const DiagonalProduct<Derived, DiagonalDerived, DiagonalOnTheRight>
operator*(const DiagonalBase<DiagonalDerived> &diagonal) const;
template<typename DiagonalDerived>
Derived& operator=(const DiagonalBase<DiagonalDerived> &other);
template<typename TriangularDerived>
Derived& operator=(const TriangularBase<TriangularDerived> &other);
template<typename OtherDerived>
typename ei_plain_matrix_type_column_major<OtherDerived>::type
solveTriangular(const MatrixBase<OtherDerived>& other) const;
@@ -738,9 +739,6 @@ template<typename Derived> class MatrixBase
// dense = dense * sparse
template<typename Derived1, typename Derived2>
Derived& lazyAssign(const SparseProduct<Derived1,Derived2,DenseTimeSparseProduct>& product);
template<typename OtherDerived,typename OtherEvalType>
Derived& operator=(const ReturnByValue<OtherDerived,OtherEvalType>& func);
#ifdef EIGEN_MATRIXBASE_PLUGIN
#include EIGEN_MATRIXBASE_PLUGIN

View File

@@ -90,6 +90,11 @@ template<typename Derived> class TriangularBase : public MultiplierBase<Derived>
inline Derived& derived() { return *static_cast<Derived*>(this); }
#endif // not EIGEN_PARSED_BY_DOXYGEN
template<typename DenseDerived>
void evalToDense(MatrixBase<DenseDerived> &other) const;
template<typename DenseDerived>
void evalToDenseLazy(MatrixBase<DenseDerived> &other) const;
protected:
void check_coordinates(int row, int col)
@@ -516,36 +521,34 @@ void TriangularView<MatrixType, Mode>::lazyAssign(const TriangularBase<OtherDeri
/** Assigns a triangular or selfadjoint matrix to a dense matrix.
* If the matrix is triangular, the opposite part is set to zero. */
template<typename Derived>
template<typename TriangularDerived>
Derived& MatrixBase<Derived>::operator=(const TriangularBase<TriangularDerived> &other)
template<typename DenseDerived>
void TriangularBase<Derived>::evalToDense(MatrixBase<DenseDerived> &other) const
{
if(ei_traits<TriangularDerived>::Flags & EvalBeforeAssigningBit)
if(ei_traits<Derived>::Flags & EvalBeforeAssigningBit)
{
typename TriangularDerived::PlainMatrixType other_evaluated(other.rows(), other.cols());
other_evaluated.lazyAssign(other);
this->swap(other_evaluated);
typename Derived::PlainMatrixType other_evaluated(rows(), cols());
evalToDenseLazy(other_evaluated);
other.derived().swap(other_evaluated);
}
else
lazyAssign(other.derived());
return derived();
evalToDenseLazy(other.derived());
}
/** Assigns a triangular or selfadjoint matrix to a dense matrix.
* If the matrix is triangular, the opposite part is set to zero. */
template<typename Derived>
template<typename TriangularDerived>
Derived& MatrixBase<Derived>::lazyAssign(const TriangularBase<TriangularDerived> &other)
template<typename DenseDerived>
void TriangularBase<Derived>::evalToDenseLazy(MatrixBase<DenseDerived> &other) const
{
const bool unroll = Derived::SizeAtCompileTime * TriangularDerived::CoeffReadCost / 2
const bool unroll = DenseDerived::SizeAtCompileTime * Derived::CoeffReadCost / 2
<= EIGEN_UNROLLING_LIMIT;
ei_assert(this->rows() == other.rows() && this->cols() == other.cols());
ei_part_assignment_impl
<Derived, typename ei_traits<TriangularDerived>::ExpressionType, TriangularDerived::Mode,
unroll ? int(Derived::SizeAtCompileTime) : Dynamic,
<DenseDerived, typename ei_traits<Derived>::ExpressionType, Derived::Mode,
unroll ? int(DenseDerived::SizeAtCompileTime) : Dynamic,
true // clear the opposite triangular part
>::run(this->const_cast_derived(), other.derived()._expression());
return derived();
>::run(other.derived(), derived()._expression());
}
/** \deprecated use MatrixBase::triangularView() */