code: def apply_iir_sos(
      x,
      sos,
      axis=-1,
      zi=None,
      dtype=None,
      block_sz=1024,
      apply_fir=True,
      out=None,
  ):
      if dtype is None:
          dtype = cupy.result_type(x.dtype, sos.dtype)
  
      sos = sos.astype(dtype)
  
      if zi is not None:
          zi = zi.astype(dtype)
  
      x_shape = x.shape
      x_ndim = x.ndim
      n_sections = sos.shape[0]
      axis = _normalize_axis_index(axis, x_ndim)
      k = 2
      n = x_shape[axis]
      zi_shape = None
  
      if x_ndim > 1:
          x, x_shape = collapse_2d(x, axis)
  
      if zi is not None:
          zi, zi_shape = collapse_2d_rest(zi, axis)
  
      if out is None:
          out = cupy.array(x, dtype=dtype, copy=True)
  
      num_rows = 1 if x.ndim == 1 else x.shape[0]
      n_blocks = (n + block_sz - 1) // block_sz
      total_blocks = num_rows * n_blocks
  
      correction = compute_correction_factors_sos(sos, block_sz, dtype)
      carries = cupy.empty((num_rows, n_blocks, k), dtype=dtype)
      all_carries = carries
      zi_out = None
      if zi is not None:
          zi_out = cupy.empty_like(zi)
          all_carries = cupy.empty(
              (num_rows, n_blocks + 1, k), dtype=dtype
          )
  
      first_pass_kernel = _get_module_func(
          IIR_SOS_MODULE, "first_pass_iir_sos", out
      )
      second_pass_kernel = _get_module_func(
          IIR_SOS_MODULE, "second_pass_iir_sos", out
      )
      carry_correction_kernel = _get_module_func(
          IIR_SOS_MODULE, "correct_carries_sos", out
      )
      fir_kernel = _get_module_func(IIR_SOS_MODULE, "fir_sos", out)
      carries_kernel = _get_module_func(
          IIR_SOS_MODULE, "pick_carries", out
      )
  
      starting_group = int(zi is None)
      blocks_to_merge = n_blocks - starting_group
      carries_stride = (n_blocks + (1 - starting_group)) * k
  
      carries_kernel(
          (num_rows * n_blocks,),
          (k,),
          (
              block_sz,
              n,
              carries_stride,
              n_blocks,
              starting_group,
              out,
              all_carries,
          ),
      )
  
      for s in range(n_sections):
          b = sos[s]
          if zi is not None:
              section_zi = zi[s, :, :2]
              all_carries[:, 0, :] = section_zi
              zi_out[s, :, :2] = axis_slice(out, n - 2, n)
  
          if apply_fir:
              fir_kernel(
                  (num_rows * n_blocks,),
                  (block_sz,),
                  (
                      block_sz,
                      n,
                      carries_stride,
                      n_blocks,
                      starting_group,
                      b,
                      all_carries,
                      out,
                  ),
              )
  
          first_pass_kernel(
              (total_blocks,),
              (block_sz // 2,),
              (block_sz, n, n_blocks, correction[s], out, carries),
          )
  
          if n_blocks > 1 or zi is not None:
              if zi is not None:
                  section_zi = zi[s, :, 2:]
                  all_carries[:, 0, :] = section_zi
                  all_carries[:, 1:, :] = carries
  
              carry_correction_kernel(
                  (num_rows,),
                  (k,),
                  (
                      block_sz,
                      n_blocks,
                      carries_stride,
                      starting_group,
                      correction[s],
                      all_carries,
                  ),
              )
              second_pass_kernel(
                  (num_rows * blocks_to_merge,),
                  (block_sz,),
                  (
                      block_sz,
                      n,
                      carries_stride,
                      blocks_to_merge,
                      starting_group,
                      correction[s],
                      all_carries,
                      out,
                  ),
              )
  
          if apply_fir:
              carries_kernel(
                  (num_rows * n_blocks,),
                  (k,),
                  (
                      block_sz,
                      n,
                      carries_stride,
                      n_blocks,
                      starting_group,
                      out,
                      all_carries,
                  ),
              )
  
          if zi is not None:
              zi_out[s, :, 2:] = axis_slice(out, n - 2, n)
  
      if x_ndim > 1:
          out = out.reshape(x_shape)
          out = cupy.moveaxis(out, -1, axis)
          if not out.flags.c_contiguous:
              out = out.copy()
  
      if zi is not None:
          zi_out = zi_out.reshape(zi_shape)
          zi_out = cupy.moveaxis(zi_out, -1, axis)
          if not zi_out.flags.c_contiguous:
              zi_out = zi_out.copy()
  
      if zi is not None:
          return out, zi_out
      return out
  
file_path: cupy/cupyx/scipy/signal/_iir_utils.py
imports: from itertools import product
  import cupy
  from cupy._core.internal import _normalize_axis_index
  from cupy._core._scalar import get_typename
  from cupy_backends.cuda.api import runtime
  from cupyx.scipy.signal._arraytools import axis_slice
label_desc: Use image node_id 8 for calling a global function with example usage: apply_iir_sos(x, sos, axis, zi, dtype, block_sz, apply_fir, out) and returns: out, out,  zi_out