// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// 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-FileCopyrightText: The Eigen Authors
// SPDX-License-Identifier: MPL-2.0

#ifndef EIGEN_SCALEDPERMUTATIONMATRIX_H
#define EIGEN_SCALEDPERMUTATIONMATRIX_H

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

namespace Eigen {

namespace internal {

template <typename Scalar_, int SizeAtCompileTime, int MaxSizeAtCompileTime, typename StorageIndex_>
struct traits<ScaledPermutationMatrix<Scalar_, SizeAtCompileTime, MaxSizeAtCompileTime, StorageIndex_>> {
  using Scalar = Scalar_;
  using StorageIndex = StorageIndex_;
  // Dense, so that products and sums with dense operands promote with the existing rules; the O(n) kernels are
  // selected by the shape (ScaledPermutationShape), as for TriangularView.
  using StorageKind = Dense;
  using XprKind = MatrixXpr;
  using PermutationType = PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, StorageIndex_>;
  using ScalesType = Matrix<Scalar_, SizeAtCompileTime, 1, 0, MaxSizeAtCompileTime, 1>;
  static constexpr int RowsAtCompileTime = SizeAtCompileTime;
  static constexpr int ColsAtCompileTime = SizeAtCompileTime;
  static constexpr int MaxRowsAtCompileTime = MaxSizeAtCompileTime;
  static constexpr int MaxColsAtCompileTime = MaxSizeAtCompileTime;
  static constexpr unsigned int Flags = NestByRefBit;
};

/** \internal The scaled permutation produced by a permutation-like and a diagonal-like operand. */
template <typename Scalar, typename Lhs, typename Rhs, typename StorageIndex>
struct scaled_permutation_result {
  static constexpr int Size = size_prefer_fixed(traits<Lhs>::RowsAtCompileTime, traits<Rhs>::RowsAtCompileTime);
  static constexpr int MaxSize =
      min_size_prefer_fixed(traits<Lhs>::MaxRowsAtCompileTime, traits<Rhs>::MaxRowsAtCompileTime);
  using type = ScaledPermutationMatrix<Scalar, Size, MaxSize, StorageIndex>;
};

template <typename Lhs, typename Rhs, typename StorageIndex>
struct scaled_permutation_product_result {
  using LhsScalar = typename traits<Lhs>::Scalar;
  using RhsScalar = typename traits<Rhs>::Scalar;
  using Scalar =
      typename ScalarBinaryOpTraits<LhsScalar, RhsScalar, scalar_product_op<LhsScalar, RhsScalar>>::ReturnType;
  using type = typename scaled_permutation_result<Scalar, Lhs, Rhs, StorageIndex>::type;
};

/** \internal indices of the inverse permutation: result(indices(k)) = k. */
template <typename IndicesType, typename Result>
EIGEN_DEVICE_FUNC void invert_permutation_indices(const IndicesType& indices, Result& result) {
  using StorageIndex = typename Result::Scalar;
  for (Index k = 0; k < indices.size(); ++k) result.coeffRef(indices.coeff(k)) = StorageIndex(k);
}

}  // namespace internal

/** \class ScaledPermutationBase
 * \ingroup Core_Module
 *
 * \brief Base class for scaled permutation matrices
 *
 * A scaled permutation is the product \f$P D\f$ of a permutation matrix and a diagonal matrix: a square matrix with
 * exactly one nonzero per row and per column. It is stored as the permutation's indices and one scale per
 * column, so that coefficient (indices()(k), k) equals scales()(k).
 *
 * The set is closed under products with permutations, diagonal matrices, scalars and other scaled permutations,
 * and under inversion and transposition; all of these cost \f$O(n)\f$ and return a plain ScaledPermutationMatrix.
 * Products with a dense matrix scale and permute its rows or columns in \f$O(nm)\f$, and assigning to a dense matrix
 * scatters the scales, so writing `P * D * x` or `P * D * P.inverse()` never forms an \f$n \times n\f$ intermediate.
 * Sums with a dense matrix are lazy expressions.
 *
 * \sa class ScaledPermutationMatrix, class PermutationBase, class DiagonalBase
 */
template <typename Derived>
class ScaledPermutationBase : public EigenBase<Derived> {
  using Traits = internal::traits<Derived>;
  using Base = EigenBase<Derived>;

