// 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/.

#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, 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 m_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 in clustered of eigenvalues that lies 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 std::complex<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 std::complex<typename NumTraits<Scalar>::Real> 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:
  const 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
