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

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

namespace Eigen {

enum {
  StandardCompressedFormat =
      2 /**< used by Ref<SparseMatrix> to specify whether the input storage must be in standard compressed form */
};

namespace internal {

template <typename Derived>
class SparseRefBase;

template <typename MatScalar, int MatOptions, typename MatIndex, int Options_, typename StrideType_>
struct traits<Ref<SparseMatrix<MatScalar, MatOptions, MatIndex>, Options_, StrideType_>>
    : public traits<SparseMatrix<MatScalar, MatOptions, MatIndex>> {
  typedef SparseMatrix<MatScalar, MatOptions, MatIndex> PlainObjectType;
  enum { Options = Options_, Flags = traits<PlainObjectType>::Flags | CompressedAccessBit | NestByRefBit };

  template <typename Derived>
  struct match {
    enum {
      StorageOrderMatch = PlainObjectType::IsVectorAtCompileTime || Derived::IsVectorAtCompileTime ||
                          ((PlainObjectType::Flags & RowMajorBit) == (Derived::Flags & RowMajorBit)),
      MatchAtCompileTime = (Derived::Flags & CompressedAccessBit) && StorageOrderMatch
    };
    typedef std::conditional_t<MatchAtCompileTime, std::true_type, std::false_type> type;
  };
};

template <typename MatScalar, int MatOptions, typename MatIndex, int Options_, typename StrideType_>
struct traits<Ref<const SparseMatrix<MatScalar, MatOptions, MatIndex>, Options_, StrideType_>>
    : public traits<Ref<SparseMatrix<MatScalar, MatOptions, MatIndex>, Options_, StrideType_>> {
  enum {
    Flags =
        (traits<SparseMatrix<MatScalar, MatOptions, MatIndex>>::Flags | CompressedAccessBit | NestByRefBit) & ~LvalueBit
  };
};

template <typename MatScalar, int MatOptions, typename MatIndex, int Options_, typename StrideType_>
struct traits<Ref<SparseVector<MatScalar, MatOptions, MatIndex>, Options_, StrideType_>>
    : public traits<SparseVector<MatScalar, MatOptions, MatIndex>> {
  typedef SparseVector<MatScalar, MatOptions, MatIndex> PlainObjectType;
  enum { Options = Options_, Flags = traits<PlainObjectType>::Flags | CompressedAccessBit | NestByRefBit };

  template <typename Derived>
  struct match {
    enum { MatchAtCompileTime = (Derived::Flags & CompressedAccessBit) && Derived::IsVectorAtCompileTime };
    typedef std::conditional_t<MatchAtCompileTime, std::true_type, std::false_type> type;
  };
};

template <typename MatScalar, int MatOptions, typename MatIndex, int Options_, typename StrideType_>
struct traits<Ref<const SparseVector<MatScalar, MatOptions, MatIndex>, Options_, StrideType_>>
    : public traits<Ref<SparseVector<MatScalar, MatOptions, MatIndex>, Options_, StrideType_>> {
  enum {
    Flags =
        (traits<SparseVector<MatScalar, MatOptions, MatIndex>>::Flags | CompressedAccessBit | NestByRefBit) & ~LvalueBit
  };
};

template <typename Derived>
struct traits<SparseRefBase<Derived>> : public traits<Derived> {};

template <typename Derived>
class SparseRefBase : public SparseMapBase<Derived> {
 public:
  typedef SparseMapBase<Derived> Base;
  EIGEN_SPARSE_PUBLIC_INTERFACE(SparseRefBase)

  SparseRefBase()
      : Base(RowsAtCompileTime == Dynamic ? 0 : RowsAtCompileTime, ColsAtCompileTime == Dynamic ? 0 : ColsAtCompileTime,
             0, 0, 0, 0, 0) {}

