code: def affine_transformation(
      data,
      transformation_matrix,
      output_shape=None,
      output=None,
      interpolation: str = "linear",
      mode: str = "constant",
      border_value=0,
  ):
      """
      Apply an affine transformation.
  
      The method uses texture memory and supports only 2D and 3D float32 arrays
      without channel dimension.
  
      Args:
          data (cupy.ndarray): The input array or texture object.
          transformation_matrix (cupy.ndarray): Affine transformation matrix.
              Must be a homogeneous and have shape ``(ndim + 1, ndim + 1)``.
          output_shape (tuple of ints): Shape of output. If not specified,
              the input array shape is used. Default is None.
          output (cupy.ndarray or ~cupy.dtype): The array in which to place the
              output, or the dtype of the returned array. If not specified,
              creates the output array with shape of ``output_shape``. Default is
              None.
          interpolation (str): Specifies interpolation mode: ``'linear'`` or
              ``'nearest'``. Default is ``'linear'``.
          mode (str): Specifies addressing mode for points outside of the array:
              (`'constant'``, ``'nearest'``). Default is ``'constant'``.
          border_value: Specifies value to be used for coordinates outside
              of the array for ``'constant'`` mode. Default is 0.
  
      Returns:
          cupy.ndarray:
              The transformed input.
  
      .. seealso:: :func:`cupyx.scipy.ndimage.affine_transform`
      """
  
      ndim = data.ndim
      if (ndim < 2) or (ndim > 3):
          raise ValueError(
              "Texture memory affine transformation is defined only for "
              "2D and 3D arrays without channel dimension."
          )
  
      dtype = data.dtype
      if dtype != cupy.float32:
          raise ValueError(
              f"Texture memory affine transformation is available "
              f"only for float32 data type (not {dtype})"
          )
  
      if interpolation not in ["linear", "nearest"]:
          raise ValueError(
              f"Unsupported interpolation {interpolation} "
              f"(supported: linear, nearest)"
          )
  
      if transformation_matrix.shape != (ndim + 1, ndim + 1):
          raise ValueError(
              "Matrix must be have shape (ndim + 1, ndim + 1)"
          )
  
      texture_object = _create_texture_object(
          data,
          address_mode=mode,
          filter_mode=interpolation,
          read_mode="element_type",
          border_color=border_value,
      )
  
      if ndim == 2:
          kernel = _affine_transform_2d_array_kernel
      else:
          kernel = _affine_transform_3d_array_kernel
  
      if output_shape is None:
          output_shape = data.shape
  
      if output is None:
          output = cupy.zeros(output_shape, dtype=dtype)
      elif isinstance(output, (type, cupy.dtype)):
          if output != cupy.float32:
              raise ValueError(
                  f"Texture memory affine transformation is "
                  f"available only for float32 data type (not "
                  f"{output})"
              )
          output = cupy.zeros(output_shape, dtype=output)
      elif isinstance(output, cupy.ndarray):
          if output.shape != output_shape:
              raise ValueError("Output shapes do not match")
      else:
          raise ValueError(
              "Output must be None, cupy.ndarray or cupy.dtype"
          )
  
      kernel(
          texture_object,
          transformation_matrix,
          *output_shape[1:],
          output,
      )
      return output
  
imports: import cupy
  from cupy import _core
  from cupy.cuda import texture
  from cupy.cuda import runtime
label_desc: Use image node_id 2 for calling a global function with example usage: affine_transformation(data, transformation_matrix, output_shape, output, interpolation, mode, border_value) and returns: output