class_docstr: Base class for `Corr3dMM`, `Corr3dMM_gradWeights` and
  `Corr3dMM_gradInputs`. Cannot be used directly.
  
  Every sub-class must define internal attribute ``_direction`` out of __init__().
  ``_direction`` must take one of following values:
  
   - "forward" to correlate bottom with weights and store results in top.
   - "backprop weights" to do a valid convolution of bottom with top
     (swapping the first two dimensions) and store results in weights.
   - "backprop inputs" to do a full convolution of top with weights
     (swapping the first two dimensions) and store results in bottom.
  
  Parameters
  ----------
  border_mode : {'valid', 'full', 'half'}
      Additionally, the padding size could be directly specified by an integer
      or a tuple of three of integers
  subsample
      Perform subsampling of the output (default: (1, 1, 1)).
  filter_dilation
      Perform dilated correlation (default: (1, 1, 1))
  num_groups
      Perform grouped convolutions (default: 1)
code: def c_support_code_apply(self, node, nodename):
      # REMEMBER TO RAISE c_code_cache_version when changing any of
      # these files
      sub = {}
      dtype = str(node.__dict__["inputs"][0].dtype)
      assert dtype in ("float32", "float64")
      if dtype == "float32":
          sub["gemm"] = "sgemm_"
          sub["float_type"] = "npy_float"
          sub["float_typenum"] = "NPY_FLOAT"
          sub["n_bytes"] = 4
          sub["c_float_type"] = "float"
      else:
          sub["gemm"] = "dgemm_"
          sub["float_type"] = "npy_double"
          sub["float_typenum"] = "NPY_DOUBLE"
          sub["n_bytes"] = 8
          sub["c_float_type"] = "double"
  
      if self.openmp:
          sub["omp_flags"] = "#pragma omp parallel for schedule(static)"
          sub["omp_get_max_threads"] = "omp_get_max_threads()"
          sub["omp_get_thread_num"] = "omp_get_thread_num()"
  
          if self.blas_type == "openblas":
              sub["blas_set_num_threads"] = "openblas_set_num_threads"
              sub["blas_get_num_threads"] = "openblas_get_num_threads()"
          elif self.blas_type == "mkl":
              sub["blas_set_num_threads"] = "mkl_set_num_threads"
              sub["blas_get_num_threads"] = "mkl_get_max_threads()"
          else:
              sub["blas_set_num_threads"] = ""
              sub["blas_get_num_threads"] = "0"
      else:
          sub["omp_flags"] = ""
          sub["omp_get_max_threads"] = "1"
          sub["omp_get_thread_num"] = "0"
          sub["blas_set_num_threads"] = ""
          sub["blas_get_num_threads"] = "0"
  
      final_code = ""
      with open(
          os.path.join(
              os.path.split(__file__)[0],
              os.path.join("c_code", "corr3d_gemm.c"),
          )
      ) as f:
          code = f.read()
          final_code += code
      return final_code % sub
  
imports: import logging
  import os
  from typing import Optional
  import pytensor
  from pytensor.configdefaults import config
  from pytensor.graph.basic import Apply
  from pytensor.graph.op import _NoPythonOp
  from pytensor.link.c.op import OpenMPOp
  from pytensor.link.c.params_type import ParamsType
  from pytensor.link.c.type import EnumList
  from pytensor.scalar import int64
  from pytensor.tensor import blas_headers
  from pytensor.tensor.basic import as_tensor_variable
  from pytensor.tensor.blas import blas_header_version, ldflags
  from pytensor.tensor.conv.abstract_conv import get_conv_output_shape
  from pytensor.tensor.type import TensorType
label_desc: Use image node_id 13 for calling the BaseCorr3dMM obj's underlying member method code with example usage: obj.c_support_code_apply(node, nodename) and returns: unknown