// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2015 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_SPARSEVECTOR_H
#define EIGEN_SPARSEVECTOR_H

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

namespace Eigen {

/** \ingroup SparseCore_Module
 * \class SparseVector
 *
 * \brief a sparse vector class
 *
 * \tparam Scalar_ the scalar type, i.e. the type of the coefficients
 *
 * See http://www.netlib.org/linalg/html_templates/node91.html for details on the storage scheme.
 *
 * 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_SPARSEVECTOR_PLUGIN.
 */

namespace internal {
template <typename Scalar_, int Options_, typename StorageIndex_>
struct traits<SparseVector<Scalar_, Options_, StorageIndex_> > {
  using Scalar = Scalar_;
  using StorageIndex = StorageIndex_;
  using StorageKind = Sparse;
  using XprKind = MatrixXpr;
  enum {
    IsColVector = (Options_ & RowMajorBit) ? 0 : 1,

    RowsAtCompileTime = IsColVector ? Dynamic : 1,
    ColsAtCompileTime = IsColVector ? 1 : Dynamic,
    MaxRowsAtCompileTime = RowsAtCompileTime,
    MaxColsAtCompileTime = ColsAtCompileTime,
    Flags = Options_ | NestByRefBit | LvalueBit | (IsColVector ? 0 : RowMajorBit) | CompressedAccessBit,
    SupportedAccessPatterns = InnerRandomAccessPattern
  };
};

// Sparse-Vector-Assignment kinds:
enum { SVA_RuntimeSwitch, SVA_Inner, SVA_Outer };

template <typename Dest, typename Src,
          int AssignmentKind = !bool(Src::IsVectorAtCompileTime)  ? SVA_RuntimeSwitch
                               : Src::InnerSizeAtCompileTime == 1 ? SVA_Outer
                                                                  : SVA_Inner>
struct sparse_vector_assign_selector;

}  // namespace internal

template <typename Scalar_, int Options_, typename StorageIndex_>
class SparseVector : public SparseCompressedBase<SparseVector<Scalar_, Options_, StorageIndex_> > {
  using Base = SparseCompressedBase<SparseVector>;
  using Base::convert_index;

