// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2011-2014 Gael Guennebaud // Copyright (C) 2010 Daniel Lowengrub // // 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_SPARSEVIEW_H #define EIGEN_SPARSEVIEW_H namespace Eigen { namespace internal { template struct traits > : traits { typedef typename MatrixType::StorageIndex StorageIndex; typedef Sparse StorageKind; enum { Flags = int(traits::Flags) & (RowMajorBit) }; }; } // end namespace internal template class SparseView : public SparseMatrixBase > { typedef typename MatrixType::Nested MatrixTypeNested; typedef typename internal::remove_all::type _MatrixTypeNested; typedef SparseMatrixBase Base; public: EIGEN_SPARSE_PUBLIC_INTERFACE(SparseView) typedef typename internal::remove_all::type NestedExpression; explicit SparseView(const MatrixType& mat, const Scalar& reference = Scalar(0), const RealScalar &epsilon = NumTraits::dummy_precision()) : m_matrix(mat), m_reference(reference), m_epsilon(epsilon) {} 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::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; RealScalar m_epsilon; }; 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 struct unary_evaluator, IteratorBased> : public evaluator_base > { typedef typename evaluator::InnerIterator EvalIterator; public: typedef SparseView XprType; class InnerIterator : public EvalIterator { typedef typename XprType::Scalar Scalar; public: EIGEN_STRONG_INLINE InnerIterator(const unary_evaluator& sve, 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::CoeffReadCost, Flags = XprType::Flags }; explicit unary_evaluator(const XprType& xpr) : m_argImpl(xpr.nestedExpression()), m_view(xpr) {} protected: evaluator m_argImpl; const XprType &m_view; }; template struct unary_evaluator, IndexBased> : public evaluator_base > { public: typedef SparseView XprType; protected: enum { IsRowMajor = (XprType::Flags&RowMajorBit)==RowMajorBit }; typedef typename XprType::Scalar Scalar; typedef typename XprType::StorageIndex StorageIndex; public: class InnerIterator { public: EIGEN_STRONG_INLINE InnerIterator(const unary_evaluator& sve, 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 StorageIndex 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::CoeffReadCost, Flags = XprType::Flags }; explicit unary_evaluator(const XprType& xpr) : m_argImpl(xpr.nestedExpression()), m_view(xpr) {} protected: evaluator m_argImpl; const XprType &m_view; }; } // end namespace internal template const SparseView MatrixBase::sparseView(const Scalar& reference, const typename NumTraits::Real& epsilon) const { return SparseView(derived(), reference, epsilon); } /** \returns an expression of \c *this with values smaller than * \a reference * \a epsilon are removed. * * This method is typically used in conjunction with the product of two sparse matrices * to automatically prune the smallest values as follows: * \code * C = (A*B).pruned(); // suppress numerical zeros (exact) * C = (A*B).pruned(ref); * C = (A*B).pruned(ref,epsilon); * \endcode * where \c ref is a meaningful non zero reference value. * */ template const SparseView SparseMatrixBase::pruned(const Scalar& reference, const RealScalar& epsilon) const { return SparseView(derived(), reference, epsilon); } } // end namespace Eigen #endif