// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2014 Gael Guennebaud <gael.guennebaud@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/.
// SPDX-License-Identifier: MPL-2.0

#ifndef EIGEN_SPARSEMATRIXBASE_H
#define EIGEN_SPARSEMATRIXBASE_H

// IWYU pragma: private
#include "./InternalHeaderCheck.h"

namespace Eigen {

/** \ingroup SparseCore_Module
 *
 * \class SparseMatrixBase
 *
 * \brief Base class of any sparse matrices or sparse expressions
 *
 * \tparam Derived is the derived type, e.g. a sparse matrix type, or an expression, etc.
 *
 * This class can be extended with the help of the plugin mechanism described on the page
 * \ref TopicCustomizing_Plugins by defining the preprocessor symbol \c EIGEN_SPARSEMATRIXBASE_PLUGIN.
 */
template <typename Derived>
class SparseMatrixBase : public EigenBase<Derived> {
 public:
  using Scalar = typename internal::traits<Derived>::Scalar;

  /** The numeric type of the expression's coefficients, e.g. float, double, int or std::complex<float>, etc.
   *
   * It is an alias for the Scalar type */
  using value_type = Scalar;

  using PacketScalar = typename internal::packet_traits<Scalar>::type;
  using StorageKind = typename internal::traits<Derived>::StorageKind;

  /** The integer type used to \b store indices within a SparseMatrix.
   * For a \c SparseMatrix<Scalar,Options,IndexType> it is an alias of the third template parameter \c IndexType. */
  using StorageIndex = typename internal::traits<Derived>::StorageIndex;

  using PacketReturnType = std::conditional_t<internal::is_arithmetic<PacketScalar>::value, PacketScalar,
                                              internal::add_const_on_value_type_t<PacketScalar>>;

  using StorageBaseType = SparseMatrixBase;

  using IndexVector = Matrix<StorageIndex, Dynamic, 1>;
  using ScalarVector = Matrix<Scalar, Dynamic, 1>;

  template <typename OtherDerived>
  Derived& operator=(const EigenBase<OtherDerived>& other);

  enum {

    RowsAtCompileTime = internal::traits<Derived>::RowsAtCompileTime,
    /**< The number of rows at compile-time. This is just a copy of the value provided
     * by the \a Derived type. If a value is not known at compile-time,
     * it is set to the \a Dynamic constant.
     * \sa MatrixBase::rows(), MatrixBase::cols(), ColsAtCompileTime, SizeAtCompileTime */

    ColsAtCompileTime = internal::traits<Derived>::ColsAtCompileTime,
    /**< The number of columns at compile-time. This is just a copy of the value provided
     * by the \a Derived type. If a value is not known at compile-time,
     * it is set to the \a Dynamic constant.
     * \sa MatrixBase::rows(), MatrixBase::cols(), RowsAtCompileTime, SizeAtCompileTime */

    SizeAtCompileTime = (internal::size_of_xpr_at_compile_time<Derived>::value),
    /**< This is equal to the number of coefficients, i.e. the number of
     * rows times the number of columns, or to \a Dynamic if this is not
     * known at compile-time. \sa RowsAtCompileTime, ColsAtCompileTime */

    MaxRowsAtCompileTime = RowsAtCompileTime,
    MaxColsAtCompileTime = ColsAtCompileTime,

    MaxSizeAtCompileTime = internal::size_at_compile_time(MaxRowsAtCompileTime, MaxColsAtCompileTime),

    IsVectorAtCompileTime = RowsAtCompileTime == 1 || ColsAtCompileTime == 1,
    /**< This is set to true if either the number of rows or the number of
     * columns is known at compile-time to be equal to 1. Indeed, in that case,
     * we are dealing with a column-vector (if there is only one column) or with
     * a row-vector (if there is only one row). */