 public:
#ifndef EIGEN_PARSED_BY_DOXYGEN
  using Scalar = typename Traits::Scalar;
  using RealScalar = typename NumTraits<Scalar>::Real;
  using StorageIndex = typename Traits::StorageIndex;
  using StorageKind = typename Traits::StorageKind;
  using PermutationType = typename Traits::PermutationType;
  using ScalesType = typename Traits::ScalesType;
  using IndicesType = typename PermutationType::IndicesType;
  static constexpr int RowsAtCompileTime = Traits::RowsAtCompileTime;
  static constexpr int ColsAtCompileTime = Traits::ColsAtCompileTime;
  static constexpr int MaxRowsAtCompileTime = Traits::MaxRowsAtCompileTime;
  static constexpr int MaxColsAtCompileTime = Traits::MaxColsAtCompileTime;
  static constexpr int SizeAtCompileTime = internal::size_at_compile_time(RowsAtCompileTime, ColsAtCompileTime);
  static constexpr int MaxSizeAtCompileTime =
      internal::size_at_compile_time(MaxRowsAtCompileTime, MaxColsAtCompileTime);
  static constexpr bool IsVectorAtCompileTime = false;
  static constexpr unsigned int Flags = Traits::Flags;
  using DenseMatrixType =
      Matrix<Scalar, RowsAtCompileTime, ColsAtCompileTime, 0, MaxRowsAtCompileTime, MaxColsAtCompileTime>;
  using PlainObject = ScaledPermutationMatrix<Scalar, RowsAtCompileTime, MaxRowsAtCompileTime, StorageIndex>;
  using Nested = const Derived&;
  using Base::derived;
#endif

  /** \returns the number of rows */
  EIGEN_DEVICE_FUNC constexpr Index rows() const { return indices().size(); }
  /** \returns the number of columns */
  EIGEN_DEVICE_FUNC constexpr Index cols() const { return indices().size(); }

  /** \returns the permutation factor \f$P\f$ */
  EIGEN_DEVICE_FUNC const PermutationType& permutation() const { return derived().permutation(); }
  /** \returns the permutation's indices: column \c k has its nonzero in row `indices()(k)` */
  EIGEN_DEVICE_FUNC constexpr const IndicesType& indices() const { return derived().indices(); }
  /** \returns the scales: column \c k's nonzero equals `scales()(k)` */
  EIGEN_DEVICE_FUNC const ScalesType& scales() const { return derived().scales(); }

  /** \returns the coefficient at (\a row, \a col) of the represented matrix */
  EIGEN_DEVICE_FUNC Scalar coeff(Index row, Index col) const {
    eigen_assert(row >= 0 && col >= 0 && row < rows() && col < cols());
    return Index(indices().coeff(col)) == row ? scales().coeff(col) : Scalar(0);
  }

  /** \returns the represented matrix as a plain dense matrix */
  EIGEN_DEVICE_FUNC DenseMatrixType toDenseMatrix() const { return derived(); }

#ifndef EIGEN_PARSED_BY_DOXYGEN
  template <typename DenseDerived>
  EIGEN_DEVICE_FUNC void evalTo(MatrixBase<DenseDerived>& other) const {
    other.setZero();
    for (Index k = 0; k < rows(); ++k) other.coeffRef(indices().coeff(k), k) = scales().coeff(k);
  }
#endif

  /** \returns the inverse, \f$(PD)^{-1} = D^{-1} P^{-1}\f$, which has \f$1 / \text{scales}(k)\f$ at
   * (\c k, `indices()(k)`). The scales must be nonzero. */
  PlainObject inverse() const {
    PlainObject result(rows());
    for (Index k = 0; k < rows(); ++k) {
      const Index image = indices().coeff(k);
      result.indices().coeffRef(image) = StorageIndex(k);
      result.scales().coeffRef(image) = Scalar(1) / scales().coeff(k);
    }
    return result;
  }

  /** \returns the transpose, which has `scales()(k)` at (\c k, `indices()(k)`) */
  PlainObject transpose() const {
    PlainObject result(rows());
    for (Index k = 0; k < rows(); ++k) {
      const Index image = indices().coeff(k);
      result.indices().coeffRef(image) = StorageIndex(k);
      result.scales().coeffRef(image) = scales().coeff(k);
    }
    return result;
  }

  /** \returns the adjoint, the transpose with conjugated scales */
  PlainObject adjoint() const {
    PlainObject result = transpose();
    result.scales() = result.scales().conjugate();
    return result;
  }

  /** \returns the determinant, the permutation's sign times the product of the scales */
  Scalar determinant() const { return Scalar(RealScalar(permutation().determinant())) * scales().prod(); }

  /** \returns the dense matrix product of \c *this by the dense matrix \a other: rows of \a other are scaled and
   * permuted. */
  template <typename OtherDerived>
  EIGEN_DEVICE_FUNC const Product<Derived, OtherDerived, DefaultProduct> operator*(
      const MatrixBase<OtherDerived>& other) const {
    return Product<Derived, OtherDerived, DefaultProduct>(derived(), other.derived());
  }

  /** \returns the dense matrix product of the dense matrix \a other by \a scaled: columns of \a other are scaled
   * and permuted. */
  template <typename OtherDerived>
  EIGEN_DEVICE_FUNC friend const Product<OtherDerived, Derived, DefaultProduct> operator*(
      const MatrixBase<OtherDerived>& other, const ScaledPermutationBase& scaled) {
    return Product<OtherDerived, Derived, DefaultProduct>(other.derived(), scaled.derived());
  }

