class_docstr: Reshapes the input as a 2D tensor where each row is an pooling
  example.
  
  Parameters
  ----------
  mode : {'valid', 'ignore_borders', 'wrap_centered'}
      - 'valid' :
          Requires an input that is a multiple of the pooling factor
          (in each direction).
      - 'half' :
          Equivalent to 'valid' if we pre-pad with zeros the input on
          each side by (neib_shape[0]//2, neib_shape[1]//2)
      - 'full' :
          Equivalent to 'valid' if we pre-pad with zeros the input on
          each side by (neib_shape[0] - 1, neib_shape[1] - 1)
      - 'ignore_borders' :
          Same as valid, but will ignore the borders if the shape(s)
          of the input is not a multiple of the pooling factor(s).
      - 'wrap_centered' :
          ?? TODO comment
class_docstr_tok: ["Reshapes","the","input","as","a","2D","tensor","where","each","row","is","an","pooling","example",".","Parameters","--","--","--","--","--","mode",":","{","'valid","'",",","'ignore_borders","'",",","'wrap_centered","'","}","-","'valid","'",":","Requires","an","input","that","is","a","multiple","of","the","pooling","factor","(","in","each","direction",")",".","-","'half","'",":","Equivalent","to","'valid","'","if","we","pre-pad","with","zeros","the","input","on","each","side","by","(","neib_shape","[","0","]","\/\/2",",","neib_shape","[","1","]","\/\/2",")","-","'full","'",":","Equivalent","to","'valid","'","if","we","pre-pad","with","zeros","the","input","on","each","side","by","(","neib_shape","[","0","]","-","1",",","neib_shape","[","1","]","-","1",")","-","'ignore_borders","'",":","Same","as","valid",",","but","will","ignore","the","borders","if","the","shape","(","s",")","of","the","input","is","not","a","multiple","of","the","pooling","factor","(","s",")",".","-","'wrap_centered","'",":","?","?","TODO","comment"]
code: def c_code(self, node, name, inp, out, sub):
      return """
  #ifndef CEIL_INTDIV
  #define CEIL_INTDIV(a, b) ((a/b) + ((a %% b) ? 1: 0))
  #endif
  
          int grid_c = -1; //number of patch in height
          int grid_d = -1; //number of patch in width
          {
          if (PyArray_NDIM(%(ten4)s) != 4)
          {
              PyErr_Format(PyExc_TypeError, "ten4 wrong rank");
              %(fail)s;
          }
          if (PyArray_NDIM(%(neib_shape)s) != 1)
          {
              PyErr_Format(PyExc_TypeError, "neib_shape wrong rank");
              %(fail)s;
          }
          if ( (PyArray_DIMS(%(neib_shape)s))[0] != 2)
          {
              PyErr_Format(PyExc_TypeError, "neib_shape wrong shape ; has to"
                                            " contain 2 elements");
              %(fail)s;
          }
          if (PyArray_NDIM(%(neib_step)s) != 1)
          {
              PyErr_Format(PyExc_TypeError, "neib_step wrong rank");
              %(fail)s;
          }
          if ( (PyArray_DIMS(%(neib_step)s))[0] != 2)
          {
              PyErr_Format(PyExc_TypeError,
                           "neib_step wrong step ; has to contain 2 elements");
              %(fail)s;
          }
  
          // (c,d) = neib_shape
          const npy_intp c = (npy_intp) *(dtype_%(neib_shape)s*) PyArray_GETPTR1(%(neib_shape)s, 0);
          const npy_intp d = (npy_intp) *(dtype_%(neib_shape)s*) PyArray_GETPTR1(%(neib_shape)s, 1);
          // (step_x,step_y) = neib_step
          const dtype_%(neib_step)s step_x = *(dtype_%(neib_step)s*) PyArray_GETPTR1(%(neib_step)s, 0);
          const dtype_%(neib_step)s step_y = *(dtype_%(neib_step)s*) PyArray_GETPTR1(%(neib_step)s, 1);
  
          if (step_x <=0 || step_y <=0)
          {
              PyErr_Format(PyExc_ValueError,
                           "neib_step wrong step ; values <= 0. Got %%lld %%lld.",
                           (long long) step_x, (long long) step_y);
              %(fail)s;
          }
  
          if (c <=0 || d <=0)
          {
              PyErr_Format(PyExc_ValueError,
                           "neib_shape values <= 0. Got %%lld %%lld.",
                           (long long)c, (long long)d);
              %(fail)s;
          }
  
          if (%(mode)s == MODE_WRAP_CENTERED) {
              if (c%%2!=1 || d%%2!=1){
                  PyErr_Format(PyExc_TypeError,
                               "Images2Neibs: in mode wrap_centered"
                               " need patch with odd shapes");
                  %(fail)s;
              }
              if ( (PyArray_DIMS(%(ten4)s))[2] < c ||
                   (PyArray_DIMS(%(ten4)s))[3] < d)
              {
                  PyErr_Format(PyExc_TypeError,
                      "Images2Neibs: in wrap_centered mode, don't support image"
                      " shapes smaller then the patch shapes:"
                      " neib_shape=(%%ld,%%ld), ten4[2:]=[%%ld,%%ld]",
                      (long int)c, (long int)d,
                      (long int)(PyArray_DIMS(%(ten4)s)[2]),
                      (long int)(PyArray_DIMS(%(ten4)s)[3]));
                  %(fail)s;
              }
              grid_c = CEIL_INTDIV(((PyArray_DIMS(%(ten4)s))[2]),step_x);
              grid_d = CEIL_INTDIV(((PyArray_DIMS(%(ten4)s))[3]),step_y);
  
          } else if (%(mode)s == MODE_VALID) {
              if ( ((PyArray_DIMS(%(ten4)s))[2] < c) ||
                   ( (((PyArray_DIMS(%(ten4)s))[2]-c) %% step_x)!=0))
              {
                  PyErr_Format(PyExc_TypeError,
                               "neib_shape[0]=%%ld, neib_step[0]=%%ld and"
                               " ten4.shape[2]=%%ld not consistent",
                               (long int)c, (long int)step_x,
                               (long int)(PyArray_DIMS(%(ten4)s)[2]));
                  %(fail)s;
              }
              if ( ((PyArray_DIMS(%(ten4)s))[3] < d) ||
                   ( (((PyArray_DIMS(%(ten4)s))[3]-d) %% step_y)!=0))
              {
                  PyErr_Format(PyExc_TypeError,
                               "neib_shape[1]=%%ld, neib_step[1]=%%ld and"
                               " ten4.shape[3]=%%ld not consistent",
                               (long int)d, (long int)step_y,
                               (long int)(PyArray_DIMS(%(ten4)s)[3]));
                  %(fail)s;
              }
              //number of patch in height
              grid_c = 1+(((PyArray_DIMS(%(ten4)s))[2]-c)/step_x);
              //number of patch in width
              grid_d = 1+(((PyArray_DIMS(%(ten4)s))[3]-d)/step_y);
          } else if (%(mode)s == MODE_IGNORE_BORDERS) {
              //number of patch in height
              grid_c = 1+(((PyArray_DIMS(%(ten4)s))[2]-c)/step_x);
              //number of patch in width
              grid_d = 1+(((PyArray_DIMS(%(ten4)s))[3]-d)/step_y);
          } else if (%(mode)s == MODE_HALF) {
              if ( ((PyArray_DIMS(%(ten4)s))[2] < c) ||
                   ( (((PyArray_DIMS(%(ten4)s))[2]-(c%%2)) %% step_x)!=0))
              {
                  PyErr_Format(PyExc_TypeError,
                               "neib_shape[0]=%%ld, neib_step[0]=%%ld and"
                               " ten4.shape[2]=%%ld not consistent",
                               (long int)c, (long int)step_x,
                               (long int)(PyArray_DIMS(%(ten4)s)[2]));
                  %(fail)s;
              }
              if ( ((PyArray_DIMS(%(ten4)s))[3] < d) ||
                   ( (((PyArray_DIMS(%(ten4)s))[3]-(d%%2)) %% step_y)!=0))
              {
                  PyErr_Format(PyExc_TypeError,
                               "neib_shape[1]=%%ld, neib_step[1]=%%ld and"
                               " ten4.shape[3]=%%ld not consistent",
                               (long int)d, (long int)step_y,
                               (long int)(PyArray_DIMS(%(ten4)s)[3]));
                  %(fail)s;
              }
              //number of patch in height
              grid_c = 1+(((PyArray_DIMS(%(ten4)s))[2]-(c%%2))/step_x);
              //number of patch in width
              grid_d = 1+(((PyArray_DIMS(%(ten4)s))[3]-(d%%2))/step_y);
          } else if (%(mode)s == MODE_FULL) {
              if ( ((PyArray_DIMS(%(ten4)s))[2] < c) ||
                   ( (((PyArray_DIMS(%(ten4)s))[2]+c-2) %% step_x)!=0))
              {
                  PyErr_Format(PyExc_TypeError,
                               "neib_shape[0]=%%ld, neib_step[0]=%%ld and"
                               " ten4.shape[2]=%%ld not consistent",
                               (long int)c, (long int)step_x,
                               (long int)(PyArray_DIMS(%(ten4)s)[2]));
                  %(fail)s;
              }
              if ( ((PyArray_DIMS(%(ten4)s))[3] < d) ||
                   ( (((PyArray_DIMS(%(ten4)s))[3]+d-2) %% step_y)!=0))
              {
                  PyErr_Format(PyExc_TypeError,
                               "neib_shape[1]=%%ld, neib_step[1]=%%ld and"
                               " ten4.shape[3]=%%ld not consistent",
                               (long int)d, (long int)step_y,
                               (long int)(PyArray_DIMS(%(ten4)s)[3]));
                  %(fail)s;
              }
              //number of patch in height
              grid_c = 1+(((PyArray_DIMS(%(ten4)s))[2]+c-2)/step_x);
              //number of patch in width
              grid_d = 1+(((PyArray_DIMS(%(ten4)s))[3]+d-2)/step_y);
          } else {
              PyErr_Format(PyExc_TypeError,
                           "Images2Neibs: unknow mode %%d", %(mode)s);
              %(fail)s;
          }
  
          // new dimensions for z
          const npy_intp z_dim1 = c * d;
          const npy_intp z_dim0 =  grid_c
                              * grid_d
                              * (PyArray_DIMS(%(ten4)s))[1]
                              * (PyArray_DIMS(%(ten4)s))[0];
  
          if ((NULL == %(z)s)
              || ((PyArray_DIMS(%(z)s))[0] != z_dim0 )
              || ((PyArray_DIMS(%(z)s))[1] != z_dim1 )
          )
          {
              Py_XDECREF(%(z)s);
              npy_intp dims[2];
              dims[0] = z_dim0;
              dims[1] = z_dim1;
  
              %(z)s = (PyArrayObject*) PyArray_EMPTY(2,
                  dims,
                  PyArray_TYPE((PyArrayObject*) py_%(ten4)s),
                  0);
  
              if (!%(z)s)
              {
                  PyErr_SetString(PyExc_MemoryError, "failed to alloc z output");
                  %(fail)s;
              }
          }
          }
  
          { // NESTED SCOPE
  
          const int nb_batch = (PyArray_DIMS(%(ten4)s))[0];
          const int nb_stack = (PyArray_DIMS(%(ten4)s))[1];
          const int height = (PyArray_DIMS(%(ten4)s))[2];
          const int width = (PyArray_DIMS(%(ten4)s))[3];
  
          // (c,d) = neib_shape
          const npy_intp c = (npy_intp) *(dtype_%(neib_shape)s*) PyArray_GETPTR1(%(neib_shape)s, 0);
          const npy_intp d = (npy_intp) *(dtype_%(neib_shape)s*) PyArray_GETPTR1(%(neib_shape)s, 1);
          // (step_x,step_y) = neib_step
          const npy_intp step_x = (npy_intp) *(dtype_%(neib_step)s*) PyArray_GETPTR1(%(neib_step)s, 0);
          const npy_intp step_y = (npy_intp) *(dtype_%(neib_step)s*) PyArray_GETPTR1(%(neib_step)s, 1);
  
          const int wrap_centered_half_idx_shift_x = c/2;
          const int wrap_centered_half_idx_shift_y = d/2;
          // Oh this is messed up...
          for (int n = 0; n < nb_batch; n++)              // loop over batches
              for (int s = 0; s < nb_stack; s++)          // loop over stacks
                  for (int a = 0; a < grid_c; a++)        // loop over the number of patch in height
                      for (int b = 0; b < grid_d; b++)    // loop over the number of patch in width
                      {
                          int z_row = b + grid_d*(a + grid_c*(s + nb_stack*n));
                          for (int i = 0; i < c; i++)     // loop over c
                          {
                              int ten4_2 = i + a * step_x;
                              if (%(mode)s == MODE_WRAP_CENTERED) {
                                  ten4_2 -= wrap_centered_half_idx_shift_x;
                                  if ( ten4_2 < 0 ) ten4_2 += height;
                                  else if (ten4_2 >= height) ten4_2 -= height;
                              } else if (%(mode)s == MODE_HALF) {
                                  ten4_2 -= wrap_centered_half_idx_shift_x;
                              } else if (%(mode)s == MODE_FULL) {
                                  ten4_2 -= c - 1;
                              }
                              if (ten4_2 < 0 | ten4_2 >= height) {
                                  dtype_%(z)s* curr_z = (dtype_%(z)s*) PyArray_GETPTR2(%(z)s, z_row, d * i);
                                  memset(curr_z, 0, d*sizeof(*curr_z));
                              } else {
                                  for (int j = 0; j < d; j++)  // loop over d
                                  {
                                      int ten4_3 = j + b * step_y;
                                      if (%(mode)s == MODE_WRAP_CENTERED) {
                                          ten4_3 -= wrap_centered_half_idx_shift_y;
                                          if ( ten4_3 < 0 ) ten4_3 += width;
                                          else if (ten4_3 >= width) ten4_3 -= width;
                                      } else if (%(mode)s == MODE_HALF) {
                                          ten4_3 -= wrap_centered_half_idx_shift_y;
                                      } else if (%(mode)s == MODE_FULL) {
                                          ten4_3 -= d - 1;
                                      }
                                      int z_col = j + d * i;
                                      dtype_%(z)s* curr_z = (dtype_%(z)s*) PyArray_GETPTR2(%(z)s, z_row, z_col);
                                      if (ten4_3 < 0 | ten4_3 >= width) {
                                          *curr_z = 0;
                                      } else {
                                          *curr_z = *( (dtype_%(ten4)s*) PyArray_GETPTR4(%(ten4)s, n, s, ten4_2, ten4_3));
                                      }
                                  }
                              }
                          }
                      }
          } // END NESTED SCOPE
          """ % dict(
          ten4=inp[0],
          neib_shape=inp[1],
          neib_step=inp[2],
          z=out[0],
          fail=sub["fail"],
          mode=sub["params"],
      )
  
imports: from __future__ import absolute_import, print_function, division
  import numpy
  import theano
  from theano import Op, Apply
  from theano.gof import EnumList
  import theano.tensor
  from theano.gradient import grad_not_implemented
  from theano.gradient import grad_undefined
label_desc: Use image node_id 10 for calling the Images2Neibs obj's underlying member method code with example usage: obj.c_code(node, name, inp, out, sub) and returns: unknown