code: def pool(
      padded: np.ndarray,
      x_shape: Sequence[int],
      kernel: Sequence[int],
      strides: Sequence[int],
      out_shape: Sequence[int],
      pooling_type: str,
      pads: Union[Sequence[int], None] = None,
      dilations: Union[Sequence[int], None] = None,
      count_include_pad: int = 0,
      p: int = 1,
  ) -> np.ndarray:
      """This function is used to calculate the pooling result of a padded tensor
      padded: the padded tensor
      x_shape: the shape of the original tensor in [N, C, *spatial_shape]
      kernel: the pooling kernel
      strides: the strides
      out_shape: the shape of the output tensor
      pooling_type: the pooling type, can be "AVG", "LPPOOL", or "MAX"
      pads: the padding in an order of head_pad_1, head_pad_2, ..., tail_pad_1, tail_pad_2, ...
      dilations: the dilation
      count_include_pad: whether to include the padding in the calculation of average and lp pooling
      p: the p value for lp pooling
      """
      spatial_size = len(x_shape) - 2
      y = np.zeros(
          [x_shape[0], x_shape[1], *list(out_shape)], dtype=padded.dtype
      )
      if dilations is None:
          dilations = np.ones([spatial_size], dtype=np.int64)
      if pads is None:
          pads = np.zeros([spatial_size * 2], dtype=np.int64)
      elif len(pads) == 1:
          pads = pads * spatial_size * 2
      strides = strides or [1] * spatial_size
  
      def lp_pool_p(x):
          return lp_pool(x, p)
  
      for shape in itertools.product(
          range(x_shape[0]),
          range(x_shape[1]),
          *[
              range(
                  int(
                      (
                          x_shape[i + 2]
                          + pads[i]
                          + pads[i + spatial_size]
                          - (1 + (kernel[i] - 1) * dilations[i])
                      )
                      / strides[i]
                      + 1
                  )
              )
              for i in range(spatial_size)
          ],
      ):
          window = padded[shape[0], shape[1]]
          window_vals = np.array(
              [
                  window[i]
                  for i in list(
                      itertools.product(
                          *[
                              range(
                                  strides[i] * shape[i + 2],
                                  strides[i] * shape[i + 2]
                                  + (
                                      1 + (kernel[i] - 1) * dilations[i]
                                  ),
                                  dilations[i],
                              )
                              for i in range(spatial_size)
                          ]
                      )
                  )
              ]
          )
          if pooling_type == "AVG":
              f = np.average
          elif pooling_type == "MAX":
              f = np.max
          elif pooling_type == "LPPOOL":
              f = lp_pool_p
          else:
              raise NotImplementedError(
                  f"Pooling type {pooling_type} does not support. Should be AVG, MAX"
              )
  
          if count_include_pad == 1 and (
              pooling_type in {"AVG", "LPPOOL"}
          ):
              y[shape] = f(window_vals)
          else:
              y[shape] = f(
                  window_vals[np.where(~np.isnan(window_vals))]
              )
      return y
  
file_path: onnx/onnx/reference/ops/op_pool_common.py
imports: import itertools
  import math
  from typing import Sequence, Tuple, Union
  import numpy
  from onnx.reference.op_run import OpRun
label_desc: Use image node_id 6 for calling a global function with example usage: pool(padded, x_shape, kernel, strides, out_shape, pooling_type, pads, dilations, count_include_pad, p) and returns: y, lp_pool