code: def pad(array, pad_width, mode="constant", **kwargs):
      """
      Pad an array.
  
      Parameters
      ----------
      array : array_like of rank N
          The array to pad.
      pad_width : {sequence, array_like, int}
          Number of values padded to the edges of each axis.
          ``((before_1, after_1), ... (before_N, after_N))`` unique pad widths
          for each axis.
          ``(before, after)`` or ``((before, after),)`` yields same before
          and after pad for each axis.
          ``(pad,)`` or ``int`` is a shortcut for before = after = pad width
          for all axes.
      mode : str or function, optional
          One of the following string values or a user supplied function.
  
          'constant' (default)
              Pads with a constant value.
          'edge'
              Pads with the edge values of array.
          'linear_ramp'
              Pads with the linear ramp between end_value and the
              array edge value.
          'maximum'
              Pads with the maximum value of all or part of the
              vector along each axis.
          'mean'
              Pads with the mean value of all or part of the
              vector along each axis.
          'median'
              Pads with the median value of all or part of the
              vector along each axis.
          'minimum'
              Pads with the minimum value of all or part of the
              vector along each axis.
          'reflect'
              Pads with the reflection of the vector mirrored on
              the first and last values of the vector along each
              axis.
          'symmetric'
              Pads with the reflection of the vector mirrored
              along the edge of the array.
          'wrap'
              Pads with the wrap of the vector along the axis.
              The first values are used to pad the end and the
              end values are used to pad the beginning.
          'empty'
              Pads with undefined values.
  
              .. versionadded:: 1.17
  
          <function>
              Padding function, see Notes.
      stat_length : sequence or int, optional
          Used in 'maximum', 'mean', 'median', and 'minimum'.  Number of
          values at edge of each axis used to calculate the statistic value.
  
          ``((before_1, after_1), ... (before_N, after_N))`` unique statistic
          lengths for each axis.
  
          ``(before, after)`` or ``((before, after),)`` yields same before
          and after statistic lengths for each axis.
  
          ``(stat_length,)`` or ``int`` is a shortcut for
          ``before = after = statistic`` length for all axes.
  
          Default is ``None``, to use the entire axis.
      constant_values : sequence or scalar, optional
          Used in 'constant'.  The values to set the padded values for each
          axis.
  
          ``((before_1, after_1), ... (before_N, after_N))`` unique pad constants
          for each axis.
  
          ``(before, after)`` or ``((before, after),)`` yields same before
          and after constants for each axis.
  
          ``(constant,)`` or ``constant`` is a shortcut for
          ``before = after = constant`` for all axes.
  
          Default is 0.
      end_values : sequence or scalar, optional
          Used in 'linear_ramp'.  The values used for the ending value of the
          linear_ramp and that will form the edge of the padded array.
  
          ``((before_1, after_1), ... (before_N, after_N))`` unique end values
          for each axis.
  
          ``(before, after)`` or ``((before, after),)`` yields same before
          and after end values for each axis.
  
          ``(constant,)`` or ``constant`` is a shortcut for
          ``before = after = constant`` for all axes.
  
          Default is 0.
      reflect_type : {'even', 'odd'}, optional
          Used in 'reflect', and 'symmetric'.  The 'even' style is the
          default with an unaltered reflection around the edge value.  For
          the 'odd' style, the extended part of the array is created by
          subtracting the reflected values from two times the edge value.
  
      Returns
      -------
      pad : ndarray
          Padded array of rank equal to `array` with shape increased
          according to `pad_width`.
  
      Notes
      -----
      .. versionadded:: 1.7.0
  
      For an array with rank greater than 1, some of the padding of later
      axes is calculated from padding of previous axes.  This is easiest to
      think about with a rank 2 array where the corners of the padded array
      are calculated by using padded values from the first axis.
  
      The padding function, if used, should modify a rank 1 array in-place. It
      has the following signature::
  
          padding_func(vector, iaxis_pad_width, iaxis, kwargs)
  
      where
  
      vector : ndarray
          A rank 1 array already padded with zeros.  Padded values are
          vector[:iaxis_pad_width[0]] and vector[-iaxis_pad_width[1]:].
      iaxis_pad_width : tuple
          A 2-tuple of ints, iaxis_pad_width[0] represents the number of
          values padded at the beginning of vector where
          iaxis_pad_width[1] represents the number of values padded at
          the end of vector.
      iaxis : int
          The axis currently being calculated.
      kwargs : dict
          Any keyword arguments the function requires.
  
      Examples
      --------
      >>> a = [1, 2, 3, 4, 5]
      >>> np.pad(a, (2, 3), 'constant', constant_values=(4, 6))
      array([4, 4, 1, ..., 6, 6, 6])
  
      >>> np.pad(a, (2, 3), 'edge')
      array([1, 1, 1, ..., 5, 5, 5])
  
      >>> np.pad(a, (2, 3), 'linear_ramp', end_values=(5, -4))
      array([ 5,  3,  1,  2,  3,  4,  5,  2, -1, -4])
  
      >>> np.pad(a, (2,), 'maximum')
      array([5, 5, 1, 2, 3, 4, 5, 5, 5])
  
      >>> np.pad(a, (2,), 'mean')
      array([3, 3, 1, 2, 3, 4, 5, 3, 3])
  
      >>> np.pad(a, (2,), 'median')
      array([3, 3, 1, 2, 3, 4, 5, 3, 3])
  
      >>> a = [[1, 2], [3, 4]]
      >>> np.pad(a, ((3, 2), (2, 3)), 'minimum')
      array([[1, 1, 1, 2, 1, 1, 1],
             [1, 1, 1, 2, 1, 1, 1],
             [1, 1, 1, 2, 1, 1, 1],
             [1, 1, 1, 2, 1, 1, 1],
             [3, 3, 3, 4, 3, 3, 3],
             [1, 1, 1, 2, 1, 1, 1],
             [1, 1, 1, 2, 1, 1, 1]])
  
      >>> a = [1, 2, 3, 4, 5]
      >>> np.pad(a, (2, 3), 'reflect')
      array([3, 2, 1, 2, 3, 4, 5, 4, 3, 2])
  
      >>> np.pad(a, (2, 3), 'reflect', reflect_type='odd')
      array([-1,  0,  1,  2,  3,  4,  5,  6,  7,  8])
  
      >>> np.pad(a, (2, 3), 'symmetric')
      array([2, 1, 1, 2, 3, 4, 5, 5, 4, 3])
  
      >>> np.pad(a, (2, 3), 'symmetric', reflect_type='odd')
      array([0, 1, 1, 2, 3, 4, 5, 5, 6, 7])
  
      >>> np.pad(a, (2, 3), 'wrap')
      array([4, 5, 1, 2, 3, 4, 5, 1, 2, 3])
  
      >>> def pad_with(vector, pad_width, iaxis, kwargs):
      ...     pad_value = kwargs.get('padder', 10)
      ...     vector[:pad_width[0]] = pad_value
      ...     vector[-pad_width[1]:] = pad_value
      >>> a = np.arange(6)
      >>> a = a.reshape((2, 3))
      >>> np.pad(a, 2, pad_with)
      array([[10, 10, 10, 10, 10, 10, 10],
             [10, 10, 10, 10, 10, 10, 10],
             [10, 10,  0,  1,  2, 10, 10],
             [10, 10,  3,  4,  5, 10, 10],
             [10, 10, 10, 10, 10, 10, 10],
             [10, 10, 10, 10, 10, 10, 10]])
      >>> np.pad(a, 2, pad_with, padder=100)
      array([[100, 100, 100, 100, 100, 100, 100],
             [100, 100, 100, 100, 100, 100, 100],
             [100, 100,   0,   1,   2, 100, 100],
             [100, 100,   3,   4,   5, 100, 100],
             [100, 100, 100, 100, 100, 100, 100],
             [100, 100, 100, 100, 100, 100, 100]])
      """
      array = np.asarray(array)
      pad_width = np.asarray(pad_width)
  
      if not pad_width.dtype.kind == "i":
          raise TypeError("`pad_width` must be of integral type.")
  
      # Broadcast to shape (array.ndim, 2)
      pad_width = _as_pairs(pad_width, array.ndim, as_index=True)
  
      if callable(mode):
          # Old behavior: Use user-supplied function with np.apply_along_axis
          function = mode
          # Create a new zero padded array
          padded, _ = _pad_simple(array, pad_width, fill_value=0)
          # And apply along each axis
  
          for axis in range(padded.ndim):
              # Iterate using ndindex as in apply_along_axis, but assuming that
              # function operates inplace on the padded array.
  
              # view with the iteration axis at the end
              view = np.moveaxis(padded, axis, -1)
  
              # compute indices for the iteration axes, and append a trailing
              # ellipsis to prevent 0d arrays decaying to scalars (gh-8642)
              inds = ndindex(view.shape[:-1])
              inds = (ind + (Ellipsis,) for ind in inds)
              for ind in inds:
                  function(view[ind], pad_width[axis], axis, kwargs)
  
          return padded
  
      # Make sure that no unsupported keywords were passed for the current mode
      allowed_kwargs = {
          "empty": [],
          "edge": [],
          "wrap": [],
          "constant": ["constant_values"],
          "linear_ramp": ["end_values"],
          "maximum": ["stat_length"],
          "mean": ["stat_length"],
          "median": ["stat_length"],
          "minimum": ["stat_length"],
          "reflect": ["reflect_type"],
          "symmetric": ["reflect_type"],
      }
      try:
          unsupported_kwargs = set(kwargs) - set(allowed_kwargs[mode])
      except KeyError:
          raise ValueError(
              "mode '{}' is not supported".format(mode)
          ) from None
      if unsupported_kwargs:
          raise ValueError(
              "unsupported keyword arguments for mode '{}': {}".format(
                  mode, unsupported_kwargs
              )
          )
  
      stat_functions = {
          "maximum": np.amax,
          "minimum": np.amin,
          "mean": np.mean,
          "median": np.median,
      }
  
      # Create array with final shape and original values
      # (padded area is undefined)
      padded, original_area_slice = _pad_simple(array, pad_width)
      # And prepare iteration over all dimensions
      # (zipping may be more readable than using enumerate)
      axes = range(padded.ndim)
  
      if mode == "constant":
          values = kwargs.get("constant_values", 0)
          values = _as_pairs(values, padded.ndim)
          for axis, width_pair, value_pair in zip(
              axes, pad_width, values
          ):
              roi = _view_roi(padded, original_area_slice, axis)
              _set_pad_area(roi, axis, width_pair, value_pair)
  
      elif mode == "empty":
          pass  # Do nothing as _pad_simple already returned the correct result
  
      elif array.size == 0:
          # Only modes "constant" and "empty" can extend empty axes, all other
          # modes depend on `array` not being empty
          # -> ensure every empty axis is only "padded with 0"
          for axis, width_pair in zip(axes, pad_width):
              if array.shape[axis] == 0 and any(width_pair):
                  raise ValueError(
                      "can't extend empty axis {} using modes other than "
                      "'constant' or 'empty'".format(axis)
                  )
          # passed, don't need to do anything more as _pad_simple already
          # returned the correct result
  
      elif mode == "edge":
          for axis, width_pair in zip(axes, pad_width):
              roi = _view_roi(padded, original_area_slice, axis)
              edge_pair = _get_edges(roi, axis, width_pair)
              _set_pad_area(roi, axis, width_pair, edge_pair)
  
      elif mode == "linear_ramp":
          end_values = kwargs.get("end_values", 0)
          end_values = _as_pairs(end_values, padded.ndim)
          for axis, width_pair, value_pair in zip(
              axes, pad_width, end_values
          ):
              roi = _view_roi(padded, original_area_slice, axis)
              ramp_pair = _get_linear_ramps(
                  roi, axis, width_pair, value_pair
              )
              _set_pad_area(roi, axis, width_pair, ramp_pair)
  
      elif mode in stat_functions:
          func = stat_functions[mode]
          length = kwargs.get("stat_length", None)
          length = _as_pairs(length, padded.ndim, as_index=True)
          for axis, width_pair, length_pair in zip(
              axes, pad_width, length
          ):
              roi = _view_roi(padded, original_area_slice, axis)
              stat_pair = _get_stats(
                  roi, axis, width_pair, length_pair, func
              )
              _set_pad_area(roi, axis, width_pair, stat_pair)
  
      elif mode in {"reflect", "symmetric"}:
          method = kwargs.get("reflect_type", "even")
          include_edge = True if mode == "symmetric" else False
          for axis, (left_index, right_index) in zip(axes, pad_width):
              if array.shape[axis] == 1 and (
                  left_index > 0 or right_index > 0
              ):
                  # Extending singleton dimension for 'reflect' is legacy
                  # behavior; it really should raise an error.
                  edge_pair = _get_edges(
                      padded, axis, (left_index, right_index)
                  )
                  _set_pad_area(
                      padded, axis, (left_index, right_index), edge_pair
                  )
                  continue
  
              roi = _view_roi(padded, original_area_slice, axis)
              while left_index > 0 or right_index > 0:
                  # Iteratively pad until dimension is filled with reflected
                  # values. This is necessary if the pad area is larger than
                  # the length of the original values in the current dimension.
                  left_index, right_index = _set_reflect_both(
                      roi,
                      axis,
                      (left_index, right_index),
                      method,
                      include_edge,
                  )
  
      elif mode == "wrap":
          for axis, (left_index, right_index) in zip(axes, pad_width):
              roi = _view_roi(padded, original_area_slice, axis)
              original_period = (
                  padded.shape[axis] - right_index - left_index
              )
              while left_index > 0 or right_index > 0:
                  # Iteratively pad until dimension is filled with wrapped
                  # values. This is necessary if the pad area is larger than
                  # the length of the original values in the current dimension.
                  left_index, right_index = _set_wrap_both(
                      roi,
                      axis,
                      (left_index, right_index),
                      original_period,
                  )
  
      return padded
  
file_path: numpy/numpy/lib/_arraypad_impl.py
imports: import numpy
  from numpy._core.overrides import array_function_dispatch
  from numpy.lib._index_tricks_impl import ndindex
label_desc: Use image node_id 13 for calling a global function with example usage: pad(array, pad_width, mode) and returns: padded, padded