// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2009-2015 Gael Guennebaud // Copyright (C) 2012 Désiré Nuentsa-Wakam // // 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_SPARSE_TRIANGULARVIEW_H #define EIGEN_SPARSE_TRIANGULARVIEW_H namespace Eigen { /** \ingroup SparseCore_Module * * \brief Base class for a triangular part in a \b sparse matrix * * This class is an abstract base class of class TriangularView, and objects of type TriangularViewImpl cannot be instantiated. * It extends class TriangularView with additional methods which are available for sparse expressions only. * * \sa class TriangularView, SparseMatrixBase::triangularView() */ template class TriangularViewImpl : public SparseMatrixBase > { enum { SkipFirst = ((Mode&Lower) && !(MatrixType::Flags&RowMajorBit)) || ((Mode&Upper) && (MatrixType::Flags&RowMajorBit)), SkipLast = !SkipFirst, SkipDiag = (Mode&ZeroDiag) ? 1 : 0, HasUnitDiag = (Mode&UnitDiag) ? 1 : 0 }; typedef TriangularView TriangularViewType; protected: // dummy solve function to make TriangularView happy. void solve() const; typedef SparseMatrixBase Base; public: EIGEN_SPARSE_PUBLIC_INTERFACE(TriangularViewType) typedef typename MatrixType::Nested MatrixTypeNested; typedef typename internal::remove_reference::type MatrixTypeNestedNonRef; typedef typename internal::remove_all::type MatrixTypeNestedCleaned; template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _solve_impl(const RhsType &rhs, DstType &dst) const { if(!(internal::is_same::value && internal::extract_data(dst) == internal::extract_data(rhs))) dst = rhs; this->solveInPlace(dst); } /** Applies the inverse of \c *this to the dense vector or matrix \a other, "in-place" */ template void solveInPlace(MatrixBase& other) const; /** Applies the inverse of \c *this to the sparse vector or matrix \a other, "in-place" */ template void solveInPlace(SparseMatrixBase& other) const; }; namespace internal { template struct unary_evaluator, IteratorBased> : evaluator_base > { typedef TriangularView XprType; protected: typedef typename XprType::Scalar Scalar; typedef typename XprType::StorageIndex StorageIndex; typedef typename evaluator::InnerIterator EvalIterator; enum { SkipFirst = ((Mode&Lower) && !(ArgType::Flags&RowMajorBit)) || ((Mode&Upper) && (ArgType::Flags&RowMajorBit)), SkipLast = !SkipFirst, SkipDiag = (Mode&ZeroDiag) ? 1 : 0, HasUnitDiag = (Mode&UnitDiag) ? 1 : 0 }; public: enum { CoeffReadCost = evaluator::CoeffReadCost, Flags = XprType::Flags }; explicit unary_evaluator(const XprType &xpr) : m_argImpl(xpr.nestedExpression()), m_arg(xpr.nestedExpression()) {} inline Index nonZerosEstimate() const { return m_argImpl.nonZerosEstimate(); } class InnerIterator : public EvalIterator { typedef EvalIterator Base; public: EIGEN_STRONG_INLINE InnerIterator(const unary_evaluator& xprEval, Index outer) : Base(xprEval.m_argImpl,outer), m_returnOne(false), m_containsDiag(Base::outer()index()<=outer : this->index()=Base::outer())) { if((!SkipFirst) && Base::operator bool()) Base::operator++(); m_returnOne = m_containsDiag; } } EIGEN_STRONG_INLINE InnerIterator& operator++() { if(HasUnitDiag && m_returnOne) m_returnOne = false; else { Base::operator++(); if(HasUnitDiag && (!SkipFirst) && ((!Base::operator bool()) || Base::index()>=Base::outer())) { if((!SkipFirst) && Base::operator bool()) Base::operator++(); m_returnOne = m_containsDiag; } } return *this; } EIGEN_STRONG_INLINE operator bool() const { if(HasUnitDiag && m_returnOne) return true; if(SkipFirst) return Base::operator bool(); else { if (SkipDiag) return (Base::operator bool() && this->index() < this->outer()); else return (Base::operator bool() && this->index() <= this->outer()); } } // inline Index row() const { return (ArgType::Flags&RowMajorBit ? Base::outer() : this->index()); } // inline Index col() const { return (ArgType::Flags&RowMajorBit ? this->index() : Base::outer()); } inline StorageIndex index() const { if(HasUnitDiag && m_returnOne) return internal::convert_index(Base::outer()); else return Base::index(); } inline Scalar value() const { if(HasUnitDiag && m_returnOne) return Scalar(1); else return Base::value(); } protected: bool m_returnOne; bool m_containsDiag; private: Scalar& valueRef(); }; protected: evaluator m_argImpl; const ArgType& m_arg; }; } // end namespace internal template template inline const TriangularView SparseMatrixBase::triangularView() const { return TriangularView(derived()); } } // end namespace Eigen #endif // EIGEN_SPARSE_TRIANGULARVIEW_H