    NumDimensions = int(MaxSizeAtCompileTime) == 1 ? 0
                    : bool(IsVectorAtCompileTime)  ? 1
                                                   : 2,
    /**< This value is equal to Tensor::NumDimensions, i.e. 0 for scalars, 1 for vectors,
     * and 2 for matrices.
     */

    Flags = internal::traits<Derived>::Flags,
    /**< This stores expression \ref flags flags which may or may not be inherited by new expressions
     * constructed from this one. See the \ref flags "list of flags".
     */

    IsRowMajor = Flags & RowMajorBit ? 1 : 0,

    InnerSizeAtCompileTime = int(IsVectorAtCompileTime) ? int(SizeAtCompileTime)
                             : int(IsRowMajor)          ? int(ColsAtCompileTime)
                                                        : int(RowsAtCompileTime),

#ifndef EIGEN_PARSED_BY_DOXYGEN
    HasDirectAccess_ = (int(Flags) & DirectAccessBit) ? 1 : 0  // workaround sunCC
#endif
  };

  /** \internal the return type of MatrixBase::adjoint() */
  using AdjointReturnType =
      std::conditional_t<NumTraits<Scalar>::IsComplex,
                         CwiseUnaryOp<internal::scalar_conjugate_op<Scalar>, Eigen::Transpose<const Derived>>,
                         Transpose<const Derived>>;
  using TransposeReturnType = Transpose<Derived>;
  using ConstTransposeReturnType = Transpose<const Derived>;

  // FIXME: storage order may not match evaluator storage order.
  using PlainObject = SparseMatrix<Scalar, Flags & RowMajorBit ? RowMajor : ColMajor, StorageIndex>;

  /** This is the "real scalar" type; if the \a Scalar type is already real numbers
   * (e.g. int, float or double) then \a RealScalar is just the same as \a Scalar. If
   * \a Scalar is \a std::complex<T> then RealScalar is \a T.
   *
   * \sa class NumTraits
   */
  using RealScalar = typename NumTraits<Scalar>::Real;

#ifndef EIGEN_PARSED_BY_DOXYGEN
  /** \internal the return type of coeff()
   */
  using CoeffReturnType = std::conditional_t<HasDirectAccess_, const Scalar&, Scalar>;

  /** \internal Represents a matrix with all coefficients equal to one another*/
  using ConstantReturnType = CwiseNullaryOp<internal::scalar_constant_op<Scalar>, Matrix<Scalar, Dynamic, Dynamic>>;

  /** type of the equivalent dense matrix */
  using DenseMatrixType = Matrix<Scalar, RowsAtCompileTime, ColsAtCompileTime>;
  /** type of the equivalent square matrix */
  using SquareMatrixType = Matrix<Scalar, internal::max_size_prefer_dynamic(RowsAtCompileTime, ColsAtCompileTime),
                                  internal::max_size_prefer_dynamic(RowsAtCompileTime, ColsAtCompileTime)>;

  inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
  inline Derived& derived() { return *static_cast<Derived*>(this); }
  inline Derived& const_cast_derived() const { return *static_cast<Derived*>(const_cast<SparseMatrixBase*>(this)); }

  using Base = EigenBase<Derived>;

#endif  // not EIGEN_PARSED_BY_DOXYGEN

#define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::SparseMatrixBase
#ifdef EIGEN_PARSED_BY_DOXYGEN
#define EIGEN_DOC_UNARY_ADDONS(METHOD,                                                                               \
                               OP) /** <p>This method does not change the sparsity of \c *this: the OP is applied to \
                                      explicitly stored coefficients only. \sa SparseCompressedBase::coeffs() </p> */
#define EIGEN_DOC_BLOCK_ADDONS_NOT_INNER_PANEL /** <p> \warning This method returns a read-only expression for any   \
                                                  sparse matrices. \sa \ref TutorialSparse_SubMatrices "Sparse block \
                                                  operations" </p> */
#define EIGEN_DOC_BLOCK_ADDONS_INNER_PANEL_IF(                                                                       \
    COND) /** <p> \warning This method returns a read-write expression for COND sparse matrices only. Otherwise, the \
             returned expression is read-only. \sa \ref TutorialSparse_SubMatrices "Sparse block operations" </p> */
