// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2012 Giacomo Po <gpo@ucla.edu>
// Copyright (C) 2011-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2018 David Hyde <dabh@stanford.edu>
//
// 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_MINRES_H
#define EIGEN_MINRES_H

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

namespace Eigen {

namespace internal {

/** \internal Low-level MINRES algorithm
 * \param mat The matrix A
 * \param rhs The right hand side vector b
 * \param x On input and initial solution, on output the computed solution.
 * \param precond A right preconditioner being able to efficiently solve for an
 *                approximation of Ax=b (regardless of b)
 * \param iters On input the max number of iteration, on output the number of performed iterations.
 * \param tol_error On input the tolerance error, on output an estimation of the relative error.
 */
template <typename MatrixType, typename Rhs, typename Dest, typename Preconditioner>
EIGEN_DONT_INLINE void minres(const MatrixType& mat, const Rhs& rhs, Dest& x, const Preconditioner& precond,
                              Index& iters, typename Dest::RealScalar& tol_error) {
  using std::sqrt;
  using RealScalar = typename Dest::RealScalar;
  using Scalar = typename Dest::Scalar;
  using VectorType = Matrix<Scalar, Dynamic, 1>;

  // Check for zero rhs
  const RealScalar rhsNorm(rhs.stableNorm());
  if (rhsNorm == 0) {
    x.setZero();
    iters = 0;
    tol_error = 0;
    return;
  }

  // initialize
  const Index maxIters(iters);                      // initialize maxIters to iters
  const Index N(mat.cols());                        // the size of the matrix
  const RealScalar threshold(tol_error * rhsNorm);  // convergence threshold (compared to residualNorm)

  // Initialize preconditioned Lanczos
  VectorType v_old(N);                // will be initialized inside loop
  VectorType v(VectorType::Zero(N));  // initialize v
  VectorType v_new(rhs - mat * x);    // initialize v_new
  RealScalar residualNorm(v_new.stableNorm());
  if (residualNorm == 0 || residualNorm < threshold) {
    iters = 0;
    tol_error = residualNorm / rhsNorm;
    return;
  }

  // Keep the quadratic Lanczos terms representable for very small or large residuals.
  const RealScalar residualScale = internal::iterative_solver_scaling_factor(residualNorm);
  v_new /= residualScale;
  VectorType w(N);                         // will be initialized inside loop
  VectorType w_new(precond.solve(v_new));  // initialize w_new
  RealScalar beta_new2(v_new.dot(w_new));
  eigen_assert(beta_new2 >= 0.0 && "PRECONDITIONER IS NOT POSITIVE DEFINITE");
  RealScalar beta_new(sqrt(beta_new2));
  const RealScalar beta_one(beta_new);
  // Initialize other variables
  RealScalar c(1.0);  // the cosine of the Givens rotation
  RealScalar c_old(1.0);
  RealScalar s(0.0);                      // the sine of the Givens rotation
  RealScalar s_old(0.0);                  // the sine of the Givens rotation
  VectorType p_oold(N);                   // will be initialized in loop
  VectorType p_old(VectorType::Zero(N));  // initialize p_old=0
  VectorType p(p_old);                    // initialize p=0
  RealScalar eta(1.0);

  iters = 0;  // reset iters
  while (iters < maxIters) {
    // Preconditioned Lanczos
    /* Note that there are 4 variants on the Lanczos algorithm. These are
     * described in Paige, C. C. (1972). Computational variants of
     * the Lanczos method for the eigenproblem. IMA Journal of Applied
     * Mathematics, 10(3), 373-381. The current implementation corresponds
     * to the case A(2,7) in the paper. It also corresponds to
     * algorithm 6.14 in Y. Saad, Iterative Methods for Sparse Linear
     * Systems, 2003 p.173. For the preconditioned version see
     * A. Greenbaum, Iterative Methods for Solving Linear Systems, SIAM (1987).
     */
    const RealScalar beta(beta_new);
    v_old = v;          // update: at first time step, this makes v_old = 0 so value of beta doesn't matter
    v_new /= beta_new;  // overwrite v_new for next iteration
    w_new /= beta_new;  // overwrite w_new for next iteration
    v = v_new;          // update
    w = w_new;          // update
    v_new.noalias() = mat * w - beta * v_old;  // compute v_new
    const RealScalar alpha = v_new.dot(w);
    v_new -= alpha * v;            // overwrite v_new
    w_new = precond.solve(v_new);  // overwrite w_new
    beta_new2 = v_new.dot(w_new);  // compute beta_new
    eigen_assert(beta_new2 >= 0.0 && "PRECONDITIONER IS NOT POSITIVE DEFINITE");
    beta_new = sqrt(beta_new2);  // compute beta_new

    // Givens rotation
    const RealScalar r2 = s * alpha + c * c_old * beta;  // s, s_old, c and c_old are still from previous iteration
    const RealScalar r3 = s_old * beta;                  // s, s_old, c and c_old are still from previous iteration
    const RealScalar r1_hat = c * alpha - c_old * s * beta;
    const RealScalar r1 = numext::hypot(r1_hat, beta_new);
    c_old = c;          // store for next iteration
    s_old = s;          // store for next iteration
    c = r1_hat / r1;    // new cosine
    s = beta_new / r1;  // new sine

    // Update solution
    p_oold = p_old;
    p_old = p;
    p = (w - r2 * p_old - r3 * p_oold) / r1;
    x += (residualScale * beta_one * c * eta) * p;

    /* Update the estimated residual norm. Note that this is the estimated
    residual; the real residual |Ax-b| may be slightly larger. */
    residualNorm *= numext::abs(s);

    if (residualNorm < threshold) {
      break;
    }

    eta = -s * eta;  // update eta
    iters++;         // increment iteration number (for output purposes)
  }

  /* Compute error. Note that this is the estimated error. The real
   error |Ax-b|/|b| may be slightly larger */
  tol_error = residualNorm / rhsNorm;
}

}  // namespace internal

template <typename MatrixType_, int UpLo_ = Lower, typename Preconditioner_ = IdentityPreconditioner>
class MINRES;

namespace internal {

template <typename MatrixType_, int UpLo_, typename Preconditioner_>
struct traits<MINRES<MatrixType_, UpLo_, Preconditioner_> > {
  using MatrixType = MatrixType_;
  using Preconditioner = Preconditioner_;
};

}  // namespace internal

/** \ingroup IterativeLinearSolvers_Module
 * \brief A minimal residual solver for sparse symmetric problems
 *
 * This class allows to solve for A.x = b sparse linear problems using the MINRES algorithm
 * of Paige and Saunders (1975). The sparse matrix A must be symmetric (possibly indefinite).
 * The vectors x and b can be either dense or sparse.
 *
 * \tparam MatrixType_ the type of the sparse matrix A, can be a dense or a sparse matrix.
 * \tparam UpLo_ the triangular part that will be used for the computations. It can be Lower,
 *               Upper, or Lower|Upper in which the full matrix entries will be considered. Default is Lower.
 * \tparam Preconditioner_ the type of the preconditioner. Default is IdentityPreconditioner
 *
 * The maximal number of iterations and tolerance value can be controlled via the setMaxIterations()
 * and setTolerance() methods. The defaults are twice the number of columns of the matrix for the maximal
 * number of iterations and NumTraits<Scalar>::epsilon() for the tolerance.
 *
 * This class can be used as the direct solver classes. Here is a typical usage example:
 * \code
 * int n = 10000;
 * VectorXd x(n), b(n);
 * SparseMatrix<double> A(n,n);
 * // fill A and b
 * MINRES<SparseMatrix<double> > mr;
 * mr.compute(A);
 * x = mr.solve(b);
 * std::cout << "#iterations:     " << mr.iterations() << std::endl;
 * std::cout << "estimated error: " << mr.error()      << std::endl;
 * // update b, and solve again
 * x = mr.solve(b);
 * \endcode
 *
 * By default the iterations start with x=0 as an initial guess of the solution.
 * One can control the start using the solveWithGuess() method.
 *
 * MINRES can also be used in a matrix-free context, see the following \link MatrixfreeSolverExample example \endlink.
 *
 * \sa class ConjugateGradient, BiCGSTAB, SimplicialCholesky, DiagonalPreconditioner, IdentityPreconditioner
 */
template <typename MatrixType_, int UpLo_, typename Preconditioner_>
class MINRES : public IterativeSolverBase<MINRES<MatrixType_, UpLo_, Preconditioner_> > {
 protected:
  using Base = IterativeSolverBase<MINRES>;
  using Base::m_error;
  using Base::m_info;
  using Base::m_isInitialized;
  using Base::m_iterations;
  using Base::matrix;