 protected:
  template <typename Expression>
  void construct(Expression& expr) {
    EIGEN_IF_CONSTEXPR (Expression::IsVectorAtCompileTime) {
      const Index offset = expr.outerIndexPtr() ? expr.outerIndexPtr()[0] : 0;
      auto inner_index_ptr = expr.innerIndexPtr();
      auto value_ptr = expr.valuePtr();
      if (inner_index_ptr) inner_index_ptr += offset;
      if (value_ptr) value_ptr += offset;
      internal::construct_at<Base>(this, expr.size(), expr.nonZeros(), inner_index_ptr, value_ptr);
    } else if (expr.outerIndexPtr() == 0) {
      internal::construct_at<Base>(this, expr.size(), expr.nonZeros(), expr.innerIndexPtr(), expr.valuePtr());
    } else {
      internal::construct_at<Base>(this, expr.rows(), expr.cols(), expr.nonZeros(), expr.outerIndexPtr(),
                                   expr.innerIndexPtr(), expr.valuePtr(), expr.innerNonZeroPtr());
    }
  }
};

}  // namespace internal

/**
 * \ingroup SparseCore_Module
 *
 * \brief A sparse matrix expression referencing an existing sparse expression
 *
 * \tparam SparseMatrixType the equivalent sparse matrix type of the referenced data, it must be a template instance of
 * class SparseMatrix. \tparam Options specifies whether a standard compressed format is required \c Options is  \c
 * #StandardCompressedFormat, or \c 0. The default is \c 0.
 *
 * \sa class Ref
 */
#ifndef EIGEN_PARSED_BY_DOXYGEN
template <typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
class Ref<SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>
    : public internal::SparseRefBase<Ref<SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>>
#else
template <typename SparseMatrixType, int Options>
class Ref<SparseMatrixType, Options>
    : public SparseMapBase<Derived, WriteAccessors>  // Note: 'Derived' is used here intentionally; it resolves
                                                     // correctly via CRTP.
#endif
{
  typedef internal::traits<Ref> Traits;
  template <int OtherOptions>
  inline Ref(const SparseMatrix<MatScalar, OtherOptions, MatIndex>& expr);
  template <int OtherOptions>
  inline Ref(const Map<SparseMatrix<MatScalar, OtherOptions, MatIndex>>& expr);

 public:
  typedef internal::SparseRefBase<Ref> Base;
  EIGEN_SPARSE_PUBLIC_INTERFACE(Ref)

#ifndef EIGEN_PARSED_BY_DOXYGEN
  template <int OtherOptions>
  inline Ref(SparseMatrix<MatScalar, OtherOptions, MatIndex>& expr) {
    EIGEN_STATIC_ASSERT(
        bool(Traits::template match<SparseMatrix<MatScalar, OtherOptions, MatIndex>>::MatchAtCompileTime),
        STORAGE_LAYOUT_DOES_NOT_MATCH);
    eigen_assert(((Options & int(StandardCompressedFormat)) == 0) || (expr.isCompressed()));
    Base::construct(expr.derived());
  }

  template <int OtherOptions>
  inline Ref(Map<SparseMatrix<MatScalar, OtherOptions, MatIndex>>& expr) {
    EIGEN_STATIC_ASSERT(
        bool(Traits::template match<SparseMatrix<MatScalar, OtherOptions, MatIndex>>::MatchAtCompileTime),
        STORAGE_LAYOUT_DOES_NOT_MATCH);
    eigen_assert(((Options & int(StandardCompressedFormat)) == 0) || (expr.isCompressed()));
    Base::construct(expr.derived());
  }

  template <typename Derived>
  inline Ref(const SparseCompressedBase<Derived>& expr)
#else
  /** Implicit constructor from any sparse expression (2D matrix or 1D vector) */
  template <typename Derived>
  inline Ref(SparseCompressedBase<Derived>& expr)
#endif
  {
    EIGEN_STATIC_ASSERT(bool(internal::is_lvalue<Derived>::value), THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY);
    EIGEN_STATIC_ASSERT(bool(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH);
    eigen_assert(((Options & int(StandardCompressedFormat)) == 0) || (expr.isCompressed()));
    Base::construct(expr.const_cast_derived());
  }
};

// this is the const ref version
template <typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
class Ref<const SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>
    : public internal::SparseRefBase<Ref<const SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>> {
  typedef SparseMatrix<MatScalar, MatOptions, MatIndex> TPlainObjectType;
  typedef internal::traits<Ref> Traits;

 public:
  typedef internal::SparseRefBase<Ref> Base;
  EIGEN_SPARSE_PUBLIC_INTERFACE(Ref)

  template <typename Derived>
  inline Ref(const SparseMatrixBase<Derived>& expr) : m_hasCopy(false) {
    construct(expr.derived(), typename Traits::template match<Derived>::type());
  }

  inline Ref(const Ref& other) : Base(other), m_hasCopy(false) {
    // copy constructor shall not copy the m_object, to avoid unnecessary malloc and copy
  }

  template <typename OtherRef>
  inline Ref(const RefBase<OtherRef>& other) : m_hasCopy(false) {
    construct(other.derived(), typename Traits::template match<OtherRef>::type());
  }

  ~Ref() {
    if (m_hasCopy) {
      internal::destroy_at(reinterpret_cast<TPlainObjectType*>(&m_storage));
    }
  }

 protected:
  template <typename Expression>
  void construct(const Expression& expr, std::true_type) {
    if ((Options & int(StandardCompressedFormat)) && (!expr.isCompressed())) {
      TPlainObjectType* obj = internal::construct_at(reinterpret_cast<TPlainObjectType*>(&m_storage), expr);
      m_hasCopy = true;
      Base::construct(*obj);
    } else {
      Base::construct(expr);
    }
  }

  template <typename Expression>
  void construct(const Expression& expr, std::false_type) {
    TPlainObjectType* obj = internal::construct_at(reinterpret_cast<TPlainObjectType*>(&m_storage), expr);
    m_hasCopy = true;
    Base::construct(*obj);
  }

  typename internal::aligned_storage<sizeof(TPlainObjectType), EIGEN_ALIGNOF(TPlainObjectType)>::type m_storage;
  bool m_hasCopy;
};

/**
 * \ingroup SparseCore_Module
 *
 * \brief A sparse vector expression referencing an existing sparse vector expression
 *
 * \tparam SparseVectorType the equivalent sparse vector type of the referenced data, it must be a template instance of
 * class SparseVector.
 *
 * \sa class Ref
 */
#ifndef EIGEN_PARSED_BY_DOXYGEN
template <typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
class Ref<SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>
    : public internal::SparseRefBase<Ref<SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>>
#else
template <typename SparseVectorType>
class Ref<SparseVectorType> : public SparseMapBase<Derived, WriteAccessors>
#endif
{
  typedef SparseVector<MatScalar, MatOptions, MatIndex> PlainObjectType;
  typedef internal::traits<Ref> Traits;
  template <int OtherOptions>
  inline Ref(const SparseVector<MatScalar, OtherOptions, MatIndex>& expr);

 public:
  typedef internal::SparseRefBase<Ref> Base;
  EIGEN_SPARSE_PUBLIC_INTERFACE(Ref)

#ifndef EIGEN_PARSED_BY_DOXYGEN
  template <int OtherOptions>
  inline Ref(SparseVector<MatScalar, OtherOptions, MatIndex>& expr) {
    EIGEN_STATIC_ASSERT(
        bool(Traits::template match<SparseVector<MatScalar, OtherOptions, MatIndex>>::MatchAtCompileTime),
        STORAGE_LAYOUT_DOES_NOT_MATCH);
    Base::construct(expr.derived());
  }

  template <typename Derived>
  inline Ref(const SparseCompressedBase<Derived>& expr)
#else
  /** Implicit constructor from any 1D sparse vector expression */
  template <typename Derived>
  inline Ref(SparseCompressedBase<Derived>& expr)
#endif
  {
    EIGEN_STATIC_ASSERT(bool(internal::is_lvalue<Derived>::value), THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY);
    EIGEN_STATIC_ASSERT(bool(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH);
    EIGEN_STATIC_ASSERT((!std::is_same<Derived, PlainObjectType>::value),
                        THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY);
    Base::construct(expr.const_cast_derived());
  }
};

// this is the const ref version
template <typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
class Ref<const SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>
    : public internal::SparseRefBase<Ref<const SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>> {
  typedef SparseVector<MatScalar, MatOptions, MatIndex> TPlainObjectType;
  typedef internal::traits<Ref> Traits;

 public:
  typedef internal::SparseRefBase<Ref> Base;
  EIGEN_SPARSE_PUBLIC_INTERFACE(Ref)

  template <typename Derived>
  inline Ref(const SparseMatrixBase<Derived>& expr) : m_hasCopy(false) {
    construct(expr.derived(), typename Traits::template match<Derived>::type());
  }

  inline Ref(const Ref& other) : Base(other), m_hasCopy(false) {
    // copy constructor shall not copy the m_object, to avoid unnecessary malloc and copy
  }

  template <typename OtherRef>
  inline Ref(const RefBase<OtherRef>& other) : m_hasCopy(false) {
    construct(other.derived(), typename Traits::template match<OtherRef>::type());
  }

  ~Ref() {
    if (m_hasCopy) {
      internal::destroy_at(reinterpret_cast<TPlainObjectType*>(&m_storage));
    }
  }

 protected:
  template <typename Expression>
  void construct(const Expression& expr, std::true_type) {
    Base::construct(expr);
  }

  template <typename Expression>
  void construct(const Expression& expr, std::false_type) {
    TPlainObjectType* obj = internal::construct_at(reinterpret_cast<TPlainObjectType*>(&m_storage), expr);
    m_hasCopy = true;
    Base::construct(*obj);
  }

  typename internal::aligned_storage<sizeof(TPlainObjectType), EIGEN_ALIGNOF(TPlainObjectType)>::type m_storage;
  bool m_hasCopy;
};

namespace internal {

// FIXME: consider introducing a general evaluator_ref that we can specialize for any sparse object once, and thus
// remove this copy-pasta thing...

template <typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
struct evaluator<Ref<SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>>
    : evaluator<SparseCompressedBase<Ref<SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>>> {
  typedef evaluator<SparseCompressedBase<Ref<SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>>> Base;
  typedef Ref<SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType> XprType;
  evaluator() = default;
  explicit evaluator(const XprType& mat) : Base(mat) {}
};

template <typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
struct evaluator<Ref<const SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>>
    : evaluator<SparseCompressedBase<Ref<const SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>>> {
  typedef evaluator<SparseCompressedBase<Ref<const SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>>>
      Base;
  typedef Ref<const SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType> XprType;
  evaluator() = default;
  explicit evaluator(const XprType& mat) : Base(mat) {}
};

template <typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
struct evaluator<Ref<SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>>
    : evaluator<SparseCompressedBase<Ref<SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>>> {
  typedef evaluator<SparseCompressedBase<Ref<SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>>> Base;
  typedef Ref<SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType> XprType;
  evaluator() = default;
  explicit evaluator(const XprType& mat) : Base(mat) {}
};

template <typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
struct evaluator<Ref<const SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>>
    : evaluator<SparseCompressedBase<Ref<const SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>>> {
  typedef evaluator<SparseCompressedBase<Ref<const SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>>>
      Base;
  typedef Ref<const SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType> XprType;
  evaluator() = default;
  explicit evaluator(const XprType& mat) : Base(mat) {}
};

}  // namespace internal

}  // end namespace Eigen

#endif  // EIGEN_SPARSE_REF_H
