code: def gather_nd(
      params: paddle.Tensor,
      indices: paddle.Tensor,
      /,
      *,
      batch_dims: Optional[int] = 0,
      out: Optional[paddle.Tensor] = None,
  ) -> paddle.Tensor:
      """gather_nd implementation with batch support."""
      ivy.utils.assertions.check_gather_nd_input_valid(
          params, indices, batch_dims
      )
      if not isinstance(batch_dims, int):
          raise TypeError(
              f"Argument `batch_dims` must be an int; got {batch_dims}"
          )
      if batch_dims < 0:
          raise ValueError(
              "gather_nd does not allow negative batch_dims."
          )
      params_ndims = params.ndim
      indices_ndims = indices.ndim
      if indices_ndims is not None and batch_dims >= indices_ndims:
          raise ValueError(
              f"Argument `batch_dims` = {batch_dims} must be "
              f"less than rank(`indices`) = {indices_ndims}"
          )
      if params_ndims is not None and batch_dims >= params_ndims:
          raise ValueError(
              f"Argument `batch_dims` = {batch_dims} must be "
              f"less than rank(`params`) = {params_ndims}"
          )
      expand = batch_dims == 0
      if expand:
          # Normally gather_nd will be called when batch_dims == 0.
          # But if this function is called with batch_dims = 0, e.g. for testing
          # purposes, this adds a dummy batch dimension to make batch_dims = 1.
          params = paddle_backend.expand_dims(params, axis=0)
          indices = paddle_backend.expand_dims(indices, axis=0)
          batch_dims = 1
  
      if indices.dtype not in [paddle.int32, paddle.int64]:
          indices = indices.cast(paddle.int32)
  
      params_shape = paddle.to_tensor(params.shape)
      indices_shape = indices.shape
      batch_shape = params_shape[:batch_dims]
      batch_size = paddle.prod(batch_shape, [0]).numpy().tolist()
      if isinstance(batch_size, int):
          batch_size = [batch_size]
      index_internal_ndims = indices.ndim - batch_dims - 1
      indices_internal_shape = indices_shape[batch_dims:-1]
  
      # Assuming a 'params' with shape [b1, ..., bM, g1, ..., gN] and an 'indices'
      # with shape [b1, ..., bM, i1, ..., iK, C], where C <= N, we need to modify
      # 'indices' s.t. it has shape [i1, ..., iK, D], where D <= M + N and slices
      # to the entire 'params' tensor.
      # Assuming we have a batch of shape [B1, B2], we use meshgrid to create a
      # grid of size B1 x B2.
      batch_dim_list = paddle_backend.unstack(batch_shape, axis=0)
      dim_ranges = [
          paddle.arange(0, x.item(), 1, dtype=indices.dtype)
          for x in batch_dim_list
      ]
      if dim_ranges:
          if len(dim_ranges) > 1:
              mesh_list = paddle_backend.meshgrid(
                  *dim_ranges, indexing="ij"
              )
          else:
              mesh_list = dim_ranges
      else:
          mesh_list = []
      # Then we flatten and stack the tensors to form a (B1.B2) by 2 matrix.
      flat_list = [
          paddle_backend.reshape(x, shape=(-1,)) for x in mesh_list
      ]
      stacked_list = (
          paddle_backend.stack(flat_list, axis=0)
          if flat_list
          else paddle.to_tensor([])
      )
      index_grid = paddle_backend.permute_dims(
          stacked_list,
          axes=[axis for axis in range(stacked_list.ndim)][::-1],
      )
      # We need to concatenate these batch coordinates with the internal indices.
      # concat -> index_grid [B1.B2, 2] with indices [i1, ..., iK, C]
      # So we reshape them both to [(B1.B2), i1, ..., iK, *]
      index_grid_shape = index_grid.shape
      index_grid = paddle_backend.reshape(
          index_grid,
          index_grid_shape[:1]
          + [
              1,
          ]
          * index_internal_ndims
          + index_grid_shape[1:],
      )
      tile_shape = (
          [
              1,
          ]
          + indices_internal_shape
          + [
              1,
          ]
      )
      index_grid = paddle_backend.tile(
          index_grid, repeats=paddle.to_tensor(tile_shape)
      )
      # index_grid now has shape [(B1.B2), i1, ..., iK, 2]
      flat_shape = batch_size + indices_shape[batch_dims:]
      flat_indices = paddle_backend.reshape(indices, shape=flat_shape)
      # flat_indices now has shape [(B1.B2), i1, ..., iK, C]
      indices = paddle_backend.concat(
          (index_grid, flat_indices), axis=-1
      )
      # indices has shape [(B1.B2), i1, ..., iK, 2+C]
      if params.dtype in [
          paddle.int8,
          paddle.float16,
          paddle.complex64,
          paddle.complex128,
      ]:
          if paddle.is_complex(params):
              out = paddle.complex(
                  paddle.gather_nd(params.real(), indices),
                  paddle.gather_nd(params.imag(), indices),
              )
          else:
              out = paddle.gather_nd(
                  params.cast("float32"), indices
              ).cast(params.dtype)
      else:
          out = paddle.gather_nd(params, indices)
      # out has shape [(B1.B2), i1, ..., iK, N-C]. Now we reshape batch to
      # its original form.
      out_shape = out.shape
      out = paddle_backend.reshape(
          out, shape=batch_shape.tolist() + out_shape[1:]
      )
      if expand:
          out = paddle_backend.squeeze(out, axis=0)
      return out
  
imports: from numbers import Number
  from typing import Optional, Union, Sequence, Callable, List, Tuple
  import paddle
  import numpy
  import multiprocessing
  import ivy
  import ivy.functional.backends.paddle
  from ivy.func_wrapper import with_unsupported_device_and_dtypes
  from ivy.functional.ivy.general import _broadcast_to
  from ivy.utils.exceptions import _check_inplace_update_support
  from .None import backend_version
label_desc: Use image node_id 12 for calling a global function with example usage: gather_nd() and returns: out