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)
class_docstr_tok: ["Base","class","for","`","Corr3dMM","`",",","`","Corr3dMM_gradWeights","`","and","`","Corr3dMM_gradInputs","`",".","Can","not","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",")"]
docstr: This generates the C code for Corr3dMM (direction="forward"),
  Corr3dMM_gradWeights (direction="backprop weights"), and
  Corr3dMM_gradInputs (direction="backprop inputs").
  Depending on the direction, one of bottom, weights, top will
  receive the output, while the other two serve as inputs.
  
  :param bottom: Variable name of the input images in the forward pass,
      or the gradient of the input images in backprop wrt. inputs
  :param weights: Variable name of the filters in the forward pass,
      or the gradient of the filters in backprop wrt. weights
  :param top: Variable name of the output images / feature maps in the
      forward pass, or the gradient of the outputs in the backprop passes
  :param sub: Dictionary of substitutions useable to help generating the
      C code.
  :param height: If self.subsample[0] != 1, a variable giving the height
      of the filters for direction="backprop weights" or the height of
      the input images for direction="backprop inputs".
  
      If self.border_mode == 'half', a variable giving the height of the
      filters for direction="backprop weights".  Ignored otherwise.
  :param width: If self.subsample[1] != 1, a variable giving the width
      of the filters for direction="backprop weights" or the width of the
      input images for direction="backprop inputs".
  
      If self.border_mode == 'half', a variable giving the width of the
      filters for direction="backprop weights".  Ignored otherwise.
  :param depth: If self.subsample[1] != 1, a variable giving the depth
      of the filters for direction="backprop weights" or the depth of the
      input images for direction="backprop inputs".
  
      If self.border_mode == 'half', a variable giving the depth of the
      filters for direction="backprop weights".  Ignored otherwise.
