code: def _select(
      input,
      labels=None,
      index=None,
      find_min=False,
      find_max=False,
      find_min_positions=False,
      find_max_positions=False,
      find_median=False,
  ):
      """Return one or more of: min, max, min position, max position, median.
  
      If neither `labels` or `index` is provided, these are the global values
      in `input`. If `index` is None, but `labels` is provided, a global value
      across all non-zero labels is given. When both `labels` and `index` are
      provided, lists of values are provided for each labeled region specified
      in `index`. See further details in :func:`cupyx.scipy.ndimage.minimum`,
      etc.
  
      Used by minimum, maximum, minimum_position, maximum_position, extrema.
      """
      find_positions = find_min_positions or find_max_positions
      positions = None
      if find_positions:
          positions = cupy.arange(input.size).reshape(input.shape)
  
      def single_group(vals, positions):
          result = []
          if find_min:
              result += [vals.min()]
          if find_min_positions:
              result += [positions[vals == vals.min()][0]]
          if find_max:
              result += [vals.max()]
          if find_max_positions:
              result += [positions[vals == vals.max()][0]]
          if find_median:
              result += [cupy.median(vals)]
          return result
  
      if labels is None:
          return single_group(input, positions)
  
      # ensure input and labels match sizes
      input, labels = cupy.broadcast_arrays(input, labels)
  
      if index is None:
          mask = labels > 0
          masked_positions = None
          if find_positions:
              masked_positions = positions[mask]
          return single_group(input[mask], masked_positions)
  
      if cupy.isscalar(index):
          mask = labels == index
          masked_positions = None
          if find_positions:
              masked_positions = positions[mask]
          return single_group(input[mask], masked_positions)
  
      index = cupy.asarray(index)
  
      safe_int = _safely_castable_to_int(labels.dtype)
      min_label = labels.min()
      max_label = labels.max()
  
      # Remap labels to unique integers if necessary, or if the largest label is
      # larger than the number of values.
      if not safe_int or min_label < 0 or max_label > labels.size:
          # Remap labels, and indexes
          unique_labels, labels = cupy.unique(
              labels, return_inverse=True
          )
          idxs = cupy.searchsorted(unique_labels, index)
  
          # Make all of idxs valid
          idxs[idxs >= unique_labels.size] = 0
          found = unique_labels[idxs] == index
      else:
          # Labels are an integer type, and there aren't too many
          idxs = cupy.asanyarray(index, int).copy()
          found = (idxs >= 0) & (idxs <= max_label)
  
      idxs[~found] = max_label + 1
  
      input = input.ravel()
      labels = labels.ravel()
      if find_positions:
          positions = positions.ravel()
  
      using_cub = (
          _core._accelerator.ACCELERATOR_CUB
          in cupy._core.get_routine_accelerators()
      )
  
      if using_cub:
          # Cutoff values below were determined empirically for relatively large
          # input arrays.
          if find_positions or find_median:
              n_label_cutoff = 15
          else:
              n_label_cutoff = 30
      else:
          n_label_cutoff = 0
  
      if n_label_cutoff and len(idxs) <= n_label_cutoff:
          return _select_via_looping(
              input,
              labels,
              idxs,
              positions,
              find_min,
              find_min_positions,
              find_max,
              find_max_positions,
              find_median,
          )
  
      order = cupy.lexsort(cupy.stack((input.ravel(), labels.ravel())))
      input = input[order]
      labels = labels[order]
      if find_positions:
          positions = positions[order]
  
      # Determine indices corresponding to the min or max value for each label
      label_change_index = cupy.searchsorted(
          labels, cupy.arange(1, max_label + 2)
      )
      if find_min or find_min_positions or find_median:
          # index corresponding to the minimum value at each label
          min_index = label_change_index[:-1]
      if find_max or find_max_positions or find_median:
          # index corresponding to the maximum value at each label
          max_index = label_change_index[1:] - 1
  
      result = []
      # the order below matches the order expected by cupy.ndimage.extrema
      if find_min:
          mins = cupy.zeros(int(labels.max()) + 2, input.dtype)
          mins[labels[min_index]] = input[min_index]
          result += [mins[idxs]]
      if find_min_positions:
          minpos = cupy.zeros(labels.max().item() + 2, int)
          minpos[labels[min_index]] = positions[min_index]
          result += [minpos[idxs]]
      if find_max:
          maxs = cupy.zeros(int(labels.max()) + 2, input.dtype)
          maxs[labels[max_index]] = input[max_index]
          result += [maxs[idxs]]
      if find_max_positions:
          maxpos = cupy.zeros(labels.max().item() + 2, int)
          maxpos[labels[max_index]] = positions[max_index]
          result += [maxpos[idxs]]
      if find_median:
          locs = cupy.arange(len(labels))
          lo = cupy.zeros(int(labels.max()) + 2, int)
          lo[labels[min_index]] = locs[min_index]
          hi = cupy.zeros(int(labels.max()) + 2, int)
          hi[labels[max_index]] = locs[max_index]
          lo = lo[idxs]
          hi = hi[idxs]
          # lo is an index to the lowest value in input for each label,
          # hi is an index to the largest value.
          # move them to be either the same ((hi - lo) % 2 == 0) or next
          # to each other ((hi - lo) % 2 == 1), then average.
          step = (hi - lo) // 2
          lo += step
          hi -= step
          if input.dtype.kind in "iub":
              # fix for https://github.com/scipy/scipy/issues/12836
              result += [
                  (input[lo].astype(float) + input[hi].astype(float))
                  / 2.0
              ]
          else:
              result += [(input[lo] + input[hi]) / 2.0]
  
      return result
  
imports: import warnings
  import numpy
  import cupy
  from cupy import _core
  from cupy import _util
label_desc: Use image node_id 21 for calling a global function with example usage: _select(input, labels, index, find_min, find_max, find_min_positions, find_max_positions, find_median) and returns: result, result, single_group, single_group, single_group, _select_via_looping