code: def qmr(
      A,
      b,
      x0=None,
      tol=1e-5,
      maxiter=None,
      M1=None,
      M2=None,
      callback=None,
      atol=None,
  ):
      """Use Quasi-Minimal Residual iteration to solve ``Ax = b``.
  
      Parameters
      ----------
      A : {sparse matrix, dense matrix, LinearOperator}
          The real-valued N-by-N matrix of the linear system.
          It is required that the linear operator can produce
          ``Ax`` and ``A^T x``.
      b : {array, matrix}
          Right hand side of the linear system. Has shape (N,) or (N,1).
  
      Returns
      -------
      x : {array, matrix}
          The converged solution.
      info : integer
          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.
      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.
      maxiter : integer
          Maximum number of iterations.  Iteration will stop after maxiter
          steps even if the specified tolerance has not been achieved.
      M1 : {sparse matrix, dense matrix, LinearOperator}
          Left preconditioner for A.
      M2 : {sparse matrix, dense matrix, LinearOperator}
          Right preconditioner for A. Used together with the left
          preconditioner M1.  The matrix M1*A*M2 should have better
          conditioned than A alone.
      callback : function
          User-supplied function to call after each iteration.  It is called
          as callback(xk), where xk is the current solution vector.
  
      See Also
      --------
      LinearOperator
  
      Examples
      --------
      >>> from scipy.sparse import csc_matrix
      >>> from scipy.sparse.linalg import qmr
      >>> A = csc_matrix([[3, 2, 0], [1, -1, 0], [0, 5, 1]], dtype=float)
      >>> b = np.array([2, 4, -1], dtype=float)
      >>> x, exitCode = qmr(A, b)
      >>> print(exitCode)            # 0 indicates successful convergence
      0
      >>> np.allclose(A.dot(x), b)
      True
      """
      A_ = A
      A, M, x, b, postprocess = make_system(A, None, x0, b)
  
      if M1 is None and M2 is None:
          if hasattr(A_, "psolve"):
  
              def left_psolve(b):
                  return A_.psolve(b, "left")
  
              def right_psolve(b):
                  return A_.psolve(b, "right")
  
              def left_rpsolve(b):
                  return A_.rpsolve(b, "left")
  
              def right_rpsolve(b):
                  return A_.rpsolve(b, "right")
  
              M1 = LinearOperator(
                  A.shape, matvec=left_psolve, rmatvec=left_rpsolve
              )
              M2 = LinearOperator(
                  A.shape, matvec=right_psolve, rmatvec=right_rpsolve
              )
          else:
  
              def id(b):
                  return b
  
              M1 = LinearOperator(A.shape, matvec=id, rmatvec=id)
              M2 = LinearOperator(A.shape, matvec=id, rmatvec=id)
  
      n = len(b)
      if maxiter is None:
          maxiter = n * 10
  
      ltr = _type_conv[x.dtype.char]
      revcom = getattr(_iterative, ltr + "qmrrevcom")
  
      get_residual = lambda: np.linalg.norm(A.matvec(x) - b)
      atol = _get_atol(
          tol, atol, np.linalg.norm(b), get_residual, "qmr"
      )
      if atol == "exit":
          return postprocess(x), 0
  
      resid = atol
      ndx1 = 1
      ndx2 = -1
      # Use _aligned_zeros to work around a f2py bug in Numpy 1.9.1
      work = _aligned_zeros(11 * n, x.dtype)
      ijob = 1
      info = 0
      ftflag = True
      iter_ = maxiter
      while True:
          olditer = iter_
          (
              x,
              iter_,
              resid,
              info,
              ndx1,
              ndx2,
              sclr1,
              sclr2,
              ijob,
          ) = revcom(b, x, work, iter_, resid, info, ndx1, ndx2, ijob)
          if callback is not None and iter_ > olditer:
              callback(x)
          slice1 = slice(ndx1 - 1, ndx1 - 1 + n)
          slice2 = slice(ndx2 - 1, ndx2 - 1 + n)
          if ijob == -1:
              if callback is not None:
                  callback(x)
              break
          elif ijob == 1:
              work[slice2] *= sclr2
              work[slice2] += sclr1 * A.matvec(work[slice1])
          elif ijob == 2:
              work[slice2] *= sclr2
              work[slice2] += sclr1 * A.rmatvec(work[slice1])
          elif ijob == 3:
              work[slice1] = M1.matvec(work[slice2])
          elif ijob == 4:
              work[slice1] = M2.matvec(work[slice2])
          elif ijob == 5:
              work[slice1] = M1.rmatvec(work[slice2])
          elif ijob == 6:
              work[slice1] = M2.rmatvec(work[slice2])
          elif ijob == 7:
              work[slice2] *= sclr2
              work[slice2] += sclr1 * A.matvec(x)
          elif ijob == 8:
              if ftflag:
                  info = -1
                  ftflag = False
              resid, info = _stoptest(work[slice1], atol)
          ijob = 2
  
      if info > 0 and iter_ == maxiter and not (resid <= atol):
          # info isn't set appropriately otherwise
          info = iter_
  
      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 9 for calling a global function with example usage: qmr(A, b, x0, tol, maxiter, M1, M2, callback, atol) and returns: postprocess,  info, postprocess,  int, A_, A_, A_, A_, b