code: def gmres(
      A,
      b,
      x0=None,
      tol=1e-5,
      restart=None,
      maxiter=None,
      M=None,
      callback=None,
      restrt=None,
      atol=None,
  ):
      """
      Use Generalized Minimal RESidual iteration to solve ``Ax = b``.
  
      Parameters
      ----------
      A : {sparse matrix, dense matrix, LinearOperator}
          The real or complex N-by-N matrix of the linear system.
      b : {array, matrix}
          Right hand side of the linear system. Has shape (N,) or (N,1).
  
      Returns
      -------
      x : {array, matrix}
          The converged solution.
      info : int
          Provides convergence information:
            * 0  : successful exit
            * >0 : convergence to tolerance not achieved, number of iterations
            * <0 : illegal input or breakdown
  
      Other parameters
      ----------------
      x0 : {array, matrix}
          Starting guess for the solution (a vector of zeros by default).
      tol, atol : float, optional
          Tolerances for convergence, ``norm(residual) <= max(tol*norm(b), atol)``.
          The default for ``atol`` is ``'legacy'``, which emulates
          a different legacy behavior.
  
          .. warning::
  
             The default value for `atol` will be changed in a future release.
             For future compatibility, specify `atol` explicitly.
      restart : int, optional
          Number of iterations between restarts. Larger values increase
          iteration cost, but may be necessary for convergence.
          Default is 20.
      maxiter : int, optional
          Maximum number of iterations (restart cycles).  Iteration will stop
          after maxiter steps even if the specified tolerance has not been
          achieved.
      M : {sparse matrix, dense matrix, LinearOperator}
          Inverse of the preconditioner of A.  M should approximate the
          inverse of A and be easy to solve for (see Notes).  Effective
          preconditioning dramatically improves the rate of convergence,
          which implies that fewer iterations are needed to reach a given
          error tolerance.  By default, no preconditioner is used.
      callback : function
          User-supplied function to call after each iteration.  It is called
          as callback(rk), where rk is the current residual vector.
      restrt : int, optional
          DEPRECATED - use `restart` instead.
  
      See Also
      --------
      LinearOperator
  
      Notes
      -----
      A preconditioner, P, is chosen such that P is close to A but easy to solve
      for. The preconditioner parameter required by this routine is
      ``M = P^-1``. The inverse should preferably not be calculated
      explicitly.  Rather, use the following template to produce M::
  
        # Construct a linear operator that computes P^-1 * x.
        import scipy.sparse.linalg as spla
        M_x = lambda x: spla.spsolve(P, x)
        M = spla.LinearOperator((n, n), M_x)
  
      Examples
      --------
      >>> from scipy.sparse import csc_matrix
      >>> from scipy.sparse.linalg import gmres
      >>> A = csc_matrix([[3, 2, 0], [1, -1, 0], [0, 5, 1]], dtype=float)
      >>> b = np.array([2, 4, -1], dtype=float)
      >>> x, exitCode = gmres(A, b)
      >>> print(exitCode)            # 0 indicates successful convergence
      0
      >>> np.allclose(A.dot(x), b)
      True
      """
  
      # Change 'restrt' keyword to 'restart'
      if restrt is None:
          restrt = restart
      elif restart is not None:
          raise ValueError(
              "Cannot specify both restart and restrt keywords. "
              "Preferably use 'restart' only."
          )
  
      A, M, x, b, postprocess = make_system(A, M, x0, b)
  
      n = len(b)
      if maxiter is None:
          maxiter = n * 10
  
      if restrt is None:
          restrt = 20
      restrt = min(restrt, n)
  
      matvec = A.matvec
      psolve = M.matvec
      ltr = _type_conv[x.dtype.char]
      revcom = getattr(_iterative, ltr + "gmresrevcom")
  
      bnrm2 = np.linalg.norm(b)
      Mb_nrm2 = np.linalg.norm(psolve(b))
      get_residual = lambda: np.linalg.norm(matvec(x) - b)
      atol = _get_atol(tol, atol, bnrm2, get_residual, "gmres")
      if atol == "exit":
          return postprocess(x), 0
  
      if bnrm2 == 0:
          return postprocess(b), 0
  
      # Tolerance passed to GMRESREVCOM applies to the inner iteration
      # and deals with the left-preconditioned residual.
      ptol_max_factor = 1.0
      ptol = Mb_nrm2 * min(ptol_max_factor, atol / bnrm2)
      resid = np.nan
      presid = np.nan
      ndx1 = 1
      ndx2 = -1
      # Use _aligned_zeros to work around a f2py bug in Numpy 1.9.1
      work = _aligned_zeros((6 + restrt) * n, dtype=x.dtype)
      work2 = _aligned_zeros(
          (restrt + 1) * (2 * restrt + 2), dtype=x.dtype
      )
      ijob = 1
      info = 0
      ftflag = True
      iter_ = maxiter
      old_ijob = ijob
      first_pass = True
      resid_ready = False
      iter_num = 1
      while True:
          (
              x,
              iter_,
              presid,
              info,
              ndx1,
              ndx2,
              sclr1,
              sclr2,
              ijob,
          ) = revcom(
              b,
              x,
              restrt,
              work,
              work2,
              iter_,
              presid,
              info,
              ndx1,
              ndx2,
              ijob,
              ptol,
          )
          slice1 = slice(ndx1 - 1, ndx1 - 1 + n)
          slice2 = slice(ndx2 - 1, ndx2 - 1 + n)
          if ijob == -1:  # gmres success, update last residual
              if resid_ready and callback is not None:
                  callback(presid / bnrm2)
                  resid_ready = False
              break
          elif ijob == 1:
              work[slice2] *= sclr2
              work[slice2] += sclr1 * matvec(x)
          elif ijob == 2:
              work[slice1] = psolve(work[slice2])
              if not first_pass and old_ijob == 3:
                  resid_ready = True
  
              first_pass = False
          elif ijob == 3:
              work[slice2] *= sclr2
              work[slice2] += sclr1 * matvec(work[slice1])
              if resid_ready and callback is not None:
                  callback(presid / bnrm2)
                  resid_ready = False
                  iter_num = iter_num + 1
  
          elif ijob == 4:
              if ftflag:
                  info = -1
                  ftflag = False
              resid, info = _stoptest(work[slice1], atol)
  
              # Inner loop tolerance control
              if info or presid > ptol:
                  ptol_max_factor = min(1.0, 1.5 * ptol_max_factor)
              else:
                  # Inner loop tolerance OK, but outer loop not.
                  ptol_max_factor = max(1e-16, 0.25 * ptol_max_factor)
  
              if resid != 0:
                  ptol = presid * min(ptol_max_factor, atol / resid)
              else:
                  ptol = presid * ptol_max_factor
  
          old_ijob = ijob
          ijob = 2
  
          if iter_num > maxiter:
              info = maxiter
              break
  
      if info >= 0 and not (resid <= atol):
          # info isn't set appropriately otherwise
          info = maxiter
  
      return postprocess(x), info
  
file_path: catboost/contrib/python/scipy/py2/scipy/sparse/linalg/isolve/iterative.py
imports: from __future__ import division, print_function, absolute_import
  import warnings
  import numpy
  from .None import _iterative
  from scipy.sparse.linalg.interface import LinearOperator
  from .utils import make_system
  from scipy._lib._util import _aligned_zeros
  from scipy._lib._threadsafety import non_reentrant
label_desc: Use image node_id 8 for calling a global function with example usage: gmres(A, b, x0, tol, restart, maxiter, M, callback, restrt, atol) and returns: postprocess,  info, postprocess,  int, postprocess,  int