  /** \returns the dense matrix product of \c *this by the triangular or self-adjoint view \a other */
  template <typename OtherDerived>
  EIGEN_DEVICE_FUNC const Product<Derived, OtherDerived, DefaultProduct> operator*(
      const TriangularBase<OtherDerived>& other) const {
    return Product<Derived, OtherDerived, DefaultProduct>(derived(), other.derived());
  }

  /** \returns the dense matrix product of the triangular or self-adjoint view \a other by \a scaled */
  template <typename OtherDerived>
  EIGEN_DEVICE_FUNC friend const Product<OtherDerived, Derived, DefaultProduct> operator*(
      const TriangularBase<OtherDerived>& other, const ScaledPermutationBase& scaled) {
    return Product<OtherDerived, Derived, DefaultProduct>(other.derived(), scaled.derived());
  }

  // Closed-form products, all O(n). With S e_c = v_c e_{tau(c)} the rules are:
  //   S D: scale v_c d_c            D S: scale d_{tau(c)} v_c
  //   S P: (tau(sigma(c)), v_{sigma(c)})   P S: (sigma(tau(c)), v_c)
  //   S T: (tau(tau2(c)), v_{tau2(c)} v2_c)

  /** \returns the scaled permutation \c *this times the diagonal matrix \a other */
  template <typename OtherDerived>
  typename internal::scaled_permutation_product_result<Derived, OtherDerived, StorageIndex>::type operator*(
      const DiagonalBase<OtherDerived>& other) const {
    using Result = typename internal::scaled_permutation_product_result<Derived, OtherDerived, StorageIndex>::type;
    eigen_assert(rows() == other.rows());
    return Result(indices(), scales().cwiseProduct(other.diagonal()));
  }

  /** \returns the scaled permutation diagonal matrix \a other times \a scaled */
  template <typename OtherDerived>
  friend typename internal::scaled_permutation_product_result<OtherDerived, Derived, StorageIndex>::type operator*(
      const DiagonalBase<OtherDerived>& other, const ScaledPermutationBase& scaled) {
    using Result = typename internal::scaled_permutation_product_result<OtherDerived, Derived, StorageIndex>::type;
    eigen_assert(other.rows() == scaled.rows());
    Result result(scaled.rows());
    result.indices() = scaled.indices();
    for (Index k = 0; k < scaled.rows(); ++k)
      result.scales().coeffRef(k) = other.diagonal().coeff(scaled.indices().coeff(k)) * scaled.scales().coeff(k);
    return result;
  }

  /** \returns the scaled permutation \c *this times the permutation \a other */
  template <typename OtherDerived>
  PlainObject operator*(const PermutationBase<OtherDerived>& other) const {
    eigen_assert(rows() == other.rows());
    PlainObject result(rows());
    for (Index k = 0; k < rows(); ++k) {
      const Index source = other.indices().coeff(k);
      result.indices().coeffRef(k) = indices().coeff(source);
      result.scales().coeffRef(k) = scales().coeff(source);
    }
    return result;
  }

  /** \returns the scaled permutation permutation \a other times \a scaled */
  template <typename OtherDerived>
  friend PlainObject operator*(const PermutationBase<OtherDerived>& other, const ScaledPermutationBase& scaled) {
    eigen_assert(other.rows() == scaled.rows());
    PlainObject result(scaled.rows());
    for (Index k = 0; k < scaled.rows(); ++k)
      result.indices().coeffRef(k) = StorageIndex(other.indices().coeff(scaled.indices().coeff(k)));
    result.scales() = scaled.scales();
    return result;
  }

  /** \returns the scaled permutation \c *this times the inverse permutation \a other */
  template <typename OtherDerived>
  PlainObject operator*(const InverseImpl<OtherDerived, PermutationStorage>& other) const {
    eigen_assert(rows() == other.rows());
    IndicesType inverse(rows());
    internal::invert_permutation_indices(other.derived().nestedExpression().indices(), inverse);
    PlainObject result(rows());
    for (Index k = 0; k < rows(); ++k) {
      const Index source = inverse.coeff(k);
      result.indices().coeffRef(k) = indices().coeff(source);
      result.scales().coeffRef(k) = scales().coeff(source);
    }
    return result;
  }

  /** \returns the scaled permutation inverse permutation \a other times \a scaled */
  template <typename OtherDerived>
  friend PlainObject operator*(const InverseImpl<OtherDerived, PermutationStorage>& other,
                               const ScaledPermutationBase& scaled) {
    eigen_assert(other.rows() == scaled.rows());
    IndicesType inverse(scaled.rows());
    internal::invert_permutation_indices(other.derived().nestedExpression().indices(), inverse);
    PlainObject result(scaled.rows());
    for (Index k = 0; k < scaled.rows(); ++k) result.indices().coeffRef(k) = inverse.coeff(scaled.indices().coeff(k));
    result.scales() = scaled.scales();
    return result;
  }

