diff options
author | Gael Guennebaud <g.gael@free.fr> | 2014-06-26 13:52:19 +0200 |
---|---|---|
committer | Gael Guennebaud <g.gael@free.fr> | 2014-06-26 13:52:19 +0200 |
commit | f0648f886058a85930186bd935ffb2c9fa87b1f3 (patch) | |
tree | c1b24747937aac2a9a4095b0ca933cdce6d26a70 /Eigen/src/SparseCore/SparseView.h | |
parent | 54607665ab1650cc1d63575b231fa15e514d8aa8 (diff) |
Implement evaluator for sparse views.
Diffstat (limited to 'Eigen/src/SparseCore/SparseView.h')
-rw-r--r-- | Eigen/src/SparseCore/SparseView.h | 153 |
1 files changed, 149 insertions, 4 deletions
diff --git a/Eigen/src/SparseCore/SparseView.h b/Eigen/src/SparseCore/SparseView.h index fd8450463..96d0a849c 100644 --- a/Eigen/src/SparseCore/SparseView.h +++ b/Eigen/src/SparseCore/SparseView.h @@ -34,25 +34,36 @@ class SparseView : public SparseMatrixBase<SparseView<MatrixType> > typedef typename internal::remove_all<MatrixTypeNested>::type _MatrixTypeNested; public: EIGEN_SPARSE_PUBLIC_INTERFACE(SparseView) + typedef typename internal::remove_all<MatrixType>::type NestedExpression; SparseView(const MatrixType& mat, const Scalar& m_reference = Scalar(0), - typename NumTraits<Scalar>::Real m_epsilon = NumTraits<Scalar>::dummy_precision()) : + RealScalar m_epsilon = NumTraits<Scalar>::dummy_precision()) : m_matrix(mat), m_reference(m_reference), m_epsilon(m_epsilon) {} +#ifndef EIGEN_TEST_EVALUATORS class InnerIterator; +#endif // EIGEN_TEST_EVALUATORS inline Index rows() const { return m_matrix.rows(); } inline Index cols() const { return m_matrix.cols(); } inline Index innerSize() const { return m_matrix.innerSize(); } inline Index outerSize() const { return m_matrix.outerSize(); } - + + /** \returns the nested expression */ + const typename internal::remove_all<MatrixTypeNested>::type& + nestedExpression() const { return m_matrix; } + + Scalar reference() const { return m_reference; } + RealScalar epsilon() const { return m_epsilon; } + protected: MatrixTypeNested m_matrix; Scalar m_reference; - typename NumTraits<Scalar>::Real m_epsilon; + RealScalar m_epsilon; }; +#ifndef EIGEN_TEST_EVALUATORS template<typename MatrixType> class SparseView<MatrixType>::InnerIterator : public _MatrixTypeNested::InnerIterator { @@ -80,13 +91,147 @@ protected: private: void incrementToNonZero() { - while((bool(*this)) && internal::isMuchSmallerThan(value(), m_view.m_reference, m_view.m_epsilon)) + while((bool(*this)) && internal::isMuchSmallerThan(value(), m_view.reference(), m_view.epsilon())) { IterBase::operator++(); } } }; +#else // EIGEN_TEST_EVALUATORS + +namespace internal { + +// TODO find a way to unify the two following variants +// This is tricky because implementing an inner iterator on top of an IndexBased evaluator is +// not easy because the evaluators do not expose the sizes of the underlying expression. + +template<typename ArgType> +struct unary_evaluator<SparseView<ArgType>, IteratorBased> + : public evaluator_base<SparseView<ArgType> > +{ + typedef typename evaluator<ArgType>::InnerIterator EvalIterator; + public: + typedef SparseView<ArgType> XprType; + + class InnerIterator : public EvalIterator + { + typedef typename XprType::Scalar Scalar; + public: + + EIGEN_STRONG_INLINE InnerIterator(const unary_evaluator& sve, typename XprType::Index outer) + : EvalIterator(sve.m_argImpl,outer), m_view(sve.m_view) + { + incrementToNonZero(); + } + + EIGEN_STRONG_INLINE InnerIterator& operator++() + { + EvalIterator::operator++(); + incrementToNonZero(); + return *this; + } + + using EvalIterator::value; + + protected: + const XprType &m_view; + + private: + void incrementToNonZero() + { + while((bool(*this)) && internal::isMuchSmallerThan(value(), m_view.reference(), m_view.epsilon())) + { + EvalIterator::operator++(); + } + } + }; + + enum { + CoeffReadCost = evaluator<ArgType>::CoeffReadCost, + Flags = XprType::Flags + }; + + unary_evaluator(const XprType& xpr) : m_argImpl(xpr.nestedExpression()), m_view(xpr) {} + + protected: + typename evaluator<ArgType>::nestedType m_argImpl; + const XprType &m_view; +}; + +template<typename ArgType> +struct unary_evaluator<SparseView<ArgType>, IndexBased> + : public evaluator_base<SparseView<ArgType> > +{ + public: + typedef SparseView<ArgType> XprType; + protected: + enum { IsRowMajor = (XprType::Flags&RowMajorBit)==RowMajorBit }; + typedef typename XprType::Index Index; + typedef typename XprType::Scalar Scalar; + public: + + class InnerIterator + { + public: + + EIGEN_STRONG_INLINE InnerIterator(const unary_evaluator& sve, typename XprType::Index outer) + : m_sve(sve), m_inner(0), m_outer(outer), m_end(sve.m_view.innerSize()) + { + incrementToNonZero(); + } + + EIGEN_STRONG_INLINE InnerIterator& operator++() + { + m_inner++; + incrementToNonZero(); + return *this; + } + + EIGEN_STRONG_INLINE Scalar value() const + { + return (IsRowMajor) ? m_sve.m_argImpl.coeff(m_outer, m_inner) + : m_sve.m_argImpl.coeff(m_inner, m_outer); + } + + EIGEN_STRONG_INLINE Index index() const { return m_inner; } + inline Index row() const { return IsRowMajor ? m_outer : index(); } + inline Index col() const { return IsRowMajor ? index() : m_outer; } + + EIGEN_STRONG_INLINE operator bool() const { return m_inner < m_end && m_inner>=0; } + + protected: + const unary_evaluator &m_sve; + Index m_inner; + const Index m_outer; + const Index m_end; + + private: + void incrementToNonZero() + { + while((bool(*this)) && internal::isMuchSmallerThan(value(), m_sve.m_view.reference(), m_sve.m_view.epsilon())) + { + m_inner++; + } + } + }; + + enum { + CoeffReadCost = evaluator<ArgType>::CoeffReadCost, + Flags = XprType::Flags + }; + + unary_evaluator(const XprType& xpr) : m_argImpl(xpr.nestedExpression()), m_view(xpr) {} + + protected: + typename evaluator<ArgType>::nestedType m_argImpl; + const XprType &m_view; +}; + +} // end namespace internal + +#endif // EIGEN_TEST_EVALUATORS + template<typename Derived> const SparseView<Derived> MatrixBase<Derived>::sparseView(const Scalar& m_reference, const typename NumTraits<Scalar>::Real& m_epsilon) const |