 public:
  EIGEN_SPARSE_PUBLIC_INTERFACE(SparseVector)
  EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseVector, +=)
  EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseVector, -=)

  using Storage = internal::CompressedStorage<Scalar, StorageIndex>;
  enum { IsColVector = internal::traits<SparseVector>::IsColVector };

  enum { Options = Options_ };

  EIGEN_STRONG_INLINE Index rows() const { return IsColVector ? m_size : 1; }
  EIGEN_STRONG_INLINE Index cols() const { return IsColVector ? 1 : m_size; }
  EIGEN_STRONG_INLINE Index innerSize() const { return m_size; }
  EIGEN_STRONG_INLINE Index outerSize() const { return 1; }

  EIGEN_STRONG_INLINE const Scalar* valuePtr() const { return m_data.valuePtr(); }
  EIGEN_STRONG_INLINE Scalar* valuePtr() { return m_data.valuePtr(); }

  EIGEN_STRONG_INLINE const StorageIndex* innerIndexPtr() const { return m_data.indexPtr(); }
  EIGEN_STRONG_INLINE StorageIndex* innerIndexPtr() { return m_data.indexPtr(); }

  inline const StorageIndex* outerIndexPtr() const { return 0; }
  inline StorageIndex* outerIndexPtr() { return 0; }
  inline const StorageIndex* innerNonZeroPtr() const { return 0; }
  inline StorageIndex* innerNonZeroPtr() { return 0; }

  /** \internal */
  constexpr Storage& data() { return m_data; }
  /** \internal */
  constexpr const Storage& data() const { return m_data; }

  inline Scalar coeff(Index row, Index col) const {
    eigen_assert(IsColVector ? (col == 0 && row >= 0 && row < m_size) : (row == 0 && col >= 0 && col < m_size));
    return coeff(IsColVector ? row : col);
  }
  inline Scalar coeff(Index i) const {
    eigen_assert(i >= 0 && i < m_size);
    return m_data.at(StorageIndex(i));
  }

  inline Scalar& coeffRef(Index row, Index col) {
    eigen_assert(IsColVector ? (col == 0 && row >= 0 && row < m_size) : (row == 0 && col >= 0 && col < m_size));
    return coeffRef(IsColVector ? row : col);
  }

  /** \returns a reference to the coefficient value at given index \a i
   * This operation involves a log(rho*size) binary search. If the coefficient does not
   * exist yet, then a sorted insertion into a sequential buffer is performed.
   *
   * This insertion might be very costly if the number of nonzeros above \a i is large.
   */
  inline Scalar& coeffRef(Index i) {
    eigen_assert(i >= 0 && i < m_size);

    return m_data.atWithInsertion(StorageIndex(i));
  }

 public:
  using InnerIterator = typename Base::InnerIterator;
  using ReverseInnerIterator = typename Base::ReverseInnerIterator;

  inline void setZero() { m_data.clear(); }

  /** \returns the number of non zero coefficients */
  inline Index nonZeros() const { return m_data.size(); }

  inline void startVec(Index outer) {
    EIGEN_UNUSED_VARIABLE(outer);
    eigen_assert(outer == 0);
  }

  inline Scalar& insertBackByOuterInner(Index outer, Index inner) {
    EIGEN_UNUSED_VARIABLE(outer);
    eigen_assert(outer == 0);
    return insertBack(inner);
  }
  inline Scalar& insertBack(Index i) {
    m_data.append(Scalar(0), i);
    return m_data.value(m_data.size() - 1);
  }

  Scalar& insertBackByOuterInnerUnordered(Index outer, Index inner) {
    EIGEN_UNUSED_VARIABLE(outer);
    eigen_assert(outer == 0);
    return insertBackUnordered(inner);
  }
  inline Scalar& insertBackUnordered(Index i) {
    m_data.append(Scalar(0), i);
    return m_data.value(m_data.size() - 1);
  }

  inline Scalar& insert(Index row, Index col) {
    eigen_assert(IsColVector ? (col == 0 && row >= 0 && row < m_size) : (row == 0 && col >= 0 && col < m_size));

    Index inner = IsColVector ? row : col;
    Index outer = IsColVector ? col : row;
    EIGEN_ONLY_USED_FOR_DEBUG(outer);
    eigen_assert(outer == 0);
    return insert(inner);
  }
  Scalar& insert(Index i) {
    eigen_assert(i >= 0 && i < m_size);

    Index startId = 0;
    Index p = Index(m_data.size()) - 1;
    // TODO: implement smart reallocation.
    m_data.resize(p + 2, 1);

    while ((p >= startId) && (m_data.index(p) > i)) {
      m_data.index(p + 1) = m_data.index(p);
      m_data.value(p + 1) = m_data.value(p);
      --p;
    }
    m_data.index(p + 1) = convert_index(i);
    m_data.value(p + 1) = Scalar(0);
    return m_data.value(p + 1);
  }

  inline void reserve(Index reserveSize) { m_data.reserve(reserveSize); }

  inline void finalize() {}

  /** \copydoc SparseMatrix::prune(const Scalar&,const RealScalar&) */
  Index prune(const Scalar& reference, const RealScalar& epsilon = NumTraits<RealScalar>::dummy_precision()) {
    return prune([&](const Scalar& val) { return !internal::isMuchSmallerThan(val, reference, epsilon); });
  }

  /**
   * \brief Prunes the entries of the vector based on a `predicate`
   * \tparam F Type of the predicate.
   * \param keep_predicate The predicate that is used to test whether a value should be kept. A callable that
   * gets passed in a `Scalar` value and returns a boolean. If the predicate returns true, the value is kept.
   * \return The new number of structural non-zeros.
   */
  template <class F>
  Index prune(F&& keep_predicate) {
    Index k = 0;
    Index n = m_data.size();
    for (Index i = 0; i < n; ++i) {
      if (keep_predicate(m_data.value(i))) {
        m_data.value(k) = std::move(m_data.value(i));
        m_data.index(k) = m_data.index(i);
        ++k;
      }
    }
    m_data.resize(k);
    return k;
  }

  /** Resizes the sparse vector to \a rows x \a cols
   *
   * This method is provided for compatibility with matrices.
   * For a column vector, \a cols must be equal to 1.
   * For a row vector, \a rows must be equal to 1.
   *
   * \sa resize(Index)
   */
  void resize(Index rows, Index cols) {
    eigen_assert((IsColVector ? cols : rows) == 1 && "Outer dimension must equal 1");
    resize(IsColVector ? rows : cols);
  }

  /** \sa resize(Index,Index) */
  void resize(NoChange_t, Index cols) { resize(rows(), cols); }

  /** \sa resize(Index,Index) */
  void resize(Index rows, NoChange_t) { resize(rows, cols()); }

  /** Resizes the sparse vector to \a newSize
   * This method deletes all entries, thus leaving an empty sparse vector
   *
   * \sa  conservativeResize(), setZero() */
  void resize(Index newSize) {
    m_size = newSize;
    m_data.clear();
  }

  /** Resizes the sparse vector to \a newSize, while leaving old values untouched.
   *
   * If the size of the vector is decreased, then the storage of the out-of bounds coefficients is kept and reserved.
   * Call .data().squeeze() to free extra memory.
   *
   * \sa reserve(), setZero()
   */
  void conservativeResize(Index newSize) {
    if (newSize < m_size) {
      Index i = 0;
      while (i < m_data.size() && m_data.index(i) < newSize) ++i;
      m_data.resize(i);
    }
    m_size = newSize;
  }

  void resizeNonZeros(Index size) { m_data.resize(size); }

  inline SparseVector() : m_size(0) { resize(0); }

  explicit inline SparseVector(Index size) : m_size(0) { resize(size); }

  inline SparseVector(Index rows, Index cols) : m_size(0) { resize(rows, cols); }

  template <typename OtherDerived>
  inline SparseVector(const SparseMatrixBase<OtherDerived>& other) : m_size(0) {
#ifdef EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN
    EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN
#endif
    *this = other.derived();
  }

  inline SparseVector(const SparseVector& other) : Base(other), m_size(0) { *this = other.derived(); }

  /** Swaps the values of \c *this and \a other.
   * Overloaded for performance: this version performs a \em shallow swap by swapping pointers and attributes only.
   * \sa SparseMatrixBase::swap()
   */
  inline void swap(SparseVector& other) {
    std::swap(m_size, other.m_size);
    m_data.swap(other.m_data);
  }
  friend EIGEN_DEVICE_FUNC void swap(SparseVector& a, SparseVector& b) { a.swap(b); }

  template <int OtherOptions>
  inline void swap(SparseMatrix<Scalar, OtherOptions, StorageIndex>& other) {
    eigen_assert(other.outerSize() == 1);
    other.makeCompressed();
    std::swap(m_size, other.m_innerSize);
    m_data.swap(other.m_data);
    other.m_outerIndex[1] = convert_index(other.m_data.size());
  }
  template <int OtherOptions>
  friend EIGEN_DEVICE_FUNC void swap(SparseVector& a, SparseMatrix<Scalar, OtherOptions, StorageIndex>& b) {
    a.swap(b);
  }
  template <int OtherOptions>
  friend EIGEN_DEVICE_FUNC void swap(SparseMatrix<Scalar, OtherOptions, StorageIndex>& a, SparseVector& b) {
    b.swap(a);
  }

  inline SparseVector& operator=(const SparseVector& other) {
    if (other.isRValue()) {
      swap(other.const_cast_derived());
    } else {
      resize(other.size());
      m_data = other.m_data;
    }
    return *this;
  }

  template <typename OtherDerived>
  inline SparseVector& operator=(const SparseMatrixBase<OtherDerived>& other) {
    SparseVector tmp(other.size());
    internal::sparse_vector_assign_selector<SparseVector, OtherDerived>::run(tmp, other.derived());
    this->swap(tmp);
    return *this;
  }

  inline SparseVector(SparseVector&& other) : SparseVector() { this->swap(other); }

  template <typename OtherDerived>
  inline SparseVector(SparseCompressedBase<OtherDerived>&& other) : SparseVector() {
    *this = other.derived().markAsRValue();
  }

  inline SparseVector& operator=(SparseVector&& other) {
    this->swap(other);
    return *this;
  }

  template <typename OtherDerived>
  inline SparseVector& operator=(SparseCompressedBase<OtherDerived>&& other) {
    *this = other.derived().markAsRValue();
    return *this;
  }