  /** \returns the scaled permutation \c *this times the scaled permutation \a other */
  template <typename OtherDerived>
  typename internal::scaled_permutation_product_result<Derived, OtherDerived, StorageIndex>::type operator*(
      const ScaledPermutationBase<OtherDerived>& other) const {
    using Result = typename internal::scaled_permutation_product_result<Derived, OtherDerived, StorageIndex>::type;
    eigen_assert(rows() == other.rows());
    Result result(rows());
    for (Index k = 0; k < rows(); ++k) {
      const Index source = other.indices().coeff(k);
      result.indices().coeffRef(k) = indices().coeff(source);
      result.scales().coeffRef(k) = scales().coeff(source) * other.scales().coeff(k);
    }
    return result;
  }

  /** \returns \c *this with its scales multiplied by \a alpha */
  PlainObject operator*(const Scalar& alpha) const { return PlainObject(indices(), scales() * alpha); }

  /** \returns \a scaled with its scales multiplied by \a alpha */
  friend PlainObject operator*(const Scalar& alpha, const ScaledPermutationBase& scaled) {
    return PlainObject(scaled.indices(), alpha * scaled.scales());
  }

  /** \returns \c *this with its scales negated */
  PlainObject operator-() const { return PlainObject(indices(), -scales()); }

  // Sums with a dense matrix are lazy: the scaled permutation is read through its index-based evaluator.

  /** \returns the lazy sum of the dense matrix \a lhs and the scaled permutation \a rhs */
  template <typename OtherDerived>
  EIGEN_DEVICE_FUNC friend const EIGEN_CWISE_BINARY_RETURN_TYPE(OtherDerived, Derived, internal::scalar_sum_op)
  operator+(const MatrixBase<OtherDerived>& lhs, const ScaledPermutationBase & rhs) {
    return EIGEN_CWISE_BINARY_RETURN_TYPE(OtherDerived, Derived, internal::scalar_sum_op)(lhs.derived(), rhs.derived());
  }

  /** \returns the lazy sum of the scaled permutation \a lhs and the dense matrix \a rhs */
  template <typename OtherDerived>
  EIGEN_DEVICE_FUNC friend const EIGEN_CWISE_BINARY_RETURN_TYPE(Derived, OtherDerived, internal::scalar_sum_op)
  operator+(const ScaledPermutationBase & lhs, const MatrixBase<OtherDerived>& rhs) {
    return EIGEN_CWISE_BINARY_RETURN_TYPE(Derived, OtherDerived, internal::scalar_sum_op)(lhs.derived(), rhs.derived());
  }

  /** \returns the lazy difference of the dense matrix \a lhs and the scaled permutation \a rhs */
  template <typename OtherDerived>
  EIGEN_DEVICE_FUNC friend const EIGEN_CWISE_BINARY_RETURN_TYPE(OtherDerived, Derived, internal::scalar_difference_op)
  operator-(const MatrixBase<OtherDerived>& lhs, const ScaledPermutationBase & rhs) {
    return EIGEN_CWISE_BINARY_RETURN_TYPE(OtherDerived, Derived, internal::scalar_difference_op)(lhs.derived(),
                                                                                                 rhs.derived());
  }