#else
#define EIGEN_DOC_UNARY_ADDONS(X, Y)
#define EIGEN_DOC_BLOCK_ADDONS_NOT_INNER_PANEL
#define EIGEN_DOC_BLOCK_ADDONS_INNER_PANEL_IF(COND)
#endif
#include "../plugins/CommonCwiseUnaryOps.inc"
#include "../plugins/CommonCwiseBinaryOps.inc"
#include "../plugins/MatrixCwiseUnaryOps.inc"
#include "../plugins/MatrixCwiseBinaryOps.inc"
#include "../plugins/BlockMethods.inc"
#ifdef EIGEN_SPARSEMATRIXBASE_PLUGIN
#include EIGEN_SPARSEMATRIXBASE_PLUGIN
#endif
#undef EIGEN_CURRENT_STORAGE_BASE_CLASS
#undef EIGEN_DOC_UNARY_ADDONS
#undef EIGEN_DOC_BLOCK_ADDONS_NOT_INNER_PANEL
#undef EIGEN_DOC_BLOCK_ADDONS_INNER_PANEL_IF

  /** \returns the number of rows. \sa cols() */
  inline Index rows() const { return derived().rows(); }
  /** \returns the number of columns. \sa rows() */
  inline Index cols() const { return derived().cols(); }
  /** \returns the number of coefficients, which is \a rows()*cols().
   * \sa rows(), cols(). */
  inline Index size() const { return rows() * cols(); }
  /** \returns true if either the number of rows or the number of columns is equal to 1.
   * In other words, this function returns
   * \code rows()==1 || cols()==1 \endcode
   * \sa rows(), cols(), IsVectorAtCompileTime. */
  inline bool isVector() const { return rows() == 1 || cols() == 1; }
  /** \returns the size of the storage major dimension,
   * i.e., the number of columns for a column major matrix, and the number of rows otherwise */
  Index outerSize() const { return (int(Flags) & RowMajorBit) ? this->rows() : this->cols(); }
  /** \returns the size of the inner dimension according to the storage order,
   * i.e., the number of rows for a column major matrix, and the number of cols otherwise */
  Index innerSize() const { return (int(Flags) & RowMajorBit) ? this->cols() : this->rows(); }

  bool isRValue() const { return m_isRValue; }
  Derived& markAsRValue() {
    m_isRValue = true;
    return derived();
  }

  SparseMatrixBase() : m_isRValue(false) { /* TODO: validate traits flags. */
  }

  template <typename OtherDerived>
  Derived& operator=(const ReturnByValue<OtherDerived>& other);

  template <typename OtherDerived>
  inline Derived& operator=(const SparseMatrixBase<OtherDerived>& other);

  inline Derived& operator=(const Derived& other);

 protected:
  template <typename OtherDerived>
  inline Derived& assign(const OtherDerived& other);

  template <typename OtherDerived>
  inline void assignGeneric(const OtherDerived& other);

 public:
