From c415b627a7edcf89ceac2121f57824196be9c215 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Fri, 20 Jun 2014 15:42:13 +0200 Subject: Started to move the SparseCore module to evaluators: implemented assignment and cwise-unary evaluator --- Eigen/src/SparseCore/SparseAssign.h | 252 ++++++++++++++++++++++++++++++ Eigen/src/SparseCore/SparseCwiseUnaryOp.h | 150 +++++++++++++++++- Eigen/src/SparseCore/SparseMatrix.h | 93 +++++++++++ Eigen/src/SparseCore/SparseMatrixBase.h | 83 +--------- Eigen/src/SparseCore/SparseUtil.h | 6 + 5 files changed, 504 insertions(+), 80 deletions(-) create mode 100644 Eigen/src/SparseCore/SparseAssign.h (limited to 'Eigen/src') diff --git a/Eigen/src/SparseCore/SparseAssign.h b/Eigen/src/SparseCore/SparseAssign.h new file mode 100644 index 000000000..99a1a8712 --- /dev/null +++ b/Eigen/src/SparseCore/SparseAssign.h @@ -0,0 +1,252 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2014 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_SPARSEASSIGN_H +#define EIGEN_SPARSEASSIGN_H + +namespace Eigen { + +#ifndef EIGEN_TEST_EVALUATORS + +template +template +Derived& SparseMatrixBase::operator=(const EigenBase &other) +{ + other.derived().evalTo(derived()); + return derived(); +} + +template +template +Derived& SparseMatrixBase::operator=(const ReturnByValue& other) +{ + other.evalTo(derived()); + return derived(); +} + +template +template +inline Derived& SparseMatrixBase::operator=(const SparseMatrixBase& other) +{ + return assign(other.derived()); +} + +template +inline Derived& SparseMatrixBase::operator=(const Derived& other) +{ +// if (other.isRValue()) +// derived().swap(other.const_cast_derived()); +// else + return assign(other.derived()); +} + +template +template +inline Derived& SparseMatrixBase::assign(const OtherDerived& other) +{ + const bool transpose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit); + const Index outerSize = (int(OtherDerived::Flags) & RowMajorBit) ? other.rows() : other.cols(); + if ((!transpose) && other.isRValue()) + { + // eval without temporary + derived().resize(other.rows(), other.cols()); + derived().setZero(); + derived().reserve((std::max)(this->rows(),this->cols())*2); + for (Index j=0; j +template +inline void SparseMatrixBase::assignGeneric(const OtherDerived& other) +{ + //const bool transpose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit); + eigen_assert(( ((internal::traits::SupportedAccessPatterns&OuterRandomAccessPattern)==OuterRandomAccessPattern) || + (!((Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit)))) && + "the transpose operation is supposed to be handled in SparseMatrix::operator="); + + enum { Flip = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit) }; + + const Index outerSize = other.outerSize(); + //typedef typename internal::conditional, Derived>::type TempType; + // thanks to shallow copies, we always eval to a tempary + Derived temp(other.rows(), other.cols()); + + temp.reserve((std::max)(this->rows(),this->cols())*2); + for (Index j=0; j +// inline Derived& operator=(const SparseSparseProduct& product); +// +// template +// Derived& operator+=(const SparseMatrixBase& other); +// template +// Derived& operator-=(const SparseMatrixBase& other); +// +// Derived& operator*=(const Scalar& other); +// Derived& operator/=(const Scalar& other); +// +// template +// Derived& operator*=(const SparseMatrixBase& other); + +#else // EIGEN_TEST_EVALUATORS + +template +template +Derived& SparseMatrixBase::operator=(const EigenBase &other) +{ + other.derived().evalTo(derived()); + return derived(); +} + +template +template +Derived& SparseMatrixBase::operator=(const ReturnByValue& other) +{ + other.evalTo(derived()); + return derived(); +} + +template +template +inline Derived& SparseMatrixBase::operator=(const SparseMatrixBase& other) +{ + internal::call_assignment_no_alias(derived(), other.derived()); + return derived(); +} + +template +inline Derived& SparseMatrixBase::operator=(const Derived& other) +{ + internal::call_assignment_no_alias(derived(), other.derived()); + return derived(); +} + +namespace internal { + +template<> +struct storage_kind_to_evaluator_kind { + typedef IteratorBased Kind; +}; + +template<> +struct storage_kind_to_shape { + typedef SparseShape Shape; +}; + +struct Sparse2Sparse {}; + +template<> struct AssignmentKind { typedef Sparse2Sparse Kind; }; + + +template +void assign_sparse_to_sparse(DstXprType &dst, const SrcXprType &src) +{ + eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); + + typedef typename DstXprType::Index Index; + typedef typename DstXprType::Scalar Scalar; + typedef typename internal::evaluator::type DstEvaluatorType; + typedef typename internal::evaluator::type SrcEvaluatorType; + + DstEvaluatorType dstEvaluator(dst); + SrcEvaluatorType srcEvaluator(src); + + const bool transpose = (DstEvaluatorType::Flags & RowMajorBit) != (SrcEvaluatorType::Flags & RowMajorBit); + const Index outerSize = (int(SrcEvaluatorType::Flags) & RowMajorBit) ? src.rows() : src.cols(); + if ((!transpose) && src.isRValue()) + { + // eval without temporary + dst.resize(src.rows(), src.cols()); + dst.setZero(); + dst.reserve((std::max)(src.rows(),src.cols())*2); + for (Index j=0; j::SupportedAccessPatterns & OuterRandomAccessPattern)==OuterRandomAccessPattern) || + (!((DstEvaluatorType::Flags & RowMajorBit) != (SrcEvaluatorType::Flags & RowMajorBit)))) && + "the transpose operation is supposed to be handled in SparseMatrix::operator="); + + enum { Flip = (DstEvaluatorType::Flags & RowMajorBit) != (SrcEvaluatorType::Flags & RowMajorBit) }; + + const Index outerSize = src.outerSize(); + DstXprType temp(src.rows(), src.cols()); + + temp.reserve((std::max)(src.rows(),src.cols())*2); + for (Index j=0; j +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()); + + assign_sparse_to_sparse(dst.derived(), src.derived()); + } +}; + +} // end namespace internal + +#endif // EIGEN_TEST_EVALUATORS + +} // end namespace Eigen + +#endif // EIGEN_SPARSEASSIGN_H diff --git a/Eigen/src/SparseCore/SparseCwiseUnaryOp.h b/Eigen/src/SparseCore/SparseCwiseUnaryOp.h index 5a50c7803..c5042504b 100644 --- a/Eigen/src/SparseCore/SparseCwiseUnaryOp.h +++ b/Eigen/src/SparseCore/SparseCwiseUnaryOp.h @@ -11,6 +11,8 @@ #define EIGEN_SPARSE_CWISE_UNARY_OP_H namespace Eigen { + +#ifndef EIGEN_TEST_EVALUATORS template class CwiseUnaryOpImpl @@ -18,12 +20,12 @@ class CwiseUnaryOpImpl { public: - class InnerIterator; - class ReverseInnerIterator; - typedef CwiseUnaryOp Derived; EIGEN_SPARSE_PUBLIC_INTERFACE(Derived) + class InnerIterator; + class ReverseInnerIterator; + protected: typedef typename internal::traits::_XprTypeNested _MatrixTypeNested; typedef typename _MatrixTypeNested::InnerIterator MatrixTypeIterator; @@ -138,6 +140,148 @@ class CwiseUnaryViewImpl::ReverseInnerIterator const ViewOp m_functor; }; +#else // EIGEN_TEST_EVALUATORS + +namespace internal { + +template +struct unary_evaluator, IteratorBased> + : public evaluator_base > +{ + public: + typedef CwiseUnaryOp XprType; + + class InnerIterator; + class ReverseInnerIterator; + + enum { + CoeffReadCost = evaluator::CoeffReadCost + functor_traits::Cost, + Flags = XprType::Flags + }; + + unary_evaluator(const XprType& op) : m_functor(op.functor()), m_argImpl(op.nestedExpression()) {} + + protected: + typedef typename evaluator::InnerIterator EvalIterator; + typedef typename evaluator::ReverseInnerIterator EvalReverseIterator; + + const UnaryOp m_functor; + typename evaluator::nestedType m_argImpl; +}; + +template +class unary_evaluator, IteratorBased>::InnerIterator + : public unary_evaluator, IteratorBased>::EvalIterator +{ + typedef typename XprType::Scalar Scalar; + typedef typename unary_evaluator, IteratorBased>::EvalIterator Base; + public: + + EIGEN_STRONG_INLINE InnerIterator(const unary_evaluator& unaryOp, typename XprType::Index outer) + : Base(unaryOp.m_argImpl,outer), m_functor(unaryOp.m_functor) + {} + + EIGEN_STRONG_INLINE InnerIterator& operator++() + { Base::operator++(); return *this; } + + EIGEN_STRONG_INLINE Scalar value() const { return m_functor(Base::value()); } + + protected: + const UnaryOp m_functor; + private: + Scalar& valueRef(); +}; + +template +class unary_evaluator, IteratorBased>::ReverseInnerIterator + : public unary_evaluator, IteratorBased>::EvalReverseIterator +{ + typedef typename XprType::Scalar Scalar; + typedef typename unary_evaluator, IteratorBased>::EvalReverseIterator Base; + public: + + EIGEN_STRONG_INLINE ReverseInnerIterator(const XprType& unaryOp, typename XprType::Index outer) + : Base(unaryOp.derived().nestedExpression(),outer), m_functor(unaryOp.derived().functor()) + {} + + EIGEN_STRONG_INLINE ReverseInnerIterator& operator--() + { Base::operator--(); return *this; } + + EIGEN_STRONG_INLINE Scalar value() const { return m_functor(Base::value()); } + + protected: + const UnaryOp m_functor; + private: + Scalar& valueRef(); +}; + + +// template +// class CwiseUnaryViewImpl +// : public SparseMatrixBase > +// { +// public: +// +// class InnerIterator; +// class ReverseInnerIterator; +// +// typedef CwiseUnaryView Derived; +// EIGEN_SPARSE_PUBLIC_INTERFACE(Derived) +// +// protected: +// typedef typename internal::traits::_MatrixTypeNested _MatrixTypeNested; +// typedef typename _MatrixTypeNested::InnerIterator MatrixTypeIterator; +// typedef typename _MatrixTypeNested::ReverseInnerIterator MatrixTypeReverseIterator; +// }; +// +// template +// class CwiseUnaryViewImpl::InnerIterator +// : public CwiseUnaryViewImpl::MatrixTypeIterator +// { +// typedef typename CwiseUnaryViewImpl::Scalar Scalar; +// typedef typename CwiseUnaryViewImpl::MatrixTypeIterator Base; +// public: +// +// EIGEN_STRONG_INLINE InnerIterator(const CwiseUnaryViewImpl& unaryOp, typename CwiseUnaryViewImpl::Index outer) +// : Base(unaryOp.derived().nestedExpression(),outer), m_functor(unaryOp.derived().functor()) +// {} +// +// EIGEN_STRONG_INLINE InnerIterator& operator++() +// { Base::operator++(); return *this; } +// +// EIGEN_STRONG_INLINE typename CwiseUnaryViewImpl::Scalar value() const { return m_functor(Base::value()); } +// EIGEN_STRONG_INLINE typename CwiseUnaryViewImpl::Scalar& valueRef() { return m_functor(Base::valueRef()); } +// +// protected: +// const ViewOp m_functor; +// }; +// +// template +// class CwiseUnaryViewImpl::ReverseInnerIterator +// : public CwiseUnaryViewImpl::MatrixTypeReverseIterator +// { +// typedef typename CwiseUnaryViewImpl::Scalar Scalar; +// typedef typename CwiseUnaryViewImpl::MatrixTypeReverseIterator Base; +// public: +// +// EIGEN_STRONG_INLINE ReverseInnerIterator(const CwiseUnaryViewImpl& unaryOp, typename CwiseUnaryViewImpl::Index outer) +// : Base(unaryOp.derived().nestedExpression(),outer), m_functor(unaryOp.derived().functor()) +// {} +// +// EIGEN_STRONG_INLINE ReverseInnerIterator& operator--() +// { Base::operator--(); return *this; } +// +// EIGEN_STRONG_INLINE typename CwiseUnaryViewImpl::Scalar value() const { return m_functor(Base::value()); } +// EIGEN_STRONG_INLINE typename CwiseUnaryViewImpl::Scalar& valueRef() { return m_functor(Base::valueRef()); } +// +// protected: +// const ViewOp m_functor; +// }; + +} // end namespace internal + +#endif // EIGEN_TEST_EVALUATORS + template EIGEN_STRONG_INLINE Derived& SparseMatrixBase::operator*=(const Scalar& other) diff --git a/Eigen/src/SparseCore/SparseMatrix.h b/Eigen/src/SparseCore/SparseMatrix.h index 9ac18bcf6..a25bd83eb 100644 --- a/Eigen/src/SparseCore/SparseMatrix.h +++ b/Eigen/src/SparseCore/SparseMatrix.h @@ -1053,6 +1053,7 @@ void SparseMatrix::sumupDuplicates() m_data.resize(m_outerIndex[m_outerSize]); } +#ifndef EIGEN_TEST_EVALUATORS template template EIGEN_DONT_INLINE SparseMatrix& SparseMatrix::operator=(const SparseMatrixBase& other) @@ -1114,6 +1115,71 @@ EIGEN_DONT_INLINE SparseMatrix& SparseMatrix +template +EIGEN_DONT_INLINE SparseMatrix& SparseMatrix::operator=(const SparseMatrixBase& other) +{ + EIGEN_STATIC_ASSERT((internal::is_same::value), + YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) + + const bool needToTranspose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit); + if (needToTranspose) + { + // two passes algorithm: + // 1 - compute the number of coeffs per dest inner vector + // 2 - do the actual copy/eval + // Since each coeff of the rhs has to be evaluated twice, let's evaluate it if needed + typedef typename internal::nested_eval::type OtherCopy; + typedef typename internal::remove_all::type _OtherCopy; + typedef internal::evaluator<_OtherCopy> OtherCopyEval; + OtherCopy otherCopy(other.derived()); + OtherCopyEval otherCopyEval(otherCopy); + + SparseMatrix dest(other.rows(),other.cols()); + Eigen::Map > (dest.m_outerIndex,dest.outerSize()).setZero(); + + // pass 1 + // FIXME the above copy could be merged with that pass + for (Index j=0; j positions(dest.outerSize()); + for (Index j=0; jswap(dest); + return *this; + } + else + { + if(other.isRValue()) + initAssignment(other.derived()); + // there is no special optimization + return Base::operator=(other.derived()); + } +} +#endif template EIGEN_DONT_INLINE typename SparseMatrix<_Scalar,_Options,_Index>::Scalar& SparseMatrix<_Scalar,_Options,_Index>::insertUncompressed(Index row, Index col) @@ -1254,6 +1320,33 @@ EIGEN_DONT_INLINE typename SparseMatrix<_Scalar,_Options,_Index>::Scalar& Sparse return (m_data.value(p) = 0); } +#ifdef EIGEN_ENABLE_EVALUATORS +namespace internal { + +template +struct evaluator > + : evaluator_base > +{ + typedef SparseMatrix<_Scalar,_Options,_Index> SparseMatrixType; + typedef typename SparseMatrixType::InnerIterator InnerIterator; + typedef typename SparseMatrixType::ReverseInnerIterator ReverseInnerIterator; + + enum { + CoeffReadCost = NumTraits<_Scalar>::ReadCost, + Flags = SparseMatrixType::Flags + }; + + evaluator(const SparseMatrixType &mat) : m_matrix(mat) {} + + operator SparseMatrixType&() { return m_matrix.const_cast_derived(); } + operator const SparseMatrixType&() const { return m_matrix; } + + const SparseMatrixType &m_matrix; +}; + +} +#endif + } // end namespace Eigen #endif // EIGEN_SPARSEMATRIX_H diff --git a/Eigen/src/SparseCore/SparseMatrixBase.h b/Eigen/src/SparseCore/SparseMatrixBase.h index bbcf7fb1c..a87407fe9 100644 --- a/Eigen/src/SparseCore/SparseMatrixBase.h +++ b/Eigen/src/SparseCore/SparseMatrixBase.h @@ -39,11 +39,7 @@ template class SparseMatrixBase : public EigenBase typedef EigenBase Base; template - Derived& operator=(const EigenBase &other) - { - other.derived().evalTo(derived()); - return derived(); - } + Derived& operator=(const EigenBase &other); enum { @@ -175,87 +171,20 @@ template class SparseMatrixBase : public EigenBase template - Derived& operator=(const ReturnByValue& other) - { - other.evalTo(derived()); - return derived(); - } - + Derived& operator=(const ReturnByValue& other); template - inline Derived& operator=(const SparseMatrixBase& other) - { - return assign(other.derived()); - } + inline Derived& operator=(const SparseMatrixBase& other); - inline Derived& operator=(const Derived& other) - { -// if (other.isRValue()) -// derived().swap(other.const_cast_derived()); -// else - return assign(other.derived()); - } + inline Derived& operator=(const Derived& other); protected: template - inline Derived& assign(const OtherDerived& other) - { - const bool transpose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit); - const Index outerSize = (int(OtherDerived::Flags) & RowMajorBit) ? other.rows() : other.cols(); - if ((!transpose) && other.isRValue()) - { - // eval without temporary - derived().resize(other.rows(), other.cols()); - derived().setZero(); - derived().reserve((std::max)(this->rows(),this->cols())*2); - for (Index j=0; j - inline void assignGeneric(const OtherDerived& other) - { - //const bool transpose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit); - eigen_assert(( ((internal::traits::SupportedAccessPatterns&OuterRandomAccessPattern)==OuterRandomAccessPattern) || - (!((Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit)))) && - "the transpose operation is supposed to be handled in SparseMatrix::operator="); - - enum { Flip = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit) }; - - const Index outerSize = other.outerSize(); - //typedef typename internal::conditional, Derived>::type TempType; - // thanks to shallow copies, we always eval to a tempary - Derived temp(other.rows(), other.cols()); - - temp.reserve((std::max)(this->rows(),this->cols())*2); - for (Index j=0; j struct plain_matrix_type typedef SparseMatrix<_Scalar, _Options, _Index> type; }; +template +struct generic_xpr_base +{ + typedef SparseMatrixBase type; +}; + } // end namespace internal /** \ingroup SparseCore_Module -- cgit v1.2.3