  /** \returns the lazy difference of the scaled permutation \a lhs and the dense matrix \a rhs */
  template <typename OtherDerived>
  EIGEN_DEVICE_FUNC friend const EIGEN_CWISE_BINARY_RETURN_TYPE(Derived, OtherDerived, internal::scalar_difference_op)
  operator-(const ScaledPermutationBase & lhs, const MatrixBase<OtherDerived>& rhs) {
    return EIGEN_CWISE_BINARY_RETURN_TYPE(Derived, OtherDerived, internal::scalar_difference_op)(lhs.derived(),
                                                                                                 rhs.derived());
  }
};

/** \class ScaledPermutationMatrix
 * \ingroup Core_Module
 *
 * \brief Scaled permutation matrix \f$P D\f$ with its storage
 *
 * \tparam Scalar_ the type of the scales
 * \tparam SizeAtCompileTime the number of rows/cols, or Dynamic
 * \tparam MaxSizeAtCompileTime the maximum number of rows/cols, or Dynamic; defaults to SizeAtCompileTime
 * \tparam StorageIndex_ the integer type of the permutation's indices
 *
 * This is the type returned by the products of a permutation (or its inverse) and a diagonal matrix, in either
 * order. See ScaledPermutationBase for the operations.
 *
 * \sa class ScaledPermutationBase, class PermutationMatrix, class DiagonalMatrix
 */
template <typename Scalar_, int SizeAtCompileTime, int MaxSizeAtCompileTime, typename StorageIndex_>
class ScaledPermutationMatrix
    : public ScaledPermutationBase<
          ScaledPermutationMatrix<Scalar_, SizeAtCompileTime, MaxSizeAtCompileTime, StorageIndex_>> {
  using Base = ScaledPermutationBase<ScaledPermutationMatrix>;
  using Traits = internal::traits<ScaledPermutationMatrix>;

 public:
#ifndef EIGEN_PARSED_BY_DOXYGEN
  using Scalar = Scalar_;
  using StorageIndex = StorageIndex_;
  using PermutationType = typename Traits::PermutationType;
  using ScalesType = typename Traits::ScalesType;
  using IndicesType = typename PermutationType::IndicesType;
#endif

  /** Default constructor; the matrix is uninitialized. */
  EIGEN_DEVICE_FUNC ScaledPermutationMatrix() = default;

  /** Constructs an uninitialized scaled permutation of the given size. */
  EIGEN_DEVICE_FUNC explicit ScaledPermutationMatrix(Index size) : m_permutation(size), m_scales(size) {}

  /** Constructs the product \a permutation times \a diagonal. */
  template <typename PermutationDerived, typename DiagonalDerived>
  EIGEN_DEVICE_FUNC ScaledPermutationMatrix(const PermutationBase<PermutationDerived>& permutation,
                                            const DiagonalBase<DiagonalDerived>& diagonal)
      : m_permutation(permutation), m_scales(diagonal.diagonal()) {
    eigen_assert(permutation.rows() == diagonal.rows());
  }

  /** Constructs the scaled permutation with the given \a indices and \a scales. */
  template <typename IndicesDerived, typename ScalesDerived>
  EIGEN_DEVICE_FUNC ScaledPermutationMatrix(const MatrixBase<IndicesDerived>& indices,
                                            const MatrixBase<ScalesDerived>& scales)
      : m_permutation(indices), m_scales(scales) {
    eigen_assert(indices.size() == scales.size());
  }

  /** Converts the permutation \a permutation, all scales being one. */
  template <typename OtherDerived>
  EIGEN_DEVICE_FUNC explicit ScaledPermutationMatrix(const PermutationBase<OtherDerived>& permutation)
      : m_permutation(permutation), m_scales(ScalesType::Ones(permutation.rows())) {}

  /** Converts the diagonal matrix \a diagonal, the permutation being the identity. */
  template <typename OtherDerived>
  EIGEN_DEVICE_FUNC explicit ScaledPermutationMatrix(const DiagonalBase<OtherDerived>& diagonal)
      : m_permutation(diagonal.rows()), m_scales(diagonal.diagonal()) {
    m_permutation.setIdentity();
  }

  /** Copies the scaled permutation \a other. */
  template <typename OtherDerived>
  EIGEN_DEVICE_FUNC ScaledPermutationMatrix(const ScaledPermutationBase<OtherDerived>& other)
      : m_permutation(other.permutation()), m_scales(other.scales()) {}

  /** Copies the scaled permutation \a other. */
  template <typename OtherDerived>
  EIGEN_DEVICE_FUNC ScaledPermutationMatrix& operator=(const ScaledPermutationBase<OtherDerived>& other) {
    m_permutation = other.permutation();
    m_scales = other.scales();
    return *this;
  }

  /** \returns the permutation factor */
  EIGEN_DEVICE_FUNC const PermutationType& permutation() const { return m_permutation; }
  /** \returns a reference to the permutation factor */
  EIGEN_DEVICE_FUNC PermutationType& permutation() { return m_permutation; }
  /** \returns the permutation's indices */
  EIGEN_DEVICE_FUNC constexpr const IndicesType& indices() const { return m_permutation.indices(); }
  /** \returns a reference to the permutation's indices */
  EIGEN_DEVICE_FUNC constexpr IndicesType& indices() { return m_permutation.indices(); }
  /** \returns the scales */
  EIGEN_DEVICE_FUNC const ScalesType& scales() const { return m_scales; }
  /** \returns a reference to the scales */
  EIGEN_DEVICE_FUNC ScalesType& scales() { return m_scales; }

  /** Resizes to the given size, leaving the coefficients uninitialized. */
  EIGEN_DEVICE_FUNC void resize(Index size) {
    m_permutation.resize(size);
    m_scales.resize(size);
  }

  /** Sets \c *this to the identity matrix. */
  EIGEN_DEVICE_FUNC void setIdentity() {
    m_permutation.setIdentity();
    m_scales.setOnes();
  }

  /** Sets \c *this to the identity matrix of the given size. */
  EIGEN_DEVICE_FUNC void setIdentity(Index size) {
    resize(size);
    setIdentity();
  }

 protected:
  PermutationType m_permutation;
  ScalesType m_scales;
};

// The products of a permutation (or its inverse) and a diagonal matrix. With P e_c = e_{sigma(c)}:
//   P D:   (sigma(c), d_c)          D P:   (sigma(c), d_{sigma(c)})
//   P^-1 D: (sigma^-1(c), d_c)      D P^-1: (sigma^-1(c), d_{sigma^-1(c)})

/** \returns the scaled permutation \a permutation times \a diagonal
 * \relates ScaledPermutationMatrix */
template <typename PermutationDerived, typename DiagonalDerived>
typename internal::scaled_permutation_result<typename DiagonalDerived::Scalar, PermutationDerived, DiagonalDerived,
                                             typename PermutationDerived::StorageIndex>::type
operator*(const PermutationBase<PermutationDerived>& permutation, const DiagonalBase<DiagonalDerived>& diagonal) {
  using Result =
      typename internal::scaled_permutation_result<typename DiagonalDerived::Scalar, PermutationDerived,
                                                   DiagonalDerived, typename PermutationDerived::StorageIndex>::type;
  eigen_assert(permutation.rows() == diagonal.rows());
  return Result(permutation.indices(), diagonal.diagonal());
}

/** \returns the scaled permutation \a diagonal times \a permutation
 * \relates ScaledPermutationMatrix */
template <typename DiagonalDerived, typename PermutationDerived>
typename internal::scaled_permutation_result<typename DiagonalDerived::Scalar, PermutationDerived, DiagonalDerived,
                                             typename PermutationDerived::StorageIndex>::type
operator*(const DiagonalBase<DiagonalDerived>& diagonal, const PermutationBase<PermutationDerived>& permutation) {
  using Result =
      typename internal::scaled_permutation_result<typename DiagonalDerived::Scalar, PermutationDerived,
                                                   DiagonalDerived, typename PermutationDerived::StorageIndex>::type;
  eigen_assert(permutation.rows() == diagonal.rows());
  Result result(permutation.rows());
  result.indices() = permutation.indices();
  for (Index k = 0; k < permutation.rows(); ++k)
    result.scales().coeffRef(k) = diagonal.diagonal().coeff(permutation.indices().coeff(k));
  return result;
}

/** \returns the scaled permutation \a inverse (an inverse permutation) times \a diagonal
 * \relates ScaledPermutationMatrix */
template <typename PermutationType, typename DiagonalDerived>
typename internal::scaled_permutation_result<typename DiagonalDerived::Scalar, PermutationType, DiagonalDerived,
                                             typename PermutationType::StorageIndex>::type
operator*(const InverseImpl<PermutationType, PermutationStorage>& inverse,
          const DiagonalBase<DiagonalDerived>& diagonal) {
  using Result =
      typename internal::scaled_permutation_result<typename DiagonalDerived::Scalar, PermutationType, DiagonalDerived,
                                                   typename PermutationType::StorageIndex>::type;
  eigen_assert(inverse.rows() == diagonal.rows());
  Result result(inverse.rows());
  internal::invert_permutation_indices(inverse.derived().nestedExpression().indices(), result.indices());
  result.scales() = diagonal.diagonal();
  return result;
}

/** \returns the scaled permutation \a diagonal times \a inverse (an inverse permutation)
 * \relates ScaledPermutationMatrix */
template <typename DiagonalDerived, typename PermutationType>
typename internal::scaled_permutation_result<typename DiagonalDerived::Scalar, PermutationType, DiagonalDerived,
                                             typename PermutationType::StorageIndex>::type
operator*(const DiagonalBase<DiagonalDerived>& diagonal,
          const InverseImpl<PermutationType, PermutationStorage>& inverse) {
  using Result =
      typename internal::scaled_permutation_result<typename DiagonalDerived::Scalar, PermutationType, DiagonalDerived,
                                                   typename PermutationType::StorageIndex>::type;
  eigen_assert(inverse.rows() == diagonal.rows());
  Result result(inverse.rows());
  internal::invert_permutation_indices(inverse.derived().nestedExpression().indices(), result.indices());
  for (Index k = 0; k < inverse.rows(); ++k)
    result.scales().coeffRef(k) = diagonal.diagonal().coeff(result.indices().coeff(k));
  return result;
}

namespace internal {

template <typename Scalar_, int SizeAtCompileTime, int MaxSizeAtCompileTime, typename StorageIndex_>
struct evaluator_traits<ScaledPermutationMatrix<Scalar_, SizeAtCompileTime, MaxSizeAtCompileTime, StorageIndex_>> {
  using Kind = IndexBased;
  using Shape = ScaledPermutationShape;
};

/** \internal Index-based evaluator, for the lazy sums with a dense matrix. Every coefficient is synthesized, so there
 * is no linear, packet or direct access. */
template <typename Scalar_, int SizeAtCompileTime, int MaxSizeAtCompileTime, typename StorageIndex_>
struct evaluator<ScaledPermutationMatrix<Scalar_, SizeAtCompileTime, MaxSizeAtCompileTime, StorageIndex_>>
    : evaluator_base<ScaledPermutationMatrix<Scalar_, SizeAtCompileTime, MaxSizeAtCompileTime, StorageIndex_>> {
  using XprType = ScaledPermutationMatrix<Scalar_, SizeAtCompileTime, MaxSizeAtCompileTime, StorageIndex_>;
  using Scalar = Scalar_;
  using CoeffReturnType = Scalar;

  static constexpr int CoeffReadCost =
      int(NumTraits<StorageIndex_>::ReadCost) + int(NumTraits<Scalar>::ReadCost) + int(NumTraits<Scalar>::AddCost);
  static constexpr unsigned int Flags = 0;
  static constexpr int Alignment = 0;

  EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr) : m_indices(xpr.indices()), m_scales(xpr.scales()) {}

