// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009-2011, 2013 Jitse Niesen <jitse@maths.leeds.ac.uk>
//
// 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_MATRIX_FUNCTION_H
#define EIGEN_MATRIX_FUNCTION_H

#include "StemFunction.h"

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

namespace Eigen {

namespace internal {

/** \brief Maximum distance allowed between eigenvalues to be considered "close". */
static const float matrix_function_separation = 0.1f;

/** \ingroup MatrixFunctions_Module
 * \class MatrixFunctionAtomic
 * \brief Helper class for computing matrix functions of atomic matrices.
 *
 * Here, an atomic matrix is a triangular matrix whose diagonal entries are close to each other.
 */
template <typename MatrixType>
class MatrixFunctionAtomic {
 public:
  typedef typename MatrixType::Scalar Scalar;
  typedef typename stem_function<Scalar>::type StemFunction;

  /** \brief Constructor
   * \param[in]  f  matrix function to compute.
   */
  MatrixFunctionAtomic(StemFunction f) : m_f(f) {}

  /** \brief Compute matrix function of atomic matrix
   * \param[in]  A  argument of matrix function, should be upper triangular and atomic
   * \returns  f(A), the matrix function evaluated at the given matrix
   */
  MatrixType compute(const MatrixType& A);

 private:
  StemFunction* m_f;
};

template <typename MatrixType>
typename NumTraits<typename MatrixType::Scalar>::Real matrix_function_compute_mu(const MatrixType& A) {
  typedef typename plain_col_type<MatrixType>::type VectorType;
  Index rows = A.rows();
  const MatrixType N = MatrixType::Identity(rows, rows) - A;
  VectorType e = VectorType::Ones(rows);
  N.template triangularView<Upper>().solveInPlace(e);
  return e.cwiseAbs().maxCoeff();
}

template <typename MatrixType>
MatrixType MatrixFunctionAtomic<MatrixType>::compute(const MatrixType& A) {
  // TODO: Use that A is upper triangular
  typedef typename NumTraits<Scalar>::Real RealScalar;
  Index rows = A.rows();
  Scalar avgEival = A.trace() / Scalar(RealScalar(rows));
  MatrixType Ashifted = A - avgEival * MatrixType::Identity(rows, rows);
  RealScalar mu = matrix_function_compute_mu(Ashifted);
  MatrixType F = m_f(avgEival, 0) * MatrixType::Identity(rows, rows);
  MatrixType P = Ashifted;
  MatrixType Fincr;
  for (Index s = 1; double(s) < 1.1 * double(rows) + 10.0; s++) {  // upper limit is fairly arbitrary
    Fincr = m_f(avgEival, static_cast<int>(s)) * P;
    F += Fincr;
    P = Scalar(RealScalar(1) / RealScalar(s + 1)) * P * Ashifted;

    // test whether Taylor series converged
    const RealScalar F_norm = F.cwiseAbs().rowwise().sum().maxCoeff();
    const RealScalar Fincr_norm = Fincr.cwiseAbs().rowwise().sum().maxCoeff();
    if (Fincr_norm < NumTraits<Scalar>::epsilon() * F_norm) {
      RealScalar delta = 0;
      RealScalar rfactorial = 1;
      for (Index r = 0; r < rows; r++) {
        RealScalar mx = 0;
        for (Index i = 0; i < rows; i++)
          mx = (std::max)(mx, std::abs(m_f(Ashifted(i, i) + avgEival, static_cast<int>(s + r))));
        if (r != 0) rfactorial *= RealScalar(r);
        delta = (std::max)(delta, RealScalar(mx / rfactorial));
      }
      const RealScalar P_norm = P.cwiseAbs().rowwise().sum().maxCoeff();
      if (mu * delta * P_norm < NumTraits<Scalar>::epsilon() * F_norm)  // series converged
        break;
    }
  }
  return F;
}

/** \brief Find cluster in \p clusters containing some value
 * \param[in] key Value to find
 * \returns Iterator to cluster containing \p key, or \c clusters.end() if no cluster in \p clusters
 * contains \p key.
 */
template <typename Index, typename ListOfClusters>
typename ListOfClusters::iterator matrix_function_find_cluster(Index key, ListOfClusters& clusters) {
  typename std::list<Index>::iterator j;
  for (typename ListOfClusters::iterator i = clusters.begin(); i != clusters.end(); ++i) {
    j = std::find(i->begin(), i->end(), key);
    if (j != i->end()) return i;
  }
  return clusters.end();
}

/** \brief Partition eigenvalues in clusters of ei'vals close to each other
 *
 * \param[in]  eivals    Eigenvalues
 * \param[out] clusters  Resulting partition of eigenvalues
 *
 * The partition satisfies the following two properties:
 * # Any eigenvalue in a certain cluster is at most matrix_function_separation() away from another eigenvalue
 *   in the same cluster.
 * # The distance between two eigenvalues in different clusters is more than matrix_function_separation().
 * The implementation follows Algorithm 4.1 in the paper of Davies and Higham.
 */
template <typename EivalsType, typename Cluster>
void matrix_function_partition_eigenvalues(const EivalsType& eivals, std::list<Cluster>& clusters) {
  typedef typename EivalsType::RealScalar RealScalar;
  for (Index i = 0; i < eivals.rows(); ++i) {
    // Find cluster containing i-th ei'val, adding a new cluster if necessary
    typename std::list<Cluster>::iterator qi = matrix_function_find_cluster(i, clusters);
    if (qi == clusters.end()) {
      Cluster l;
      l.push_back(i);
      clusters.push_back(l);
      qi = clusters.end();
      --qi;
    }

    // Look for other element to add to the set
    for (Index j = i + 1; j < eivals.rows(); ++j) {
      if (abs(eivals(j) - eivals(i)) <= RealScalar(matrix_function_separation) &&
          std::find(qi->begin(), qi->end(), j) == qi->end()) {
        typename std::list<Cluster>::iterator qj = matrix_function_find_cluster(j, clusters);
        if (qj == clusters.end()) {
          qi->push_back(j);
        } else {
          qi->insert(qi->end(), qj->begin(), qj->end());
          clusters.erase(qj);
        }
      }
    }
  }
}

/** \brief Compute size of each cluster given a partitioning */
template <typename ListOfClusters, typename Index>
void matrix_function_compute_cluster_size(const ListOfClusters& clusters, Matrix<Index, Dynamic, 1>& clusterSize) {
  const Index numClusters = static_cast<Index>(clusters.size());
  clusterSize.setZero(numClusters);
  Index clusterIndex = 0;
  for (typename ListOfClusters::const_iterator cluster = clusters.begin(); cluster != clusters.end(); ++cluster) {
    clusterSize[clusterIndex] = cluster->size();
    ++clusterIndex;
  }
}

/** \brief Compute start of each block using clusterSize */
template <typename VectorType>
void matrix_function_compute_block_start(const VectorType& clusterSize, VectorType& blockStart) {
  blockStart.resize(clusterSize.rows());
  blockStart(0) = 0;
  for (Index i = 1; i < clusterSize.rows(); i++) {
    blockStart(i) = blockStart(i - 1) + clusterSize(i - 1);
  }
}

/** \brief Compute mapping of eigenvalue indices to cluster indices */
template <typename EivalsType, typename ListOfClusters, typename VectorType>
void matrix_function_compute_map(const EivalsType& eivals, const ListOfClusters& clusters, VectorType& eivalToCluster) {
  eivalToCluster.resize(eivals.rows());
  Index clusterIndex = 0;
  for (typename ListOfClusters::const_iterator cluster = clusters.begin(); cluster != clusters.end(); ++cluster) {
    for (Index i = 0; i < eivals.rows(); ++i) {
      if (std::find(cluster->begin(), cluster->end(), i) != cluster->end()) {
        eivalToCluster[i] = clusterIndex;
      }
    }
    ++clusterIndex;
  }
}

/** \brief Compute permutation which groups ei'vals in same cluster together */
template <typename DynVectorType, typename VectorType>
void matrix_function_compute_permutation(const DynVectorType& blockStart, const DynVectorType& eivalToCluster,
                                         VectorType& permutation) {
  DynVectorType indexNextEntry = blockStart;
  permutation.resize(eivalToCluster.rows());
  for (Index i = 0; i < eivalToCluster.rows(); i++) {
    Index cluster = eivalToCluster[i];
    permutation[i] = indexNextEntry[cluster];
    ++indexNextEntry[cluster];
  }
}

/** \brief Permute Schur decomposition in U and T according to permutation */
template <typename VectorType, typename MatrixType>
void matrix_function_permute_schur(VectorType& permutation, MatrixType& U, MatrixType& T) {
  for (Index i = 0; i < permutation.rows() - 1; i++) {
    Index j;
    for (j = i; j < permutation.rows(); j++) {
      if (permutation(j) == i) break;
    }
    eigen_assert(permutation(j) == i);
    for (Index k = j - 1; k >= i; k--) {
      JacobiRotation<typename MatrixType::Scalar> rotation;
      rotation.makeGivens(T(k, k + 1), T(k + 1, k + 1) - T(k, k));
      T.applyOnTheLeft(k, k + 1, rotation.adjoint());
      T.applyOnTheRight(k, k + 1, rotation);
      U.applyOnTheRight(k, k + 1, rotation);
      std::swap(permutation.coeffRef(k), permutation.coeffRef(k + 1));
    }
  }
}

/** \brief Compute block diagonal part of matrix function.
 *
 * This routine computes the matrix function applied to the block diagonal part of \p T (which should be
 * upper triangular), with the blocking given by \p blockStart and \p clusterSize. The matrix function of
 * each diagonal block is computed by \p atomic. The off-diagonal parts of \p fT are set to zero.
 */
template <typename MatrixType, typename AtomicType, typename VectorType>
void matrix_function_compute_block_atomic(const MatrixType& T, AtomicType& atomic, const VectorType& blockStart,
                                          const VectorType& clusterSize, MatrixType& fT) {
  fT.setZero(T.rows(), T.cols());
  for (Index i = 0; i < clusterSize.rows(); ++i) {
    fT.block(blockStart(i), blockStart(i), clusterSize(i), clusterSize(i)) =
        atomic.compute(T.block(blockStart(i), blockStart(i), clusterSize(i), clusterSize(i)));
  }
}

/** \brief Solve a triangular Sylvester equation AX + XB = C
 *
 * \param[in]  A  the matrix A; should be square and upper triangular
 * \param[in]  B  the matrix B; should be square and upper triangular
 * \param[in]  C  the matrix C; should have correct size.
 *
 * \returns the solution X.
 *
 * If A is m-by-m and B is n-by-n, then both C and X are m-by-n.  The (i,j)-th component of the Sylvester
 * equation is
 * \f[
 *     \sum_{k=i}^m A_{ik} X_{kj} + \sum_{k=1}^j X_{ik} B_{kj} = C_{ij}.
 * \f]
 * This can be re-arranged to yield:
 * \f[
 *     X_{ij} = \frac{1}{A_{ii} + B_{jj}} \Bigl( C_{ij}
 *     - \sum_{k=i+1}^m A_{ik} X_{kj} - \sum_{k=1}^{j-1} X_{ik} B_{kj} \Bigr).
 * \f]
 * It is assumed that A and B are such that the numerator is never zero (otherwise the Sylvester equation
 * does not have a unique solution). In that case, these equations can be evaluated in the order
 * \f$ i=m,\ldots,1 \f$ and \f$ j=1,\ldots,n \f$.
 */
template <typename MatrixType>
MatrixType matrix_function_solve_triangular_sylvester(const MatrixType& A, const MatrixType& B, const MatrixType& C) {
  eigen_assert(A.rows() == A.cols());
  eigen_assert(A.isUpperTriangular());
  eigen_assert(B.rows() == B.cols());
  eigen_assert(B.isUpperTriangular());
  eigen_assert(C.rows() == A.rows());
  eigen_assert(C.cols() == B.rows());

  typedef typename MatrixType::Scalar Scalar;

  Index m = A.rows();
  Index n = B.rows();
  MatrixType X(m, n);

  for (Index i = m - 1; i >= 0; --i) {
    for (Index j = 0; j < n; ++j) {
      // Compute AX = \sum_{k=i+1}^m A_{ik} X_{kj}
      Scalar AX;
      if (i == m - 1) {
        AX = 0;
      } else {
        Matrix<Scalar, 1, 1> AXmatrix = A.row(i).tail(m - 1 - i) * X.col(j).tail(m - 1 - i);
        AX = AXmatrix(0, 0);
      }

      // Compute XB = \sum_{k=1}^{j-1} X_{ik} B_{kj}
      Scalar XB;
      if (j == 0) {
        XB = 0;
      } else {
        Matrix<Scalar, 1, 1> XBmatrix = X.row(i).head(j) * B.col(j).head(j);
        XB = XBmatrix(0, 0);
      }

      X(i, j) = (C(i, j) - AX - XB) / (A(i, i) + B(j, j));
    }
  }
  return X;
}

/** \brief Compute part of matrix function above block diagonal.
 *
 * This routine completes the computation of \p fT, denoting a matrix function applied to the triangular
 * matrix \p T. It assumes that the block diagonal part of \p fT has already been computed. The part below
 * the diagonal is zero, because \p T is upper triangular.
 */
template <typename MatrixType, typename VectorType>
void matrix_function_compute_above_diagonal(const MatrixType& T, const VectorType& blockStart,
                                            const VectorType& clusterSize, MatrixType& fT) {
  typedef internal::traits<MatrixType> Traits;
  typedef typename MatrixType::Scalar Scalar;
  static const int Options = MatrixType::Options;
  typedef Matrix<Scalar, Dynamic, Dynamic, Options, Traits::RowsAtCompileTime, Traits::ColsAtCompileTime> DynMatrixType;

  for (Index k = 1; k < clusterSize.rows(); k++) {
    for (Index i = 0; i < clusterSize.rows() - k; i++) {
      // compute (i, i+k) block
      DynMatrixType A = T.block(blockStart(i), blockStart(i), clusterSize(i), clusterSize(i));
      DynMatrixType B = -T.block(blockStart(i + k), blockStart(i + k), clusterSize(i + k), clusterSize(i + k));
      DynMatrixType C = fT.block(blockStart(i), blockStart(i), clusterSize(i), clusterSize(i)) *
                        T.block(blockStart(i), blockStart(i + k), clusterSize(i), clusterSize(i + k));
      C -= T.block(blockStart(i), blockStart(i + k), clusterSize(i), clusterSize(i + k)) *
           fT.block(blockStart(i + k), blockStart(i + k), clusterSize(i + k), clusterSize(i + k));
      for (Index m = i + 1; m < i + k; m++) {
        C += fT.block(blockStart(i), blockStart(m), clusterSize(i), clusterSize(m)) *
             T.block(blockStart(m), blockStart(i + k), clusterSize(m), clusterSize(i + k));
        C -= T.block(blockStart(i), blockStart(m), clusterSize(i), clusterSize(m)) *
             fT.block(blockStart(m), blockStart(i + k), clusterSize(m), clusterSize(i + k));
      }
      fT.block(blockStart(i), blockStart(i + k), clusterSize(i), clusterSize(i + k)) =
          matrix_function_solve_triangular_sylvester(A, B, C);
    }
  }
}

/** \ingroup MatrixFunctions_Module
 * \brief Class for computing matrix functions.
 * \tparam  MatrixType  type of the argument of the matrix function,
 *                      expected to be an instantiation of the Matrix class template.
 * \tparam  AtomicType  type for computing matrix function of atomic blocks.
 * \tparam  IsComplex   used internally to select correct specialization.
 *
 * This class implements the Schur-Parlett algorithm for computing matrix functions. The spectrum of the
 * matrix is divided into clusters of eigenvalues that lie close together. This class delegates the
 * computation of the matrix function on every block corresponding to these clusters to an object of type
 * \p AtomicType and uses these results to compute the matrix function of the whole matrix. The class
 * \p AtomicType should have a \p compute() member function for computing the matrix function of a block.
 *
 * \sa class MatrixFunctionAtomic, class MatrixLogarithmAtomic
 */
template <typename MatrixType, int IsComplex = NumTraits<typename internal::traits<MatrixType>::Scalar>::IsComplex>
struct matrix_function_compute {
  /** \brief Compute the matrix function.
   *
   * \param[in]  A       argument of matrix function, should be a square matrix.
   * \param[in]  atomic  class for computing matrix function of atomic blocks.
   * \param[out] result  the function \p f applied to \p A, as
   * specified in the constructor.
   *
   * See MatrixBase::matrixFunction() for details on how this computation
   * is implemented.
   */
  template <typename AtomicType, typename ResultType>
  static void run(const MatrixType& A, AtomicType& atomic, ResultType& result);
};

/** \internal \ingroup MatrixFunctions_Module
 * \brief Partial specialization of MatrixFunction for real matrices
 *
 * This converts the real matrix to a complex matrix, compute the matrix function of that matrix, and then
 * converts the result back to a real matrix.
 */
template <typename MatrixType>
struct matrix_function_compute<MatrixType, 0> {
  template <typename MatA, typename AtomicType, typename ResultType>
  static void run(const MatA& A, AtomicType& atomic, ResultType& result) {
    typedef internal::traits<MatrixType> Traits;
    typedef typename Traits::Scalar Scalar;
    static const int Rows = Traits::RowsAtCompileTime, Cols = Traits::ColsAtCompileTime;
    static const int MaxRows = Traits::MaxRowsAtCompileTime, MaxCols = Traits::MaxColsAtCompileTime;

    typedef internal::make_complex_t<Scalar> ComplexScalar;
    typedef Matrix<ComplexScalar, Rows, Cols, 0, MaxRows, MaxCols> ComplexMatrix;

    ComplexMatrix CA = A.template cast<ComplexScalar>();
    ComplexMatrix Cresult;
    matrix_function_compute<ComplexMatrix>::run(CA, atomic, Cresult);
    result = Cresult.real();
  }
};

/** \internal \ingroup MatrixFunctions_Module
 * \brief Partial specialization of MatrixFunction for complex matrices
 */
template <typename MatrixType>
struct matrix_function_compute<MatrixType, 1> {
  template <typename MatA, typename AtomicType, typename ResultType>
  static void run(const MatA& A, AtomicType& atomic, ResultType& result) {
    typedef internal::traits<MatrixType> Traits;

    // compute Schur decomposition of A
    const ComplexSchur<MatrixType> schurOfA(A);
    eigen_assert(schurOfA.info() == Success);
    MatrixType T = schurOfA.matrixT();
    MatrixType U = schurOfA.matrixU();

    // partition eigenvalues into clusters of ei'vals "close" to each other
    std::list<std::list<Index> > clusters;
    matrix_function_partition_eigenvalues(T.diagonal(), clusters);

    // compute size of each cluster
    Matrix<Index, Dynamic, 1> clusterSize;
    matrix_function_compute_cluster_size(clusters, clusterSize);

    // blockStart[i] is row index at which block corresponding to i-th cluster starts
    Matrix<Index, Dynamic, 1> blockStart;
    matrix_function_compute_block_start(clusterSize, blockStart);

    // compute map so that eivalToCluster[i] = j means that i-th ei'val is in j-th cluster
    Matrix<Index, Dynamic, 1> eivalToCluster;
    matrix_function_compute_map(T.diagonal(), clusters, eivalToCluster);

    // compute permutation which groups ei'vals in same cluster together
    Matrix<Index, Traits::RowsAtCompileTime, 1> permutation;
    matrix_function_compute_permutation(blockStart, eivalToCluster, permutation);

    // permute Schur decomposition
    matrix_function_permute_schur(permutation, U, T);

    // compute result
    MatrixType fT;  // matrix function applied to T
    matrix_function_compute_block_atomic(T, atomic, blockStart, clusterSize, fT);
    matrix_function_compute_above_diagonal(T, blockStart, clusterSize, fT);
    result = U * (fT.template triangularView<Upper>() * U.adjoint());
  }
};

}  // end of namespace internal

/** \ingroup MatrixFunctions_Module
 *
 * \brief Proxy for the matrix function of some matrix (expression).
 *
 * \tparam Derived  Type of the argument to the matrix function.
 *
 * This class holds the argument to the matrix function until it is assigned or evaluated for some other
 * reason (so the argument should not be changed in the meantime). It is the return type of
 * MatrixBase::matrixFunction() and related functions and most of the time this is the only way it is used.
 */
template <typename Derived>
class MatrixFunctionReturnValue : public ReturnByValue<MatrixFunctionReturnValue<Derived> > {
 public:
  typedef typename Derived::Scalar Scalar;
  typedef typename internal::stem_function<Scalar>::type StemFunction;