#ifndef EIGEN_NO_IO
  friend std::ostream& operator<<(std::ostream& s, const SparseVector& m) {
    for (Index i = 0; i < m.nonZeros(); ++i) s << "(" << m.m_data.value(i) << "," << m.m_data.index(i) << ") ";
    s << std::endl;
    return s;
  }
#endif

  /** Overloaded for performance */
  Scalar sum() const;

 public:
  /** \internal \deprecated use setZero() and reserve() */
  EIGEN_DEPRECATED_WITH_REASON("Use .setZero() and .reserve() instead.") void startFill(Index reserve) {
    setZero();
    m_data.reserve(reserve);
  }

  /** \internal \deprecated use insertBack(Index,Index) */
  EIGEN_DEPRECATED_WITH_REASON("Use .insertBack() instead.") Scalar& fill(Index r, Index c) {
    eigen_assert(r == 0 || c == 0);
    return fill(IsColVector ? r : c);
  }

  /** \internal \deprecated use insertBack(Index) */
  EIGEN_DEPRECATED_WITH_REASON("Use .insertBack() instead.") Scalar& fill(Index i) {
    m_data.append(Scalar(0), i);
    return m_data.value(m_data.size() - 1);
  }

  /** \internal \deprecated use insert(Index,Index) */
  EIGEN_DEPRECATED_WITH_REASON("Use .insert() instead.") Scalar& fillrand(Index r, Index c) {
    eigen_assert(r == 0 || c == 0);
    return fillrand(IsColVector ? r : c);
  }

  /** \internal \deprecated use insert(Index) */
  EIGEN_DEPRECATED_WITH_REASON("Use .insert() instead.") Scalar& fillrand(Index i) { return insert(i); }

  /** \internal \deprecated use finalize() */
  EIGEN_DEPRECATED_WITH_REASON("Use .finalize() instead.") void endFill() {}

  // These two functions were here in the 3.1 release, so let's keep them in case some code relies on them.
  /** \internal \deprecated use data() */
  EIGEN_DEPRECATED_WITH_REASON("Use .data() instead.") Storage& _data() { return m_data; }
  /** \internal \deprecated use data() */
  EIGEN_DEPRECATED_WITH_REASON("Use .data() instead.") const Storage& _data() const { return m_data; }