  EIGEN_DEVICE_FUNC Scalar coeff(Index row, Index col) const {
    return Index(m_indices.coeff(col)) == row ? m_scales.coeff(col) : Scalar(0);
  }

  // Linear access is requested only for vector-shaped operands (inner products), i.e. a 1x1 matrix.
  EIGEN_DEVICE_FUNC Scalar coeff(Index index) const {
    eigen_assert(index == 0);
    return m_scales.coeff(index);
  }

 protected:
  evaluator<typename XprType::IndicesType> m_indices;
  evaluator<typename XprType::ScalesType> m_scales;
};

struct ScaledPermutation2Dense {};

template <>
struct AssignmentKind<DenseShape, ScaledPermutationShape> {
  using Kind = ScaledPermutation2Dense;
};

// Scaled permutation to dense assignment: zero fill plus one scatter of n coefficients.
template <typename DstXprType, typename SrcXprType, typename Functor>
struct Assignment<DstXprType, SrcXprType, Functor, ScaledPermutation2Dense> {
  static EIGEN_DEVICE_FUNC void run(
      DstXprType& dst, const SrcXprType& src,
      const internal::assign_op<typename DstXprType::Scalar, typename SrcXprType::Scalar>&) {
    if (dst.rows() != src.rows() || dst.cols() != src.cols()) dst.resize(src.rows(), src.cols());
    dst.setZero();
    for (Index k = 0; k < src.rows(); ++k) dst.coeffRef(src.indices().coeff(k), k) = src.scales().coeff(k);
  }

