code: def qr(a, mode="reduced"):
      """QR decomposition.
  
      Decompose a given two-dimensional matrix into ``Q * R``, where ``Q``
      is an orthonormal and ``R`` is an upper-triangular matrix.
  
      Args:
          a (cupy.ndarray): The input matrix.
          mode (str): The mode of decomposition. Currently 'reduced',
              'complete', 'r', and 'raw' modes are supported. The default mode
              is 'reduced', in which matrix ``A = (..., M, N)`` is decomposed
              into ``Q``, ``R`` with dimensions ``(..., M, K)``, ``(..., K, N)``,
              where ``K = min(M, N)``.
  
      Returns:
          cupy.ndarray, or tuple of ndarray:
              Although the type of returned object depends on the mode,
              it returns a tuple of ``(Q, R)`` by default.
              For details, please see the document of :func:`numpy.linalg.qr`.
  
      .. warning::
          This function calls one or more cuSOLVER routine(s) which may yield
          invalid results if input conditions are not met.
          To detect these invalid results, you can set the `linalg`
          configuration to a value that is not `ignore` in
          :func:`cupyx.errstate` or :func:`cupyx.seterr`.
  
      .. seealso:: :func:`numpy.linalg.qr`
      """
      from cupy_backends.cuda.libs import cusolver
  
      _util._assert_cupy_array(a)
  
      if mode not in ("reduced", "complete", "r", "raw"):
          if mode in ("f", "full", "e", "economic"):
              msg = "The deprecated mode '{}' is not supported".format(
                  mode
              )
          else:
              msg = "Unrecognized mode '{}'".format(mode)
          raise ValueError(msg)
      if a.ndim > 2:
          return _qr_batched(a, mode)
  
      # support float32, float64, complex64, and complex128
      dtype, out_dtype = _util.linalg_common_type(a)
  
      m, n = a.shape
      k = min(m, n)
      if k == 0:
          if mode == "reduced":
              return cupy.empty((m, 0), out_dtype), cupy.empty(
                  (0, n), out_dtype
              )
          elif mode == "complete":
              return cupy.identity(m, out_dtype), cupy.empty(
                  (m, n), out_dtype
              )
          elif mode == "r":
              return cupy.empty((0, n), out_dtype)
          else:  # mode == 'raw'
              return cupy.empty((n, m), out_dtype), cupy.empty(
                  (0,), out_dtype
              )
  
      x = a.transpose().astype(dtype, order="C", copy=True)
      handle = device.get_cusolver_handle()
      dev_info = cupy.empty(1, dtype=numpy.int32)
  
      if dtype == "f":
          geqrf_bufferSize = cusolver.sgeqrf_bufferSize
          geqrf = cusolver.sgeqrf
      elif dtype == "d":
          geqrf_bufferSize = cusolver.dgeqrf_bufferSize
          geqrf = cusolver.dgeqrf
      elif dtype == "F":
          geqrf_bufferSize = cusolver.cgeqrf_bufferSize
          geqrf = cusolver.cgeqrf
      elif dtype == "D":
          geqrf_bufferSize = cusolver.zgeqrf_bufferSize
          geqrf = cusolver.zgeqrf
      else:
          msg = (
              "dtype must be float32, float64, complex64 or complex128"
              " (actual: {})".format(a.dtype)
          )
          raise ValueError(msg)
  
      # compute working space of geqrf and solve R
      buffersize = geqrf_bufferSize(handle, m, n, x.data.ptr, n)
      workspace = cupy.empty(buffersize, dtype=dtype)
      tau = cupy.empty(k, dtype=dtype)
      geqrf(
          handle,
          m,
          n,
          x.data.ptr,
          m,
          tau.data.ptr,
          workspace.data.ptr,
          buffersize,
          dev_info.data.ptr,
      )
      cupy.linalg._util._check_cusolver_dev_info_if_synchronization_allowed(
          geqrf, dev_info
      )
  
      if mode == "r":
          r = x[:, :k].transpose()
          return _util._triu(r).astype(out_dtype, copy=False)
  
      if mode == "raw":
          return (
              x.astype(out_dtype, copy=False),
              tau.astype(out_dtype, copy=False),
          )
  
      if mode == "complete" and m > n:
          mc = m
          q = cupy.empty((m, m), dtype)
      else:
          mc = k
          q = cupy.empty((n, m), dtype)
      q[:n] = x
  
      # compute working space of orgqr and solve Q
      if dtype == "f":
          orgqr_bufferSize = cusolver.sorgqr_bufferSize
          orgqr = cusolver.sorgqr
      elif dtype == "d":
          orgqr_bufferSize = cusolver.dorgqr_bufferSize
          orgqr = cusolver.dorgqr
      elif dtype == "F":
          orgqr_bufferSize = cusolver.cungqr_bufferSize
          orgqr = cusolver.cungqr
      elif dtype == "D":
          orgqr_bufferSize = cusolver.zungqr_bufferSize
          orgqr = cusolver.zungqr
  
      buffersize = orgqr_bufferSize(
          handle, m, mc, k, q.data.ptr, m, tau.data.ptr
      )
      workspace = cupy.empty(buffersize, dtype=dtype)
      orgqr(
          handle,
          m,
          mc,
          k,
          q.data.ptr,
          m,
          tau.data.ptr,
          workspace.data.ptr,
          buffersize,
          dev_info.data.ptr,
      )
      cupy.linalg._util._check_cusolver_dev_info_if_synchronization_allowed(
          orgqr, dev_info
      )
  
      q = q[:mc].transpose()
      r = x[:, :mc].transpose()
      return (
          q.astype(out_dtype, copy=False),
          _util._triu(r).astype(out_dtype, copy=False),
      )
  
file_path: cupy/cupy/linalg/_decomposition.py
imports: import numpy
  import cupy
  from cupy_backends.cuda.api import runtime
  from cupy._core import internal
  from cupy.cuda import device
  from cupy.linalg import _util
label_desc: Use image node_id 5 for calling a global function with example usage: qr(a, mode) and returns: q,  _util, _qr_batched, _util, x,  tau, cupy,  cupy, cupy,  cupy, cupy, cupy,  cupy