docstr_tok: ["This","generates","the","C","code","for","Corr3dMM","(","direction=","''","forward","''",")",",","Corr3dMM_gradWeights","(","direction=","''","backprop","weights","''",")",",","and","Corr3dMM_gradInputs","(","direction=","''","backprop","inputs","''",")",".","Depending","on","the","direction",",","one","of","bottom",",","weights",",","top","will","receive","the","output",",","while","the","other","two","serve","as","inputs",".",":","param","bottom",":","Variable","name","of","the","input","images","in","the","forward","pass",",","or","the","gradient","of","the","input","images","in","backprop","wrt",".","inputs",":","param","weights",":","Variable","name","of","the","filters","in","the","forward","pass",",","or","the","gradient","of","the","filters","in","backprop","wrt",".","weights",":","param","top",":","Variable","name","of","the","output","images","\/","feature","maps","in","the","forward","pass",",","or","the","gradient","of","the","outputs","in","the","backprop","passes",":","param","sub",":","Dictionary","of","substitutions","useable","to","help","generating","the","C","code",".",":","param","height",":","If","self.subsample","[","0","]","!","=","1",",","a","variable","giving","the","height","of","the","filters","for","direction=","''","backprop","weights","''","or","the","height","of","the","input","images","for","direction=","''","backprop","inputs","''",".","If","self.border_mode","==","'half","'",",","a","variable","giving","the","height","of","the","filters","for","direction=","''","backprop","weights","''",".","Ignored","otherwise",".",":","param","width",":","If","self.subsample","[","1","]","!","=","1",",","a","variable","giving","the","width","of","the","filters","for","direction=","''","backprop","weights","''","or","the","width","of","the","input","images","for","direction=","''","backprop","inputs","''",".","If","self.border_mode","==","'half","'",",","a","variable","giving","the","width","of","the","filters","for","direction=","''","backprop","weights","''",".","Ignored","otherwise",".",":","param","depth",":","If","self.subsample","[","1","]","!","=","1",",","a","variable","giving","the","depth","of","the","filters","for","direction=","''","backprop","weights","''","or","the","depth","of","the","input","images","for","direction=","''","backprop","inputs","''",".","If","self.border_mode","==","'half","'",",","a","variable","giving","the","depth","of","the","filters","for","direction=","''","backprop","weights","''",".","Ignored","otherwise","."]
code: def c_code_helper(
      self,
      bottom,
      weights,
      top,
      sub,
      height=None,
      width=None,
      depth=None,
  ):
      """
      This generates the C code for Corr3dMM (direction="forward"),
      Corr3dMM_gradWeights (direction="backprop weights"), and
      Corr3dMM_gradInputs (direction="backprop inputs").
      Depending on the direction, one of bottom, weights, top will
      receive the output, while the other two serve as inputs.
  
      :param bottom: Variable name of the input images in the forward pass,
          or the gradient of the input images in backprop wrt. inputs
      :param weights: Variable name of the filters in the forward pass,
          or the gradient of the filters in backprop wrt. weights
      :param top: Variable name of the output images / feature maps in the
          forward pass, or the gradient of the outputs in the backprop passes
      :param sub: Dictionary of substitutions useable to help generating the
          C code.
      :param height: If self.subsample[0] != 1, a variable giving the height
          of the filters for direction="backprop weights" or the height of
          the input images for direction="backprop inputs".
  
          If self.border_mode == 'half', a variable giving the height of the
          filters for direction="backprop weights".  Ignored otherwise.
      :param width: If self.subsample[1] != 1, a variable giving the width
          of the filters for direction="backprop weights" or the width of the
          input images for direction="backprop inputs".
  
          If self.border_mode == 'half', a variable giving the width of the
          filters for direction="backprop weights".  Ignored otherwise.
      :param depth: If self.subsample[1] != 1, a variable giving the depth
          of the filters for direction="backprop weights" or the depth of the
          input images for direction="backprop inputs".
  
          If self.border_mode == 'half', a variable giving the depth of the
          filters for direction="backprop weights".  Ignored otherwise.
      """
  
      # When subsampling, we cannot unambiguously infer the height and width
      # of bottom and weights from top, so we require them to be given.
      # Similarly, when border_mode="half", we cannot infer the weight size.
      if height:
          height = "(*(npy_int64 *)(PyArray_DATA(%s)))" % height
      else:
          if ((self.direction != 0) and (self.dH != 1)) or (
              (self.direction == 1) and (self.padH == -1)
          ):
              raise ValueError(
                  "height must be given for backprop with vertical sampling or border_mode='half'"
              )
          height = "-1"
      if width:
          width = "(*(npy_int64 *)(PyArray_DATA(%s)))" % width
      else:
          if ((self.direction != 0) and (self.dW != 1)) or (
              (self.direction == 1) and (self.padW == -1)
          ):
              raise ValueError(
                  "width must be given for backprop with horizontal sampling or border_mode='half'"
              )
          width = "-1"
      if depth:
          depth = "(*(npy_int64 *)(PyArray_DATA(%s)))" % depth
      else:
          if ((self.direction != 0) and (self.dD != 1)) or (
              (self.direction == 1) and (self.padD == -1)
          ):
              raise ValueError(
                  "depth must be given for backprop with depth sampling or border_mode='half'"
              )
          depth = "-1"
  
      return """
      // Mandatory args
      int direction = %(params)s->direction;  // forward, bprop weights, bprop inputs
  
      // Optional args
      int dH = %(params)s->dH;
      int dW = %(params)s->dW;
      int dD = %(params)s->dD;
      int dilH = %(params)s->dilH;
      int dilW = %(params)s->dilW;
      int dilD = %(params)s->dilD;
      int padH = %(params)s->padH;
      int padW = %(params)s->padW;
      int padD = %(params)s->padD;
      int numgroups = %(params)s->num_groups;
  
      PyArrayObject * bottom = %(bottom)s;
      PyArrayObject * weights = %(weights)s;
      PyArrayObject * top = %(top)s;
      PyArrayObject * out2 = NULL;
      PyArrayObject **out = NULL;
  
      switch(%(params)s->direction) {
          case DIRECTION_FORWARD:
              out = &%(top)s;
              break;
          case DIRECTION_BACKPROP_WEIGHTS:
              out = &%(weights)s;
              break;
          case DIRECTION_BACKPROP_INPUTS:
              out = &%(bottom)s;
              break;
          default:
              PyErr_SetString(PyExc_ValueError, "CPU Corr3dMM: Invalid direction.");
              {%(fail)s}
              break;
      }
  
      // Obtain or infer kernel width, height and depth
      // (we need to know it early to be able to handle auto-padding)
      int kH, kW, kD, dil_kH, dil_kW, dil_kD;
      if (direction != 1) {
          // weight is an input variable, we can just read its shape
          kH = PyArray_DIMS(weights)[2];
          kW = PyArray_DIMS(weights)[3];
          kD = PyArray_DIMS(weights)[4];
      }
      else {
          if (%(height)s != -1) {
              // kernel height is specified (perhaps vertical subsampling or half padding)
              kH = %(height)s;
          }
          else if (padH == -2) {
              // vertical full padding, we can infer the kernel height
              kH = (2 - PyArray_DIMS(bottom)[2] + (PyArray_DIMS(top)[2] - 1) * dH - 1)/ dilH + 1;
          }
          else {
              // explicit padding, we can infer the kernel height
              kH = (PyArray_DIMS(bottom)[2] + 2*padH - (PyArray_DIMS(top)[2] - 1) * dH - 1) / dilH +1;
          }
          if (%(width)s != -1) {
              kW = %(width)s;
          }
          else if (padW == -2) {
              kW = (2 - PyArray_DIMS(bottom)[3] + (PyArray_DIMS(top)[3] - 1) * dW - 1) / dilW + 1;
          }
          else {
              kW = (PyArray_DIMS(bottom)[3] + 2*padW - (PyArray_DIMS(top)[3] - 1) * dW - 1) / dilW + 1;
          }
          if (%(depth)s != -1) {
              kD = %(depth)s;
          }
          else if (padD == -2) {
              kD = (2 - PyArray_DIMS(bottom)[4] + (PyArray_DIMS(top)[4] - 1) * dD - 1) / dilD + 1;
          }
          else {
              kD = (PyArray_DIMS(bottom)[4] + 2*padD - (PyArray_DIMS(top)[4] - 1) * dD - 1) / dilD + 1;
          }
      }
  
      // Implicit dilated kernel size
      dil_kH = (kH - 1) * dilH + 1;
      dil_kW = (kW - 1) * dilW + 1;
      dil_kD = (kD - 1) * dilD + 1;
  
      // Auto-padding if requested
      if (padH == -1) {  // vertical half padding
          padH = dil_kH / 2;
      }
      else if (padH == -2) {  // vertical full padding
          padH = dil_kH - 1;
      }
      else if (padH < 0) {
          PyErr_SetString(PyExc_ValueError, "BaseCorr3dMM: padH must be >= -2");
          %(fail)s
      }
      if (padW == -1) {  // horizontal half padding
          padW = dil_kW / 2;
      }
      else if (padW == -2) {  // horizontal full padding
          padW = dil_kW - 1;
      }
      else if (padW < 0) {
          PyErr_SetString(PyExc_ValueError, "BaseCorr3dMM: padW must be >= -2");
          %(fail)s
      }
      if (padD == -1) {  // depth half padding
          padD = dil_kD / 2;
      }
      else if (padD == -2) {  // depth full padding
          padD = dil_kD - 1;
      }
      else if (padD < 0) {
          PyErr_SetString(PyExc_ValueError, "BaseCorr3dMM: padD must be >= -2");
          %(fail)s
      }
  
      // Infer output shape
      npy_intp out_dim[5];
      switch(direction) {
      case 0:  // forward pass
          // output is top: (batchsize, num_filters, height, width, depth)
          // height and width: top = (bottom + 2*pad - ((weight-1)*dil + 1)) / sample + 1
          out_dim[0] = (npy_intp)PyArray_DIMS(bottom)[0];
          out_dim[1] = (npy_intp)PyArray_DIMS(weights)[0];
          out_dim[2] = (npy_intp)((PyArray_DIMS(bottom)[2] + 2*padH - ((PyArray_DIMS(weights)[2]-1)*dilH + 1)) / dH + 1);
          out_dim[3] = (npy_intp)((PyArray_DIMS(bottom)[3] + 2*padW - ((PyArray_DIMS(weights)[3]-1)*dilW + 1)) / dW + 1);
          out_dim[4] = (npy_intp)((PyArray_DIMS(bottom)[4] + 2*padD - ((PyArray_DIMS(weights)[4]-1)*dilD + 1)) / dD + 1);
          if (out_dim[0] < 0 || out_dim[1] < 0 || out_dim[2] <= 0 || out_dim[3] <= 0 || out_dim[4] <= 0)
          {
              PyErr_Format(PyExc_ValueError,
                           "Corr3dMM: impossible output shape\\n"
                           "  bottom shape: %%ld x %%ld x %%ld x %%ld x %%ld\\n"
                           "  weights shape: %%ld x %%ld x %%ld x %%ld x %%ld\\n"
                           "  top shape: %%ld x %%ld x %%ld x %%ld x %%ld\\n",
                           (long int)PyArray_DIMS(bottom)[0], (long int)PyArray_DIMS(bottom)[1],
                           (long int)PyArray_DIMS(bottom)[2], (long int)PyArray_DIMS(bottom)[3],
                           (long int)PyArray_DIMS(bottom)[4],
                           (long int)PyArray_DIMS(weights)[0], (long int)PyArray_DIMS(weights)[1],
                           (long int)PyArray_DIMS(weights)[2], (long int)PyArray_DIMS(weights)[3],
                           (long int)PyArray_DIMS(weights)[4],
                           (long int)out_dim[0], (long int)out_dim[1], (long int)out_dim[2],
                           (long int)out_dim[3], (long int)out_dim[4]);
              %(fail)s
          }
          break;
      case 1:  // backprop wrt. weights
          // output is weights: (num_filters, num_channels, height, width, depth)
          // height and width: weights = (bottom + 2*pad - (top - 1) * sample - 1) / dil + 1
          out_dim[0] = (npy_intp)PyArray_DIMS(top)[1];
          out_dim[1] = (npy_intp)PyArray_DIMS(bottom)[1] / numgroups;
          out_dim[2] = (npy_intp)kH;  // already inferred further above
          out_dim[3] = (npy_intp)kW;  // how convenient
          out_dim[4] = (npy_intp)kD;
          if (out_dim[0] < 0 || out_dim[1] < 0 || out_dim[2] <= 0 || out_dim[3] <= 0 || out_dim[4] <= 0)
          {
              PyErr_Format(PyExc_ValueError,
                           "Corr3dMM backprop wrt. weights: impossible output shape\\n"
                           "  bottom shape: %%ld x %%ld x %%ld x %%ld x %%ld\\n"
                           "  weights shape: %%ld x %%ld x %%ld x %%ld x %%ld\\n"
                           "  top shape: %%ld x %%ld x %%ld x %%ld x %%ld\\n",
                           (long int)PyArray_DIMS(bottom)[0], (long int)PyArray_DIMS(bottom)[1],
                           (long int)PyArray_DIMS(bottom)[2], (long int)PyArray_DIMS(bottom)[3],
                           (long int)PyArray_DIMS(bottom)[4],
                           (long int)out_dim[0], (long int)out_dim[1], (long int)out_dim[2],
                           (long int)out_dim[3], (long int)out_dim[4],
                           (long int)PyArray_DIMS(top)[0], (long int)PyArray_DIMS(top)[1],
                           (long int)PyArray_DIMS(top)[2], (long int)PyArray_DIMS(top)[3],
                           (long int)PyArray_DIMS(top)[4]);
              %(fail)s
          }
          break;
      case 2:  // backprop wrt. inputs
          // output is bottom: (batchsize, num_channels, height, width, depth)
          // height and width: bottom = (top - 1) * sample + (weights-1)*dil + 1 - 2*pad
          out_dim[0] = (npy_intp)PyArray_DIMS(top)[0];
          out_dim[1] = (npy_intp)PyArray_DIMS(weights)[1] * numgroups;
          out_dim[2] = (npy_intp)((%(height)s != -1) ? %(height)s : (PyArray_DIMS(top)[2] - 1) * dH + (PyArray_DIMS(weights)[2]-1)*dilH + 1 - 2*padH);
          out_dim[3] = (npy_intp)((%(width)s != -1) ? %(width)s : (PyArray_DIMS(top)[3] - 1) * dW + (PyArray_DIMS(weights)[3]-1)*dilW + 1 - 2*padW);
          out_dim[4] = (npy_intp)((%(depth)s != -1) ? %(depth)s : (PyArray_DIMS(top)[4] - 1) * dD + (PyArray_DIMS(weights)[4]-1)*dilD + 1 - 2*padD);
          if (out_dim[0] < 0 || out_dim[1] < 0 || out_dim[2] <= 0 || out_dim[3] <= 0 || out_dim[4] <= 0)
          {
              PyErr_Format(PyExc_ValueError,
                           "Corr3dMM backprop wrt. inputs: impossible output shape\\n"
                           "  bottom shape: %%ld x %%ld x %%ld x %%ld x %%ld\\n"
                           "  weights shape: %%ld x %%ld x %%ld x %%ld x %%ld\\n"
                           "  top shape: %%ld x %%ld x %%ld x %%ld x %%ld\\n",
                           (long int)out_dim[0], (long int)out_dim[1], (long int)out_dim[2],
                           (long int)out_dim[3], (long int)out_dim[4],
                           (long int)PyArray_DIMS(weights)[0], (long int)PyArray_DIMS(weights)[1],
                           (long int)PyArray_DIMS(weights)[2], (long int)PyArray_DIMS(weights)[3],
                           (long int)PyArray_DIMS(weights)[4],
                           (long int)PyArray_DIMS(top)[0], (long int)PyArray_DIMS(top)[1],
                           (long int)PyArray_DIMS(top)[2], (long int)PyArray_DIMS(top)[3],
                           (long int)PyArray_DIMS(top)[4]);
              %(fail)s
          }
          break;
      default:
          PyErr_SetString(PyExc_ValueError, "BaseCorr3dMM: direction must be 0, 1, or 2\\n");
          %(fail)s
      }
  
      // Prepare output array
      int typenum;
      if ( !(*out
             && PyArray_NDIM(*out)==4
             && PyArray_IS_C_CONTIGUOUS(*out)
             && PyArray_DIMS(*out)[0]==out_dim[0]
             && PyArray_DIMS(*out)[1]==out_dim[1]
             && PyArray_DIMS(*out)[2]==out_dim[2]
             && PyArray_DIMS(*out)[3]==out_dim[3]
             && PyArray_DIMS(*out)[4]==out_dim[4]))
      {
          Py_XDECREF(*out);
          if (direction != 1) {
            typenum = PyArray_TYPE(weights);
          }
          else {
            typenum = PyArray_TYPE(bottom);
          }
          //Change to PyArray_ZEROS which is faster than PyArray_EMPTY.
          *out = (PyArrayObject*)PyArray_ZEROS(5,
                                            out_dim,
                                            typenum,
                                            0);
          if (NULL == *out)
          {
              PyErr_Format(PyExc_RuntimeError,
                      "BaseCorr3dMM: Failed to allocate output of %%lld x %%lld x %%lld x %%lld x %%lld",
                      (long long)out_dim[0], (long long)out_dim[1],
                      (long long)out_dim[2], (long long)out_dim[3], (long long)out_dim[4]);
              %(fail)s
          }
      }
  
      // Call corr3dMM code
      out2 = corr3dMM(%(bottom)s, %(weights)s, %(top)s, direction,
                      dH, dW, dD, dilH, dilW, dilD, padH, padW, padD,
                      numgroups);
      if (out2==NULL){
         %(fail)s
      }
      assert (out2 == *out);
  
  """ % dict(
          bottom=bottom,
          weights=weights,
          top=top,
          height=height,
          width=width,
          depth=depth,
          fail=sub["fail"],
          params=sub["params"],
      )
  
imports: from __future__ import absolute_import, print_function, division
  import os
  import logging
  from six import integer_types
  import theano
  from theano import Apply
  from theano import gof
  from theano.gof import ParamsType, EnumList
  from theano.scalar import int64
  from theano.tensor import as_tensor_variable, TensorType
  from theano.tensor.nnet.abstract_conv import get_conv_output_shape
  from theano.tensor import blas_headers
  from theano.tensor.blas import ldflags, blas_header_version
label_desc: Use image node_id 14 for calling the BaseCorr3dMM obj's underlying member method code with example usage: obj.c_code_helper(bottom, weights, top, sub, height, width, depth) and returns: unknown