  static EIGEN_DEVICE_FUNC void run(
      DstXprType& dst, const SrcXprType& src,
      const internal::add_assign_op<typename DstXprType::Scalar, typename SrcXprType::Scalar>&) {
    eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
    for (Index k = 0; k < src.rows(); ++k) dst.coeffRef(src.indices().coeff(k), k) += src.scales().coeff(k);
  }

  static EIGEN_DEVICE_FUNC void run(
      DstXprType& dst, const SrcXprType& src,
      const internal::sub_assign_op<typename DstXprType::Scalar, typename SrcXprType::Scalar>&) {
    eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
    for (Index k = 0; k < src.rows(); ++k) dst.coeffRef(src.indices().coeff(k), k) -= src.scales().coeff(k);
  }
};

/***************************************************************************
 * Products with a dense matrix: rows (S * X) or columns (X * S) are scaled and permuted, O(n m).
 * evalTo reuses the dense permutation kernel, which handles X aliasing dst, and scales in place afterwards;
 * the accumulating form works on the nested (evaluated once) operand.
 * scaleAndAddTo evaluates dst += alpha * (lhs * rhs) with alpha a left factor of the product. Scalar
 * multiplication need not commute, so both kernels keep that operand order: S * X regroups it as
 * (alpha * v_c) * X(c, j) by associativity; X * S keeps alpha * (X(i, tau(c)) * v_c), as folding alpha into
 * v_c would move it past the dense coefficient.
 ***************************************************************************/

template <typename Lhs, typename Rhs, int ProductTag>
struct generic_product_impl<Lhs, Rhs, ScaledPermutationShape, DenseShape, ProductTag>
    : generic_product_impl_base<Lhs, Rhs,
                                generic_product_impl<Lhs, Rhs, ScaledPermutationShape, DenseShape, ProductTag>> {
  using Scalar = typename Product<Lhs, Rhs>::Scalar;

  template <typename Dest>
  static EIGEN_DEVICE_FUNC void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs) {
    permutation_matrix_product<Rhs, OnTheLeft, false, DenseShape>::run(dst, lhs.permutation(), rhs);
    for (Index k = 0; k < lhs.rows(); ++k) {
      auto row = dst.row(lhs.indices().coeff(k));
      row = lhs.scales().coeff(k) * row;
    }
  }

