code: def minres(
      A,
      b,
      x0=None,
      shift=0.0,
      tol=1e-5,
      maxiter=None,
      M=None,
      callback=None,
      check=False,
  ):
      """Uses MINimum RESidual iteration to solve  ``Ax = b``.
  
      Args:
          A (ndarray, spmatrix or LinearOperator): The real or complex matrix of
              the linear system with shape ``(n, n)``.
          b (cupy.ndarray): Right hand side of the linear system with shape
              ``(n,)`` or ``(n, 1)``.
          x0 (cupy.ndarray): Starting guess for the solution.
          shift (int or float): If shift != 0 then the method solves
              ``(A - shift*I)x = b``
          tol (float): Tolerance for convergence.
          maxiter (int): Maximum number of iterations.
          M (ndarray, spmatrix or LinearOperator): Preconditioner for ``A``.
              The preconditioner should approximate the inverse of ``A``.
              ``M`` must be :class:`cupy.ndarray`,
              :class:`cupyx.scipy.sparse.spmatrix` or
              :class:`cupyx.scipy.sparse.linalg.LinearOperator`.
          callback (function): User-specified function to call after each
              iteration. It is called as ``callback(xk)``, where ``xk`` is the
              current solution vector.
  
      Returns:
          tuple:
              It returns ``x`` (cupy.ndarray) and ``info`` (int) where ``x`` is
              the converged solution and ``info`` provides convergence
              information.
  
      .. seealso:: :func:`scipy.sparse.linalg.minres`
      """
      A, M, x, b = _make_system(A, M, x0, b)
  
      matvec = A.matvec
      psolve = M.matvec
  
      n = b.shape[0]
  
      if maxiter is None:
          maxiter = n * 5
  
      istop = 0
      itn = 0
      Anorm = 0
      Acond = 0
      rnorm = 0
      ynorm = 0
  
      xtype = x.dtype
  
      eps = cupy.finfo(xtype).eps
  
      Ax = matvec(x)
      r1 = b - Ax
      y = psolve(r1)
  
      beta1 = cupy.inner(r1, y)
  
      if beta1 < 0:
          raise ValueError("indefinite preconditioner")
      elif beta1 == 0:
          return x, 0
  
      beta1 = cupy.sqrt(beta1)
      beta1 = beta1.get().item()
  
      if check:
          # see if A is symmetric
          if not _check_symmetric(A, Ax, x, eps):
              raise ValueError("non-symmetric matrix")
  
          # see if M is symmetric
          if not _check_symmetric(M, y, r1, eps):
              raise ValueError("non-symmetric preconditioner")
  
      oldb = 0
      beta = beta1
      dbar = 0
      epsln = 0
      qrnorm = beta1
      phibar = beta1
      rhs1 = beta1
      rhs2 = 0
      tnorm2 = 0
      gmax = 0
      gmin = cupy.finfo(xtype).max
      cs = -1
      sn = 0
      w = cupy.zeros(n, dtype=xtype)
      w2 = cupy.zeros(n, dtype=xtype)
      r2 = r1
  
      while itn < maxiter:
          itn += 1
          s = 1.0 / beta
          v = s * y
  
          y = matvec(v)
          y -= shift * v
  
          if itn >= 2:
              y -= (beta / oldb) * r1
  
          alpha = cupy.inner(v, y)
          alpha = alpha.get().item()
          y -= (alpha / beta) * r2
          r1 = r2
          r2 = y
          y = psolve(r2)
          oldb = beta
          beta = cupy.inner(r2, y)
          beta = beta.get().item()
          beta = numpy.sqrt(beta)
          if beta < 0:
              raise ValueError("non-symmetric matrix")
  
          tnorm2 += alpha**2 + oldb**2 + beta**2
  
          if itn == 1:
              if beta / beta1 <= 10 * eps:
                  istop = -1
  
          # Apply previous rotation Qk-1 to get
          #   [deltak epslnk+1] = [cs  sn][dbark    0   ]
          #   [gbar k dbar k+1]   [sn -cs][alfak betak+1].
  
          oldeps = epsln
          delta = cs * dbar + sn * alpha  # delta1 = 0         deltak
          gbar = sn * dbar - cs * alpha  # gbar 1 = alfa1     gbar k
          epsln = sn * beta  # epsln2 = 0         epslnk+1
          dbar = -cs * beta  # dbar 2 = beta2     dbar k+1
          root = numpy.linalg.norm([gbar, dbar])
  
          # Compute the next plane rotation Qk
  
          gamma = numpy.linalg.norm([gbar, beta])  # gammak
          gamma = max(gamma, eps)
          cs = gbar / gamma  # ck
          sn = beta / gamma  # sk
          phi = cs * phibar  # phik
          phibar = sn * phibar  # phibark+1
  
          # Update  x.
  
          denom = 1.0 / gamma
          w1 = w2
          w2 = w
          w = (v - oldeps * w1 - delta * w2) * denom
          x += phi * w
  
          # Go round again.
  
          gmax = max(gmax, gamma)
          gmin = min(gmin, gamma)
          z = rhs1 / gamma
          rhs1 = rhs2 - delta * z
          rhs2 = -epsln * z
  
          # Estimate various norms and test for convergence.
  
          Anorm = numpy.sqrt(tnorm2)
          ynorm = cupy.linalg.norm(x)
          ynorm = ynorm.get().item()
          epsa = Anorm * eps
          epsx = Anorm * ynorm * eps
          diag = gbar
  
          if diag == 0:
              diag = epsa
  
          qrnorm = phibar
          rnorm = qrnorm
          if ynorm == 0 or Anorm == 0:
              test1 = numpy.inf
          else:
              test1 = rnorm / (Anorm * ynorm)  # ||r||  / (||A|| ||x||)
          if Anorm == 0:
              test2 = numpy.inf
          else:
              test2 = root / Anorm  # ||Ar|| / (||A|| ||r||)
  
          # Estimate  cond(A).
          # In this version we look at the diagonals of  R  in the
          # factorization of the lower Hessenberg matrix,  Q * H = R,
          # where H is the tridiagonal matrix from Lanczos with one
          # extra row, beta(k+1) e_k^T.
  
          Acond = gmax / gmin
  
          # See if any of the stopping criteria are satisfied.
          # In rare cases, istop is already -1 from above (Abar = const*I).
  
          if istop == 0:
              t1 = 1 + test1  # These tests work if tol < eps
              t2 = 1 + test2
              if t2 <= 1:
                  istop = 2
              if t1 <= 1:
                  istop = 1
  
              if itn >= maxiter:
                  istop = 6
              if Acond >= 0.1 / eps:
                  istop = 4
              if epsx >= beta1:
                  istop = 3
              # epsr = Anorm * ynorm * tol
              # if rnorm <= epsx   : istop = 2
              # if rnorm <= epsr   : istop = 1
              if test2 <= tol:
                  istop = 2
              if test1 <= tol:
                  istop = 1
  
          if callback is not None:
              callback(x)
  
          if istop != 0:
              break
  
      if istop == 6:
          info = maxiter
      else:
          info = 0
  
      return x, info
  
imports: import numpy
  import cupy
  from cupy import cublas
  from cupy.cuda import device
  from cupy.cuda import runtime
  from cupy.linalg import _util
  from cupyx.scipy import sparse
  from cupyx.scipy.sparse.linalg import _interface
  from cupyx.scipy.sparse.linalg._iterative import _make_system
  import warnings
label_desc: Use image node_id 10 for calling a global function with example usage: minres(A, b, x0, shift, tol, maxiter, M, callback, check) and returns: x,  info, x,  int