 protected:
  typedef typename internal::ref_selector<Derived>::type DerivedNested;

 public:
  /** \brief Constructor.
   *
   * \param[in] A  %Matrix (expression) forming the argument of the matrix function.
   * \param[in] f  Stem function for matrix function under consideration.
   */
  MatrixFunctionReturnValue(const Derived& A, StemFunction f) : m_A(A), m_f(f) {}

  /** \brief Compute the matrix function.
   *
   * \param[out] result \p f applied to \p A, where \p f and \p A are as in the constructor.
   */
  template <typename ResultType>
  inline void evalTo(ResultType& result) const {
    typedef typename internal::nested_eval<Derived, 10>::type NestedEvalType;
    typedef internal::remove_all_t<NestedEvalType> NestedEvalTypeClean;
    typedef internal::traits<NestedEvalTypeClean> Traits;
    typedef internal::make_complex_t<Scalar> ComplexScalar;
    typedef Matrix<ComplexScalar, Dynamic, Dynamic, 0, Traits::RowsAtCompileTime, Traits::ColsAtCompileTime>
        DynMatrixType;

    typedef internal::MatrixFunctionAtomic<DynMatrixType> AtomicType;
    AtomicType atomic(m_f);

    internal::matrix_function_compute<typename NestedEvalTypeClean::PlainObject>::run(m_A, atomic, result);
  }