  template <typename Dest>
  static EIGEN_DEVICE_FUNC void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha) {
    typename nested_eval<Rhs, 1>::type rhsNested(rhs);
    for (Index k = 0; k < lhs.rows(); ++k)
      dst.row(lhs.indices().coeff(k)) += (alpha * lhs.scales().coeff(k)) * rhsNested.row(k);
  }
};

template <typename Lhs, typename Rhs, int ProductTag>
struct generic_product_impl<Lhs, Rhs, DenseShape, ScaledPermutationShape, ProductTag>
    : generic_product_impl_base<Lhs, Rhs,
                                generic_product_impl<Lhs, Rhs, DenseShape, ScaledPermutationShape, ProductTag>> {
  using Scalar = typename Product<Lhs, Rhs>::Scalar;

  template <typename Dest>
  static EIGEN_DEVICE_FUNC void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs) {
    permutation_matrix_product<Lhs, OnTheRight, false, DenseShape>::run(dst, rhs.permutation(), lhs);
    for (Index k = 0; k < rhs.rows(); ++k) dst.col(k) *= rhs.scales().coeff(k);
  }

  template <typename Dest>
  static EIGEN_DEVICE_FUNC void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha) {
    typename nested_eval<Lhs, 1>::type lhsNested(lhs);
    for (Index k = 0; k < rhs.rows(); ++k)
      dst.col(k) += alpha * (lhsNested.col(rhs.indices().coeff(k)) * rhs.scales().coeff(k));
  }
};

// A triangular or self-adjoint operand is evaluated into a plain matrix first, as toDenseMatrix() does.
template <typename Lhs, typename Rhs, int ProductTag, bool ViewOnTheRight>
struct scaled_permutation_view_product_impl;

template <typename Lhs, typename Rhs, int ProductTag>
struct scaled_permutation_view_product_impl<Lhs, Rhs, ProductTag, true>
    : generic_product_impl_base<Lhs, Rhs, scaled_permutation_view_product_impl<Lhs, Rhs, ProductTag, true>> {
  using Scalar = typename Product<Lhs, Rhs>::Scalar;
  using DenseType = typename Rhs::DenseMatrixType;
  using DenseImpl = generic_product_impl<Lhs, DenseType, ScaledPermutationShape, DenseShape, ProductTag>;

  template <typename Dest>
  static EIGEN_DEVICE_FUNC void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs) {
    const DenseType dense(rhs);
    DenseImpl::evalTo(dst, lhs, dense);
  }
  template <typename Dest>
  static EIGEN_DEVICE_FUNC void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha) {
    const DenseType dense(rhs);
    DenseImpl::scaleAndAddTo(dst, lhs, dense, alpha);
  }
};

template <typename Lhs, typename Rhs, int ProductTag>
struct scaled_permutation_view_product_impl<Lhs, Rhs, ProductTag, false>
    : generic_product_impl_base<Lhs, Rhs, scaled_permutation_view_product_impl<Lhs, Rhs, ProductTag, false>> {
  using Scalar = typename Product<Lhs, Rhs>::Scalar;
  using DenseType = typename Lhs::DenseMatrixType;
  using DenseImpl = generic_product_impl<DenseType, Rhs, DenseShape, ScaledPermutationShape, ProductTag>;

  template <typename Dest>
  static EIGEN_DEVICE_FUNC void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs) {
    const DenseType dense(lhs);
    DenseImpl::evalTo(dst, dense, rhs);
  }
  template <typename Dest>
  static EIGEN_DEVICE_FUNC void scaleAndAddTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, const Scalar& alpha) {
    const DenseType dense(lhs);
    DenseImpl::scaleAndAddTo(dst, dense, rhs, alpha);
  }
};

template <typename Lhs, typename Rhs, int ProductTag>
struct generic_product_impl<Lhs, Rhs, ScaledPermutationShape, TriangularShape, ProductTag>
    : scaled_permutation_view_product_impl<Lhs, Rhs, ProductTag, true> {};
template <typename Lhs, typename Rhs, int ProductTag>
struct generic_product_impl<Lhs, Rhs, ScaledPermutationShape, SelfAdjointShape, ProductTag>
    : scaled_permutation_view_product_impl<Lhs, Rhs, ProductTag, true> {};
template <typename Lhs, typename Rhs, int ProductTag>
struct generic_product_impl<Lhs, Rhs, TriangularShape, ScaledPermutationShape, ProductTag>
    : scaled_permutation_view_product_impl<Lhs, Rhs, ProductTag, false> {};
template <typename Lhs, typename Rhs, int ProductTag>
struct generic_product_impl<Lhs, Rhs, SelfAdjointShape, ScaledPermutationShape, ProductTag>
    : scaled_permutation_view_product_impl<Lhs, Rhs, ProductTag, false> {};

}  // namespace internal

}  // namespace Eigen

#endif  // EIGEN_SCALEDPERMUTATIONMATRIX_H