#ifdef EIGEN_SPARSEVECTOR_PLUGIN
#include EIGEN_SPARSEVECTOR_PLUGIN
#endif

 protected:
  EIGEN_STATIC_ASSERT(NumTraits<StorageIndex>::IsSigned, THE_INDEX_TYPE_MUST_BE_A_SIGNED_TYPE)
  EIGEN_STATIC_ASSERT((Options_ & (ColMajor | RowMajor)) == Options, INVALID_MATRIX_TEMPLATE_PARAMETERS)

  Storage m_data;
  Index m_size;
};

namespace internal {

template <typename Scalar_, int Options_, typename Index_>
struct evaluator<SparseVector<Scalar_, Options_, Index_> > : evaluator_base<SparseVector<Scalar_, Options_, Index_> > {
  using SparseVectorType = SparseVector<Scalar_, Options_, Index_>;
  using Base = evaluator_base<SparseVectorType>;
  using InnerIterator = typename SparseVectorType::InnerIterator;
  using ReverseInnerIterator = typename SparseVectorType::ReverseInnerIterator;

  enum { CoeffReadCost = NumTraits<Scalar_>::ReadCost, Flags = SparseVectorType::Flags };

  evaluator() : Base() {}

  explicit evaluator(const SparseVectorType& mat) : m_matrix(&mat) { EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); }

  inline Index nonZerosEstimate() const { return m_matrix->nonZeros(); }

  operator SparseVectorType&() { return m_matrix->const_cast_derived(); }
  operator const SparseVectorType&() const { return *m_matrix; }

  const SparseVectorType* m_matrix;
};

template <typename Dest, typename Src>
struct sparse_vector_assign_selector<Dest, Src, SVA_Inner> {
  static void run(Dest& dst, const Src& src) {
    eigen_internal_assert(src.innerSize() == src.size());
    using SrcEvaluatorType = internal::evaluator<Src>;
    SrcEvaluatorType srcEval(src);
    for (typename SrcEvaluatorType::InnerIterator it(srcEval, 0); it; ++it) dst.insert(it.index()) = it.value();
  }
};

template <typename Dest, typename Src>
struct sparse_vector_assign_selector<Dest, Src, SVA_Outer> {
  static void run(Dest& dst, const Src& src) {
    eigen_internal_assert(src.outerSize() == src.size());
    using SrcEvaluatorType = internal::evaluator<Src>;
    SrcEvaluatorType srcEval(src);
    for (Index i = 0; i < src.size(); ++i) {
      typename SrcEvaluatorType::InnerIterator it(srcEval, i);
      if (it) dst.insert(i) = it.value();
    }
  }
};

