// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2011-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@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_BICGSTAB_H
#define EIGEN_BICGSTAB_H

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

namespace Eigen {

namespace internal {

/** \internal Low-level bi conjugate gradient stabilized 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 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.
 * \return false in the case of numerical issue, for example a break down of BiCGSTAB.
 */
template <typename MatrixType, typename Rhs, typename Dest, typename Preconditioner>
bool bicgstab(const MatrixType& mat, const Rhs& rhs, Dest& x, const Preconditioner& precond, Index& iters,
              typename Dest::RealScalar& tol_error) {
  using RealScalar = typename Dest::RealScalar;
  using Scalar = typename Dest::Scalar;
  using VectorType = Matrix<Scalar, Dynamic, 1>;
  Index maxIters = iters;

  Index n = mat.cols();
  VectorType r = rhs - mat * x;
  VectorType r0 = r;

  RealScalar r0_norm = r0.stableNorm();
  RealScalar r_norm = r0_norm;
  RealScalar rhs_norm = rhs.stableNorm();
  if (rhs_norm == 0) {
    x.setZero();
    iters = 0;
    tol_error = 0;
    return true;
  }

  RealScalar tol = tol_error * rhs_norm;

  Scalar rho(1);
  Scalar alpha(0);
  Scalar w(1);

  VectorType v = VectorType::Zero(n), p = VectorType::Zero(n);
  VectorType y(n), z(n);

  VectorType s(n), t(n);

  RealScalar eps = NumTraits<Scalar>::epsilon();
  Index i = 0;
  Index restarts = 0;

  while (r_norm > tol && i < maxIters) {
    Scalar rho_old = rho;
    rho = r0.dot(r);
    if (Eigen::numext::abs(rho) / Eigen::numext::maxi(r0_norm, r_norm) < eps * Eigen::numext::mini(r0_norm, r_norm)) {
      // The new residual vector became too orthogonal to the arbitrarily chosen direction r0
      // Let's restart with a new r0:
      r.noalias() = rhs - mat * x;
      r0 = r;
      rho = r.squaredNorm();
      r0_norm = r.stableNorm();
      alpha = Scalar(0);
      w = Scalar(1);
      if (restarts++ == 0) i = 0;
    }
    Scalar beta = (rho / rho_old) * (alpha / w);
    p = r + beta * (p - w * v);

    y = precond.solve(p);

    v.noalias() = mat * y;
    Scalar theta = r0.dot(v);
    // For small angles ∠(r0, v) < eps, random restart.
    RealScalar v_norm = v.stableNorm();
    if (Eigen::numext::abs(theta) / Eigen::numext::maxi(r0_norm, v_norm) < eps * Eigen::numext::mini(r0_norm, v_norm)) {
      r.noalias() = rhs - mat * x;
      r0.setRandom();
      r0_norm = r0.stableNorm();
      rho = Scalar(1);
      alpha = Scalar(0);
      w = Scalar(1);
      if (restarts++ == 0) i = 0;
      continue;
    }
    alpha = rho / theta;
    s = r - alpha * v;

    z = precond.solve(s);
    t.noalias() = mat * z;

    RealScalar tmp = t.squaredNorm();
    if (tmp > RealScalar(0)) {
      w = t.dot(s) / tmp;
    } else {
      w = Scalar(0);
    }
    x += alpha * y + w * z;
    r = s - w * t;
    r_norm = r.stableNorm();
    ++i;
  }

  tol_error = r_norm / rhs_norm;
  iters = i;
  return true;
}

}  // namespace internal

template <typename MatrixType_, typename Preconditioner_ = DiagonalPreconditioner<typename MatrixType_::Scalar> >
class BiCGSTAB;

namespace internal {

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

}  // namespace internal

/** \ingroup IterativeLinearSolvers_Module
 * \brief A bi conjugate gradient stabilized solver for sparse square problems
 *
 * This class allows to solve for A.x = b sparse linear problems using a bi conjugate gradient
 * stabilized algorithm. 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 Preconditioner_ the type of the preconditioner. Default is DiagonalPreconditioner
 *
 * \implsparsesolverconcept
 *
 * 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.
 *
 * The tolerance corresponds to the relative residual error: |Ax-b|/|b|
 *
 * \b Performance: when using sparse matrices, best performance is achieved for a row-major sparse matrix format.
 * Moreover, in this case multi-threading can be exploited if the user code is compiled with OpenMP enabled.
 * See \ref TopicMultiThreading for details.
 *
 * This class can be used as the direct solver classes. Here is a typical usage example:
 * \include BiCGSTAB_simple.cpp
 *
 * By default the iterations start with x=0 as an initial guess of the solution.
 * One can control the start using the solveWithGuess() method.
 *
 * BiCGSTAB can also be used in a matrix-free context, see the following \link MatrixfreeSolverExample example \endlink.
 *
 * \sa class SimplicialCholesky, DiagonalPreconditioner, IdentityPreconditioner
 */
template <typename MatrixType_, typename Preconditioner_>
class BiCGSTAB : public IterativeSolverBase<BiCGSTAB<MatrixType_, Preconditioner_> > {
 protected:
  using Base = IterativeSolverBase<BiCGSTAB>;
  using Base::m_error;
  using Base::m_info;
  using Base::m_isInitialized;
  using Base::m_iterations;
  using Base::matrix;

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

 public:
  /** Default constructor. */
  BiCGSTAB() : 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 BiCGSTAB(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 {
    m_iterations = Base::maxIterations();
    m_error = Base::m_tolerance;

    bool ret = internal::bicgstab(matrix(), b, x, Base::m_preconditioner, m_iterations, m_error);

    m_info = (!ret) ? NumericalIssue : m_error <= Base::m_tolerance ? Success : NoConvergence;
  }
};

}  // end namespace Eigen

#endif  // EIGEN_BICGSTAB_H