#ifndef EIGEN_NO_IO
  friend std::ostream& operator<<(std::ostream& s, const SparseMatrixBase& m) {
    using Nested = typename Derived::Nested;
    using NestedCleaned = internal::remove_all_t<Nested>;

    EIGEN_IF_CONSTEXPR (Flags & RowMajorBit) {
      Nested nm(m.derived());
      internal::evaluator<NestedCleaned> thisEval(nm);

      // compute global width
      std::size_t width = 0;
      {
        std::ostringstream ss0;
        ss0.copyfmt(s);
        ss0 << Scalar(0);
        width = ss0.str().size();
        for (Index row = 0; row < nm.outerSize(); ++row) {
          for (typename internal::evaluator<NestedCleaned>::InnerIterator it(thisEval, row); it; ++it) {
            std::ostringstream ss;
            ss.copyfmt(s);
            ss << it.value();

            const std::size_t potential_width = ss.str().size();
            if (potential_width > width) width = potential_width;
          }
        }
      }

      for (Index row = 0; row < nm.outerSize(); ++row) {
        Index col = 0;
        for (typename internal::evaluator<NestedCleaned>::InnerIterator it(thisEval, row); it; ++it) {
          for (; col < it.index(); ++col) {
            s.width(width);
            s << Scalar(0) << " ";
          }
          s.width(width);
          s << it.value() << " ";
          ++col;
        }
        for (; col < m.cols(); ++col) {
          s.width(width);
          s << Scalar(0) << " ";
        }
        s << std::endl;
      }
    } else {
      Nested nm(m.derived());
      internal::evaluator<NestedCleaned> thisEval(nm);
      if (m.cols() == 1) {
        // compute local width (single col)
        std::size_t width = 0;
        {
          std::ostringstream ss0;
          ss0.copyfmt(s);
          ss0 << Scalar(0);
          width = ss0.str().size();
          for (typename internal::evaluator<NestedCleaned>::InnerIterator it(thisEval, 0); it; ++it) {
            std::ostringstream ss;
            ss.copyfmt(s);
            ss << it.value();

            const std::size_t potential_width = ss.str().size();
            if (potential_width > width) width = potential_width;
          }
        }

        Index row = 0;
        for (typename internal::evaluator<NestedCleaned>::InnerIterator it(thisEval, 0); it; ++it) {
          for (; row < it.index(); ++row) {
            s.width(width);
            s << Scalar(0) << std::endl;
          }
          s.width(width);
          s << it.value() << std::endl;
          ++row;
        }
        for (; row < m.rows(); ++row) {
          s.width(width);
          s << Scalar(0) << std::endl;
        }
      } else {
        SparseMatrix<Scalar, RowMajorBit, StorageIndex> trans = m;
        s << static_cast<const SparseMatrixBase<SparseMatrix<Scalar, RowMajorBit, StorageIndex>>&>(trans);
      }
    }
    return s;
  }