  Index rows() const { return m_A.rows(); }
  Index cols() const { return m_A.cols(); }

 private:
  DerivedNested m_A;
  StemFunction* m_f;
};

namespace internal {
template <typename Derived>
struct traits<MatrixFunctionReturnValue<Derived> > {
  typedef typename Derived::PlainObject ReturnType;
};
}  // namespace internal

/********** MatrixBase methods **********/

template <typename Derived>
const MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::matrixFunction(
    typename internal::stem_function<typename internal::traits<Derived>::Scalar>::type f) const {
  eigen_assert(rows() == cols());
  return MatrixFunctionReturnValue<Derived>(derived(), f);
}

template <typename Derived>
const MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::sin() const {
  eigen_assert(rows() == cols());
  typedef typename internal::stem_function<Scalar>::ComplexScalar ComplexScalar;
  return MatrixFunctionReturnValue<Derived>(derived(), internal::stem_function_sin<ComplexScalar>);
}

template <typename Derived>
const MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::cos() const {
  eigen_assert(rows() == cols());
  typedef typename internal::stem_function<Scalar>::ComplexScalar ComplexScalar;
  return MatrixFunctionReturnValue<Derived>(derived(), internal::stem_function_cos<ComplexScalar>);
}

template <typename Derived>
const MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::sinh() const {
  eigen_assert(rows() == cols());
  typedef typename internal::stem_function<Scalar>::ComplexScalar ComplexScalar;
  return MatrixFunctionReturnValue<Derived>(derived(), internal::stem_function_sinh<ComplexScalar>);
}

template <typename Derived>
const MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::cosh() const {
  eigen_assert(rows() == cols());
  typedef typename internal::stem_function<Scalar>::ComplexScalar ComplexScalar;
  return MatrixFunctionReturnValue<Derived>(derived(), internal::stem_function_cosh<ComplexScalar>);
}

}  // end namespace Eigen

#endif  // EIGEN_MATRIX_FUNCTION_H
