code: def tile(cls, op):
      if isinstance(op.bins, ENTITY_TYPE):
          # check op.bins chunk shapes
          if has_unknown_shape(op.bins):
              yield
          bins = yield from recursive_tile(
              op.bins.rechunk(op.bins.shape)
          )
      else:
          bins = op.bins
  
      if isinstance(op.labels, ENTITY_TYPE):
          # check op.labels chunk shapes
          if has_unknown_shape(op.labels):
              yield
          labels = yield from recursive_tile(
              op.labels.rechunk(op.labels.shape)
          )
      else:
          labels = op.labels
  
      if isinstance(op.bins, Integral):
          input_min, input_max = yield from recursive_tile(
              op.input.min(), op.input.max()
          )
          input_min_chunk = input_min.chunks[0]
          input_max_chunk = input_max.chunks[0]
  
          # let input min and max execute first
          min_max_chunks = [input_min_chunk, input_max_chunk]
          yield min_max_chunks + [
              c for inp in op.inputs for c in inp.chunks
          ]
  
          ctx = get_context()
          keys = [input_min_chunk.key, input_max_chunk.key]
          # get min and max of x
          min_val, max_val = ctx.get_chunks_result(keys)
          # calculate bins
          if np.isinf(min_val) or np.isinf(max_val):
              raise ValueError(
                  "cannot specify integer `bins` when input data contains infinity"
              )
          elif min_val == max_val:  # adjust end points before binning
              min_val -= 0.001 * abs(min_val) if min_val != 0 else 0.001
              max_val += 0.001 * abs(max_val) if max_val != 0 else 0.001
              bins = np.linspace(
                  min_val, max_val, bins + 1, endpoint=True
              )
          else:  # adjust end points before binning
              bins = np.linspace(
                  min_val, max_val, bins + 1, endpoint=True
              )
              adj = (max_val - min_val) * 0.001  # 0.1% of the range
              if op.right:
                  bins[0] -= adj
              else:
                  bins[-1] += adj
  
      outs = op.outputs
  
      out_chunks = []
      for c in op.input.chunks:
          chunk_op = op.copy().reset_key()
          chunk_inputs = [c]
          chunk_op._bins = bins
          # do not return bins always for chunk
          chunk_op._retbins = False
          if isinstance(bins, ENTITY_TYPE):
              chunk_inputs.append(bins.chunks[0])
          chunk_op._labels = labels
          if isinstance(labels, ENTITY_TYPE):
              chunk_inputs.append(labels.chunks[0])
  
          chunk_kws = []
          if isinstance(outs[0], SERIES_TYPE):
              chunk_kws.append(
                  {
                      "dtype": outs[0].dtype,
                      "shape": c.shape,
                      "index_value": c.index_value,
                      "name": c.name,
                      "index": c.index,
                  }
              )
          elif isinstance(outs[0], TENSOR_TYPE):
              chunk_kws.append(
                  {
                      "dtype": outs[0].dtype,
                      "shape": c.shape,
                      "order": TensorOrder.C_ORDER,
                      "index": c.index,
                  }
              )
          else:
              chunk_kws.append(
                  {
                      "dtype": outs[0].dtype,
                      "shape": c.shape,
                      "categories_value": outs[0].categories_value,
                      "index": c.index,
                  }
              )
  
          out_chunks.append(
              chunk_op.new_chunk(chunk_inputs, kws=chunk_kws)
          )
  
      kws = []
      out_kw = outs[0].params
      out_kw["chunks"] = out_chunks
      out_kw["nsplits"] = op.input.nsplits
      kws.append(out_kw)
      if len(outs) == 2:
          bins_kw = outs[1].params
          bins_kw["chunks"] = bins_chunks = []
          if isinstance(bins, ENTITY_TYPE):
              bins_chunks.append(bins.chunks[0])
          else:
              if op.duplicates == "drop":
                  if isinstance(bins, (np.ndarray, list, tuple)):
                      bins = np.unique(bins)
                  else:
                      bins = bins.unique()
                  bins = bins.astype(outs[1].dtype, copy=False)
              convert = (
                  astensor
                  if not isinstance(bins, pd.IntervalIndex)
                  else asindex
              )
              converted = yield from recursive_tile(
                  convert(bins, chunk_size=len(bins))
              )
              bins_chunks.append(converted.chunks[0])
          bins_kw["nsplits"] = ((len(bins),),)
          kws.append(bins_kw)
      new_op = op.copy()
      return new_op.new_tileables(op.inputs, kws=kws)
  
imports: from functools import partial
  from numbers import Integral
  import numpy
  import pandas
  from ...None import opcodes
  from ...core import ENTITY_TYPE, ExecutableTuple, OutputType, recursive_tile
  from ...core.context import get_context
  from ...lib.version import parse
  from ...serialization.serializables import KeyField, AnyField, BoolField, Int32Field, StringField
  from ...tensor import tensor
  from ...tensor.core import TENSOR_TYPE, TensorOrder
  from ...utils import has_unknown_shape
  from ..core import SERIES_TYPE, INDEX_TYPE
  from ..datasource.index import from_pandas
  from ..initializer import Series
  from ..operands import DataFrameOperand, DataFrameOperandMixin
  from ..utils import parse_index
label_desc: Use image node_id 14 for calling the DataFrameCut obj's underlying member method code with example usage: obj.tile(cls, op) and returns: new_op