code: def scatter_elements(data, indices, updates, axis=0, reduction="none"):  # type: ignore
      if axis < 0:
          axis = data.ndim + axis
  
      idx_xsection_shape = (
          indices.shape[:axis] + indices.shape[axis + 1 :]
      )
  
      def make_slice(arr, axis, i):  # type: ignore
          slc = [slice(None)] * arr.ndim
          slc[axis] = i
          return slc
  
      def unpack(packed):  # type: ignore
          unpacked = packed[0]
          for i in range(1, len(packed)):
              unpacked = unpacked, packed[i]
          return unpacked
  
      def make_indices_for_duplicate(idx):  # type: ignore
          final_idx = []
          for i in range(len(idx[0])):
              final_idx.append(
                  tuple(idx_element[i] for idx_element in idx)
              )
          return list(final_idx)
  
      # We use indices and axis parameters to create idx
      # idx is in a form that can be used as a NumPy advanced indices for scattering of updates param. in data
      idx = [
          [
              unpack(
                  np.indices(idx_xsection_shape).reshape(
                      indices.ndim - 1, -1
                  )
              ),
              indices[tuple(make_slice(indices, axis, i))].reshape(
                  1, -1
              )[0],
          ]
          for i in range(indices.shape[axis])
      ]
      idx = list(np.concatenate(idx, axis=1))
      idx.insert(axis, idx.pop())
  
      # updates_idx is a NumPy advanced indices for indexing of elements in the updates
      updates_idx = list(idx)
      updates_idx.pop(axis)
      updates_idx.insert(
          axis,
          np.repeat(
              np.arange(indices.shape[axis]),
              np.prod(idx_xsection_shape),
          ),
      )
  
      scattered = np.copy(data)
      if reduction == "none":
          scattered[tuple(idx)] = updates[tuple(updates_idx)]
      else:
          idx, updates_idx = make_indices_for_duplicate(
              idx
          ), make_indices_for_duplicate(updates_idx)
          for iter, idx_set in enumerate(idx):  # noqa: A001
              if reduction == "add":
                  scattered[idx_set] += updates[updates_idx[iter]]
              elif reduction == "mul":
                  scattered[idx_set] *= updates[updates_idx[iter]]
              elif reduction == "max":
                  scattered[idx_set] = np.maximum(
                      scattered[idx_set], updates[updates_idx[iter]]
                  )
              elif reduction == "min":
                  scattered[idx_set] = np.minimum(
                      scattered[idx_set], updates[updates_idx[iter]]
                  )
      return scattered
  
file_path: onnx/onnx/backend/test/case/node/scatterelements.py
imports: import numpy
  import onnx
  from onnx.backend.test.case.base import Base
  from onnx.backend.test.case.node import expect
label_desc: Use image node_id 1 for calling a global function with example usage: scatter_elements(data, indices, updates, axis, reduction) and returns: scattered, slc, unpacked, list