docstr: Short-and-Fat QR
  
  Q [R_1 R_2 ...] = [A_1 A_2 ...]
docstr_tok: ["Short-and-Fat","QR","Q","[","R_1","R_2","...","]","=","[","A_1","A_2","...","]"]
code: def tile(cls, op):
      """
      Short-and-Fat QR
  
      Q [R_1 R_2 ...] = [A_1 A_2 ...]
      """
      from .qr import TensorQR
      from .dot import TensorDot
      from ..base import TensorTranspose
  
      a = op.input
      q, r = op.outputs
  
      tinyq, tinyr = np.linalg.qr(np.ones((1, 1), dtype=a.dtype))
      q_dtype, r_dtype = tinyq.dtype, tinyr.dtype
  
      check_nan_shape = False
      rechunk_size = dict()
      if a.chunk_shape[0] != 1:
          check_nan_shape = True
          rechunk_size[0] = a.shape[0]
  
      if len(a.chunks) > 1:
          check_nan_shape = True
          if a.chunks[0].shape[0] > a.chunks[0].shape[1]:
              rechunk_size[1] = a.shape[0]
  
      if check_nan_shape:
          if has_unknown_shape(a):
              yield
  
      if rechunk_size:
          new_chunks = decide_chunk_sizes(
              a.shape, rechunk_size, a.dtype.itemsize
          )
          a = yield from recursive_tile(a.rechunk(new_chunks))
  
      # A_1's QR decomposition
      r_chunks = []
      first_chunk = a.chunks[0]
      x, y = first_chunk.shape
      q_shape, r_shape = (
          (first_chunk.shape, (y, y))
          if x > y
          else ((x, x), first_chunk.shape)
      )
      qr_op = TensorQR()
      q_chunk, r_chunk = qr_op.new_chunks(
          [first_chunk],
          index=(0, 0),
          kws=[
              {
                  "side": "q",
                  "dtype": q_dtype,
                  "shape": q_shape,
                  "order": q.order,
              },
              {
                  "side": "r",
                  "dtype": r_dtype,
                  "shape": r_shape,
                  "order": r.order,
              },
          ],
      )
      # q is an orthogonal matrix, so q.T and inverse of q is equal
      trans_op = TensorTranspose()
      q_transpose = trans_op.new_chunk([q_chunk], shape=q_chunk.shape)
      r_chunks.append(r_chunk)
  
      r_rest = [
          TensorDot().new_chunk(
              [q_transpose, c],
              shape=(q_transpose.shape[0], c.shape[1]),
              index=c.index,
              order=q.order,
          )
          for c in a.chunks[1:]
      ]
      r_chunks.extend(r_rest)
  
      new_op = op.copy()
      q_nsplits = ((q_chunk.shape[0],), (q_chunk.shape[1],))
      r_nsplits = (
          (r_chunks[0].shape[0],),
          tuple(c.shape[1] for c in r_chunks),
      )
      kws = [
          {
              "chunks": [q_chunk],
              "nsplits": q_nsplits,
              "dtype": q.dtype,
              "shape": q.shape,
          },
          {
              "chunks": r_chunks,
              "nsplits": r_nsplits,
              "dtype": r.dtype,
              "shape": r.shape,
          },
      ]
      return new_op.new_tensors(op.inputs, kws=kws)
  
file_path: mars/mars/tensor/linalg/core.py
imports: import numpy
  from ...core import recursive_tile
  from ...utils import has_unknown_shape
  from ..core import TensorOrder
  from ..utils import decide_chunk_sizes
  from .utils import calc_svd_shapes
label_desc: Use image node_id 1 for calling the SFQR obj's underlying member method code with example usage: obj.tile(cls, op) and returns: new_op