// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009-2015 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
//
// 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

// IWYU pragma: private
#include "./InternalHeaderCheck.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 <typename MatrixType, unsigned int Mode>
class TriangularViewImpl<MatrixType, Mode, Sparse> : public SparseMatrixBase<TriangularView<MatrixType, Mode> > {
  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<MatrixType, Mode> TriangularViewType;

 protected:
  // dummy solve function to make TriangularView happy.
  void solve() const;

  typedef SparseMatrixBase<TriangularViewType> Base;

 public:
  EIGEN_SPARSE_PUBLIC_INTERFACE(TriangularViewType)

  typedef typename MatrixType::Nested MatrixTypeNested;
  typedef std::remove_reference_t<MatrixTypeNested> MatrixTypeNestedNonRef;
  typedef internal::remove_all_t<MatrixTypeNested> MatrixTypeNestedCleaned;

  template <typename RhsType, typename DstType>
  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _solve_impl(const RhsType& rhs, DstType& dst) const {
    if (!(internal::is_same<RhsType, DstType>::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 <typename OtherDerived>
  void solveInPlace(MatrixBase<OtherDerived>& other) const;

  /** Applies the inverse of \c *this to the sparse vector or matrix \a other, "in-place" */
  template <typename OtherDerived>
  void solveInPlace(SparseMatrixBase<OtherDerived>& other) const;
};

namespace internal {

template <typename ArgType, unsigned int Mode>
struct unary_evaluator<TriangularView<ArgType, Mode>, IteratorBased> : evaluator_base<TriangularView<ArgType, Mode> > {
  typedef TriangularView<ArgType, Mode> XprType;

 protected:
  typedef typename XprType::Scalar Scalar;
  typedef typename XprType::StorageIndex StorageIndex;
  typedef typename evaluator<ArgType>::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<ArgType>::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() < xprEval.m_arg.innerSize()) {
      if (SkipFirst) {
        while ((*this) && ((HasUnitDiag || SkipDiag) ? this->index() <= outer : this->index() < outer))
          Base::operator++();
        if (HasUnitDiag) m_returnOne = m_containsDiag;
      } else if (HasUnitDiag && ((!Base::operator bool()) || Base::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<StorageIndex>(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<ArgType> m_argImpl;
  const ArgType& m_arg;
};

}  // end namespace internal

template <typename Derived>
template <int Mode>
inline const TriangularView<const Derived, Mode> SparseMatrixBase<Derived>::triangularView() const {
  return TriangularView<const Derived, Mode>(derived());
}

}  // end namespace Eigen

#endif  // EIGEN_SPARSE_TRIANGULARVIEW_H
