From b868bfb84a4a86231bb338e9bcf08afd882d32dc Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Wed, 25 Jun 2014 17:23:52 +0200 Subject: [PATCH] Make operator=(EigenBase<>) uses the new assignment mechanism and introduce a generic EigenBase to EigenBase assignment kind based on the previous evalTo mechanism. --- Eigen/src/Core/Assign.h | 2 +- Eigen/src/Core/AssignEvaluator.h | 21 ++++++++++++++++++- Eigen/src/Core/BandMatrix.h | 23 +++++++++++++++++++++ Eigen/src/Core/CoreEvaluators.h | 7 ++----- Eigen/src/Core/DiagonalMatrix.h | 21 +++++++++++++++++++ Eigen/src/Core/PermutationMatrix.h | 2 ++ Eigen/src/Householder/HouseholderSequence.h | 12 +++++++++++ Eigen/src/SparseCore/SparseAssign.h | 20 ++++++++++++++++++ Eigen/src/SparseCore/SparseBlock.h | 16 +++++++------- Eigen/src/SparseCore/SparseMatrixBase.h | 2 ++ 10 files changed, 111 insertions(+), 15 deletions(-) diff --git a/Eigen/src/Core/Assign.h b/Eigen/src/Core/Assign.h index abbba84c3..071cfbf7e 100644 --- a/Eigen/src/Core/Assign.h +++ b/Eigen/src/Core/Assign.h @@ -611,7 +611,7 @@ template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& MatrixBase::operator=(const EigenBase& other) { - other.derived().evalTo(derived()); + internal::call_assignment(derived(), other.derived()); return derived(); } diff --git a/Eigen/src/Core/AssignEvaluator.h b/Eigen/src/Core/AssignEvaluator.h index 77b4dd9bc..c45ac96f2 100644 --- a/Eigen/src/Core/AssignEvaluator.h +++ b/Eigen/src/Core/AssignEvaluator.h @@ -663,7 +663,9 @@ template struct AssignmentKind; // Assignement kind defined in this file: struct Dense2Dense {}; +struct EigenBase2EigenBase {}; +template struct AssignmentKind { typedef EigenBase2EigenBase Kind; }; template<> struct AssignmentKind { typedef Dense2Dense Kind; }; // This is the main assignment class @@ -750,8 +752,12 @@ void call_assignment_no_alias(Dst& dst, const Src& src, const Func& func) // TODO check whether this is the right place to perform these checks: EIGEN_STATIC_ASSERT_LVALUE(Dst) EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(ActualDstTypeCleaned,Src) - EIGEN_CHECK_BINARY_COMPATIBILIY(Func,typename ActualDstTypeCleaned::Scalar,typename Src::Scalar); + // TODO this line is commented to allow matrix = permutation + // Actually, the "Scalar" type for a permutation matrix does not really make sense, + // perhaps it could be void, and EIGEN_CHECK_BINARY_COMPATIBILIY could allow micing void with anything...? +// EIGEN_CHECK_BINARY_COMPATIBILIY(Func,typename ActualDstTypeCleaned::Scalar,typename Src::Scalar); + Assignment::run(actualDst, src, func); } template @@ -772,6 +778,19 @@ struct Assignment } }; +// Generic assignment through evalTo. +// TODO: not sure we have to keep that one, but it helps porting current code to new evaluator mechanism. +template< typename DstXprType, typename SrcXprType, typename Functor, typename Scalar> +struct Assignment +{ + static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op &/*func*/) + { + eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); + + src.evalTo(dst); + } +}; + } // namespace internal } // end namespace Eigen diff --git a/Eigen/src/Core/BandMatrix.h b/Eigen/src/Core/BandMatrix.h index ffd7fe8b3..ba4749707 100644 --- a/Eigen/src/Core/BandMatrix.h +++ b/Eigen/src/Core/BandMatrix.h @@ -327,6 +327,29 @@ class TridiagonalMatrix : public BandMatrix +struct evaluator_traits > + : public evaluator_traits_base > +{ + typedef BandShape Shape; +}; + +template +struct evaluator_traits > + : public evaluator_traits_base > +{ + typedef BandShape Shape; +}; + +template<> struct AssignmentKind { typedef EigenBase2EigenBase Kind; }; +#endif + + } // end namespace internal } // end namespace Eigen diff --git a/Eigen/src/Core/CoreEvaluators.h b/Eigen/src/Core/CoreEvaluators.h index 81b4d63bf..f9f229b09 100644 --- a/Eigen/src/Core/CoreEvaluators.h +++ b/Eigen/src/Core/CoreEvaluators.h @@ -32,10 +32,7 @@ struct storage_kind_to_evaluator_kind { template struct storage_kind_to_shape; -template<> -struct storage_kind_to_shape { - typedef DenseShape Shape; -}; +template<> struct storage_kind_to_shape { typedef DenseShape Shape; }; // Evaluators have to be specialized with respect to various criteria such as: // - storage/structure/shape @@ -507,7 +504,7 @@ protected: // -------------------- CwiseUnaryView -------------------- template -struct unary_evaluator > +struct unary_evaluator, IndexBased> : evaluator_base > { typedef CwiseUnaryView XprType; diff --git a/Eigen/src/Core/DiagonalMatrix.h b/Eigen/src/Core/DiagonalMatrix.h index ba0042ba4..fc9ecf561 100644 --- a/Eigen/src/Core/DiagonalMatrix.h +++ b/Eigen/src/Core/DiagonalMatrix.h @@ -44,6 +44,8 @@ class DiagonalBase : public EigenBase EIGEN_DEVICE_FUNC DenseMatrixType toDenseMatrix() const { return derived(); } + +#ifndef EIGEN_TEST_EVALUATORS template EIGEN_DEVICE_FUNC void evalTo(MatrixBase &other) const; @@ -55,6 +57,7 @@ class DiagonalBase : public EigenBase EIGEN_DEVICE_FUNC void subTo(MatrixBase &other) const { other.diagonal() -= diagonal(); } +#endif // EIGEN_TEST_EVALUATORS EIGEN_DEVICE_FUNC inline const DiagonalVectorType& diagonal() const { return derived().diagonal(); } @@ -122,6 +125,7 @@ class DiagonalBase : public EigenBase #endif }; +#ifndef EIGEN_TEST_EVALUATORS template template void DiagonalBase::evalTo(MatrixBase &other) const @@ -129,6 +133,8 @@ void DiagonalBase::evalTo(MatrixBase &other) const other.setZero(); other.diagonal() = diagonal(); } +#endif // EIGEN_TEST_EVALUATORS + #endif /** \class DiagonalMatrix @@ -376,6 +382,21 @@ struct evaluator_traits > static const int AssumeAliasing = 0; }; +struct Diagonal2Dense {}; + +template<> struct AssignmentKind { typedef Diagonal2Dense Kind; }; + +// Diagonal matrix to Dense assignment +template< typename DstXprType, typename SrcXprType, typename Functor, typename Scalar> +struct Assignment +{ + static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op &/*func*/) + { + dst.setZero(); + dst.diagonal() = src.diagonal(); + } +}; + } // namespace internal #endif // EIGEN_ENABLE_EVALUATORS diff --git a/Eigen/src/Core/PermutationMatrix.h b/Eigen/src/Core/PermutationMatrix.h index 61aa0ce31..4399e1d64 100644 --- a/Eigen/src/Core/PermutationMatrix.h +++ b/Eigen/src/Core/PermutationMatrix.h @@ -803,6 +803,8 @@ struct evaluator_traits > > static const int AssumeAliasing = 0; }; +template<> struct AssignmentKind { typedef EigenBase2EigenBase Kind; }; + } // end namespace internal #endif // EIGEN_TEST_EVALUATORS diff --git a/Eigen/src/Householder/HouseholderSequence.h b/Eigen/src/Householder/HouseholderSequence.h index d800ca1fa..99d3eb21f 100644 --- a/Eigen/src/Householder/HouseholderSequence.h +++ b/Eigen/src/Householder/HouseholderSequence.h @@ -73,6 +73,18 @@ struct traits > }; }; +#ifdef EIGEN_TEST_EVALUATORS + +struct HouseholderSequenceShape {}; + +template +struct evaluator_traits > + : public evaluator_traits_base > +{ + typedef HouseholderSequenceShape Shape; +}; +#endif + template struct hseq_side_dependent_impl { diff --git a/Eigen/src/SparseCore/SparseAssign.h b/Eigen/src/SparseCore/SparseAssign.h index d4434e0ae..86a0b08c5 100644 --- a/Eigen/src/SparseCore/SparseAssign.h +++ b/Eigen/src/SparseCore/SparseAssign.h @@ -167,8 +167,10 @@ struct storage_kind_to_shape { }; struct Sparse2Sparse {}; +struct Sparse2Dense {}; template<> struct AssignmentKind { typedef Sparse2Sparse Kind; }; +template<> struct AssignmentKind { typedef Sparse2Dense Kind; }; template @@ -242,6 +244,24 @@ struct Assignment } }; +// Sparse to Dense assignment +template< typename DstXprType, typename SrcXprType, typename Functor, typename Scalar> +struct Assignment +{ + static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op &/*func*/) + { + eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); + typedef typename SrcXprType::Index Index; + + dst.setZero(); + typename internal::evaluator::type srcEval(src); + typename internal::evaluator::type dstEval(dst); + for (Index j=0; j::InnerIterator i(srcEval,j); i; ++i) + dstEval.coeffRef(i.row(),i.col()) = i.value(); + } +}; + } // end namespace internal #endif // EIGEN_TEST_EVALUATORS diff --git a/Eigen/src/SparseCore/SparseBlock.h b/Eigen/src/SparseCore/SparseBlock.h index 4926f6923..f562b5479 100644 --- a/Eigen/src/SparseCore/SparseBlock.h +++ b/Eigen/src/SparseCore/SparseBlock.h @@ -67,7 +67,7 @@ public: Index nonZeros() const { #ifndef EIGEN_TEST_EVALUATORS - typedef typename internal::evaluator::type EvaluatorType; + Index nnz = 0; Index end = m_outerStart + m_outerSize.value(); for(int j=m_outerStart; j class unary_evaluator, IteratorBased>::OuterVectorInnerIterator { - const XprType& m_block; + const unary_evaluator& m_eval; Index m_outerPos; Index m_innerIndex; Scalar m_value; @@ -649,10 +649,10 @@ class unary_evaluator, IteratorBas public: EIGEN_STRONG_INLINE OuterVectorInnerIterator(const unary_evaluator& aEval, Index outer) - : m_block(aEval.m_block), - m_outerPos( (IsRowMajor ? aEval.startCol() : aEval.startRow()) - 1), // -1 so that operator++ finds the first non-zero entry - m_innerIndex(IsRowMajor ? aEval.startRow() : aEval.startCol()), - m_end(IsRowMajor ? aEval.startCol()+aEval.blockCols() : aEval.startRow()+aEval.blockRows()) + : m_eval(aEval), + m_outerPos( (IsRowMajor ? aEval.m_block.startCol() : aEval.m_block.startRow()) - 1), // -1 so that operator++ finds the first non-zero entry + m_innerIndex(IsRowMajor ? aEval.m_block.startRow() : aEval.m_block.startCol()), + m_end(IsRowMajor ? aEval.m_block.startCol()+aEval.m_block.blockCols() : aEval.m_block.startRow()+aEval.m_block.blockRows()) { EIGEN_UNUSED_VARIABLE(outer); eigen_assert(outer==0); @@ -660,7 +660,7 @@ public: ++(*this); } - inline Index index() const { return m_outerPos - (IsRowMajor ? m_block.startCol() : m_block.startRow()); } + inline Index index() const { return m_outerPos - (IsRowMajor ? m_eval.m_block.startCol() : m_eval.m_block.startRow()); } inline Index outer() const { return 0; } inline Index row() const { return IsRowMajor ? 0 : index(); } inline Index col() const { return IsRowMajor ? index() : 0; } @@ -673,7 +673,7 @@ public: while(m_outerPos class SparseMatrixBase : public EigenBase Block innerVectors(Index outerStart, Index outerSize); const Block innerVectors(Index outerStart, Index outerSize) const; +#ifndef EIGEN_TEST_EVALUATORS /** \internal use operator= */ template void evalTo(MatrixBase& dst) const @@ -346,6 +347,7 @@ template class SparseMatrixBase : public EigenBase for (typename Derived::InnerIterator i(derived(),j); i; ++i) dst.coeffRef(i.row(),i.col()) = i.value(); } +#endif Matrix toDense() const {