 public:
  using Base::_solve_impl;
  using MatrixType = MatrixType_;
  using Scalar = typename MatrixType::Scalar;
  using RealScalar = typename MatrixType::RealScalar;
  using Preconditioner = Preconditioner_;

  enum { UpLo = UpLo_ };

 public:
  /** Default constructor. */
  MINRES() : Base() {}

  /** Initialize the solver with matrix \a A for further \c Ax=b solving.
   *
   * This constructor is a shortcut for the default constructor followed
   * by a call to compute().
   *
   * \warning this class stores a reference to the matrix A as well as some
   * precomputed values that depend on it. Therefore, if \a A is changed
   * this class becomes invalid. Call compute() to update it with the new
   * matrix A, or modify a copy of A.
   */
  template <typename MatrixDerived>
  explicit MINRES(const EigenBase<MatrixDerived>& A) : Base(A.derived()) {}

  /** \internal */
  template <typename Rhs, typename Dest>
  void _solve_vector_with_guess_impl(const Rhs& b, Dest& x) const {
    using MatrixWrapper = typename Base::MatrixWrapper;
    using ActualMatrixType = typename Base::ActualMatrixType;
    enum {
      TransposeInput = (!MatrixWrapper::MatrixFree) && (UpLo == (Lower | Upper)) && (!MatrixType::IsRowMajor) &&
                       (!NumTraits<Scalar>::IsComplex)
    };
    using RowMajorWrapper =
        std::conditional_t<TransposeInput, Transpose<const ActualMatrixType>, ActualMatrixType const&>;
    EIGEN_STATIC_ASSERT(internal::check_implication(MatrixWrapper::MatrixFree, UpLo == (Lower | Upper)),
                        MATRIX_FREE_CONJUGATE_GRADIENT_IS_COMPATIBLE_WITH_UPPER_UNION_LOWER_MODE_ONLY);
    using SelfAdjointWrapper =
        std::conditional_t<UpLo == (Lower | Upper), RowMajorWrapper,
                           typename MatrixWrapper::template ConstSelfAdjointViewReturnType<UpLo>::Type>;

    m_iterations = Base::maxIterations();
    m_error = Base::m_tolerance;
    RowMajorWrapper row_mat(matrix());
    internal::minres(SelfAdjointWrapper(row_mat), b, x, Base::m_preconditioner, m_iterations, m_error);
    m_info = m_error <= Base::m_tolerance ? Success : NoConvergence;
  }

 protected:
};

}  // end namespace Eigen

#endif  // EIGEN_MINRES_H