template <typename Dest, typename Src>
struct sparse_vector_assign_selector<Dest, Src, SVA_RuntimeSwitch> {
  static void run(Dest& dst, const Src& src) {
    if (src.outerSize() == 1)
      sparse_vector_assign_selector<Dest, Src, SVA_Inner>::run(dst, src);
    else
      sparse_vector_assign_selector<Dest, Src, SVA_Outer>::run(dst, src);
  }
};

}  // namespace internal

// Specialization for SparseVector.
// Serializes [size, numNonZeros, innerIndices, values].
template <typename Scalar, int Options, typename StorageIndex>
class Serializer<SparseVector<Scalar, Options, StorageIndex>, void> {
 public:
  using SparseMat = SparseVector<Scalar, Options, StorageIndex>;

  struct Header {
    typename SparseMat::Index size;
    Index num_non_zeros;
  };

  EIGEN_DEVICE_FUNC size_t size(const SparseMat& value) const {
    return sizeof(Header) + (sizeof(Scalar) + sizeof(StorageIndex)) * value.nonZeros();
  }

  EIGEN_DEVICE_FUNC uint8_t* serialize(uint8_t* dest, uint8_t* end, const SparseMat& value) {
    if (EIGEN_PREDICT_FALSE(dest == nullptr)) return nullptr;
    if (EIGEN_PREDICT_FALSE(dest + size(value) > end)) return nullptr;

    const size_t header_bytes = sizeof(Header);
    Header header = {value.innerSize(), value.nonZeros()};
    EIGEN_USING_STD(memcpy)
    memcpy(dest, &header, header_bytes);
    dest += header_bytes;

    // Inner indices.
    std::size_t data_bytes = sizeof(StorageIndex) * header.num_non_zeros;
    if (data_bytes != 0) {
      memcpy(dest, value.innerIndexPtr(), data_bytes);
    }
    dest += data_bytes;

    // Values.
    data_bytes = sizeof(Scalar) * header.num_non_zeros;
    if (data_bytes != 0) {
      memcpy(dest, value.valuePtr(), data_bytes);
    }
    dest += data_bytes;

    return dest;
  }

  EIGEN_DEVICE_FUNC const uint8_t* deserialize(const uint8_t* src, const uint8_t* end, SparseMat& value) const {
    if (EIGEN_PREDICT_FALSE(src == nullptr)) return nullptr;
    if (EIGEN_PREDICT_FALSE(src + sizeof(Header) > end)) return nullptr;

    const size_t header_bytes = sizeof(Header);
    Header header;
    EIGEN_USING_STD(memcpy)
    memcpy(&header, src, header_bytes);
    src += header_bytes;

    // The header is untrusted: check the sizes before allocating, and every inner index after copying.
    if (EIGEN_PREDICT_FALSE(header.size < 0 || header.num_non_zeros < 0 ||
                            header.num_non_zeros > NumTraits<StorageIndex>::highest() ||
                            static_cast<numext::uint64_t>(header.num_non_zeros) >
                                static_cast<numext::uint64_t>(end - src) / (sizeof(StorageIndex) + sizeof(Scalar))))
      return nullptr;

    value.setZero();
    value.resize(header.size);
    value.resizeNonZeros(header.num_non_zeros);

    // Inner indices.
    std::size_t data_bytes = sizeof(StorageIndex) * header.num_non_zeros;
    if (data_bytes != 0) {
      memcpy(value.innerIndexPtr(), src, data_bytes);
    }
    src += data_bytes;

    // Values.
    data_bytes = sizeof(Scalar) * header.num_non_zeros;
    if (data_bytes != 0) {
      memcpy(value.valuePtr(), src, data_bytes);
    }
    src += data_bytes;

    for (Index k = 0; k < header.num_non_zeros; ++k) {
      if (EIGEN_PREDICT_FALSE(value.innerIndexPtr()[k] < 0 || value.innerIndexPtr()[k] >= header.size)) {
        value.resize(0);
        return nullptr;
      }
    }
    return src;
  }
};

}  // end namespace Eigen

#endif  // EIGEN_SPARSEVECTOR_H