#endif

  template <typename OtherDerived>
  Derived& operator+=(const SparseMatrixBase<OtherDerived>& other);
  template <typename OtherDerived>
  Derived& operator-=(const SparseMatrixBase<OtherDerived>& other);

  template <typename OtherDerived>
  Derived& operator+=(const DiagonalBase<OtherDerived>& other);
  template <typename OtherDerived>
  Derived& operator-=(const DiagonalBase<OtherDerived>& other);

  template <typename OtherDerived>
  Derived& operator+=(const EigenBase<OtherDerived>& other);
  template <typename OtherDerived>
  Derived& operator-=(const EigenBase<OtherDerived>& other);

  Derived& operator*=(const Scalar& other);
  Derived& operator/=(const Scalar& other);

  template <typename OtherDerived>
  struct CwiseProductDenseReturnType {
    using Type = CwiseBinaryOp<internal::scalar_product_op<typename internal::traits<Derived>::Scalar,
                                                           typename internal::traits<OtherDerived>::Scalar>,
                               const Derived, const OtherDerived>;
  };

  template <typename OtherDerived>
  EIGEN_STRONG_INLINE const typename CwiseProductDenseReturnType<OtherDerived>::Type cwiseProduct(
      const MatrixBase<OtherDerived>& other) const;

  // sparse * diagonal
  template <typename OtherDerived>
  const Product<Derived, OtherDerived> operator*(const DiagonalBase<OtherDerived>& other) const {
    return Product<Derived, OtherDerived>(derived(), other.derived());
  }

  // diagonal * sparse
  template <typename OtherDerived>
  friend const Product<OtherDerived, Derived> operator*(const DiagonalBase<OtherDerived>& lhs,
                                                        const SparseMatrixBase& rhs) {
    return Product<OtherDerived, Derived>(lhs.derived(), rhs.derived());
  }

  // sparse * sparse
  template <typename OtherDerived>
  const Product<Derived, OtherDerived, AliasFreeProduct> operator*(const SparseMatrixBase<OtherDerived>& other) const;

  // sparse * dense
  template <typename OtherDerived>
  const Product<Derived, OtherDerived> operator*(const MatrixBase<OtherDerived>& other) const {
    return Product<Derived, OtherDerived>(derived(), other.derived());
  }

  // dense * sparse
  template <typename OtherDerived>
  friend const Product<OtherDerived, Derived> operator*(const MatrixBase<OtherDerived>& lhs,
                                                        const SparseMatrixBase& rhs) {
    return Product<OtherDerived, Derived>(lhs.derived(), rhs.derived());
  }

  /** \returns an expression of P H P^-1 where H is the matrix represented by \c *this */
  SparseSymmetricPermutationProduct<Derived, Upper | Lower> twistedBy(
      const PermutationMatrix<Dynamic, Dynamic, StorageIndex>& perm) const {
    return SparseSymmetricPermutationProduct<Derived, Upper | Lower>(derived(), perm);
  }

  template <typename OtherDerived>
  Derived& operator*=(const SparseMatrixBase<OtherDerived>& other);

  template <int Mode>
  inline const TriangularView<const Derived, Mode> triangularView() const;

  template <unsigned int UpLo>
  struct SelfAdjointViewReturnType {
    using Type = SparseSelfAdjointView<Derived, UpLo>;
  };
  template <unsigned int UpLo>
  struct ConstSelfAdjointViewReturnType {
    using Type = const SparseSelfAdjointView<const Derived, UpLo>;
  };

  template <unsigned int UpLo>
  inline typename ConstSelfAdjointViewReturnType<UpLo>::Type selfadjointView() const;
  template <unsigned int UpLo>
  inline typename SelfAdjointViewReturnType<UpLo>::Type selfadjointView();

  template <typename OtherDerived>
  Scalar dot(const MatrixBase<OtherDerived>& other) const;
  template <typename OtherDerived>
  Scalar dot(const SparseMatrixBase<OtherDerived>& other) const;
  RealScalar squaredNorm() const;
  RealScalar norm() const;
  RealScalar blueNorm() const;

  TransposeReturnType transpose() { return TransposeReturnType(derived()); }
  const ConstTransposeReturnType transpose() const { return ConstTransposeReturnType(derived()); }
  const AdjointReturnType adjoint() const { return AdjointReturnType(transpose()); }

  DenseMatrixType toDense() const { return DenseMatrixType(derived()); }

  template <typename OtherDerived>
  bool isApprox(const SparseMatrixBase<OtherDerived>& other,
                const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const;

  template <typename OtherDerived>
  bool isApprox(const MatrixBase<OtherDerived>& other,
                const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const {
    return toDense().isApprox(other, prec);
  }

  /** \returns the matrix or vector obtained by evaluating this expression.
   *
   * Notice that in the case of a plain matrix or vector (not an expression) this function just returns
   * a const reference, in order to avoid a useless copy.
   */
  inline const typename internal::eval<Derived>::type eval() const {
    return typename internal::eval<Derived>::type(derived());
  }

  Scalar sum() const;

  inline const SparseView<Derived> pruned(const Scalar& reference = Scalar(0),
                                          const RealScalar& epsilon = NumTraits<Scalar>::dummy_precision()) const;

 protected:
  bool m_isRValue;

  static inline StorageIndex convert_index(const Index idx) { return internal::convert_index<StorageIndex>(idx); }

 private:
  template <typename Dest>
  void evalTo(Dest&) const;
};

}  // end namespace Eigen

#endif  // EIGEN_SPARSEMATRIXBASE_H
