code: def bicgstab(
      A,
      b,
      x0=None,
      tol=1e-5,
      maxiter=None,
      M=None,
      callback=None,
      atol=None,
  ):
      A, M, x, b, postprocess = make_system(A, M, x0, b)
  
      n = len(b)
      if maxiter is None:
          maxiter = n * 10
  
      matvec = A.matvec
      psolve = M.matvec
      ltr = _type_conv[x.dtype.char]
      revcom = getattr(_iterative, ltr + "bicgstabrevcom")
  
      get_residual = lambda: np.linalg.norm(matvec(x) - b)
      atol = _get_atol(
          tol, atol, np.linalg.norm(b), get_residual, "bicgstab"
      )
      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(7 * n, dtype=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 * matvec(work[slice1])
          elif ijob == 2:
              work[slice1] = psolve(work[slice2])
          elif ijob == 3:
              work[slice2] *= sclr2
              work[slice2] += sclr1 * matvec(x)
          elif ijob == 4:
              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 5 for calling a global function with example usage: bicgstab(A, b, x0, tol, maxiter, M, callback, atol) and returns: postprocess,  info, postprocess,  int