def c_code(self, node, name, inputs, outputs, sub):
        p, h, gp, gh, gp_iszero, gh_iszero = inputs
        targets_z, targets_t, = outputs
        fail = sub['fail']

        # The amount of braces that must be closed at the end
        num_braces = 0

        if self.copy_non_contiguous:
            raise UnimplementedError()
        else:
            basic_setup = "#define PROBMAXPOOLGRAD_COPY_NON_CONTIGUOUS 0\n"

        # Convert images in nv_images, an NVMatrix, for compatibility
        # with the cuda-convnet functions
        setup_nv_h = self._argument_contiguity_check("h") + """
        if (%(h)s->nd != 4)
        {
            PyErr_Format(PyExc_ValueError,
                "h must have nd=4, got nd=%%i", %(h)s->nd);
            %(fail)s;
        }

        { //setup_nv_images brace 1

        const int * images_dims = CudaNdarray_HOST_DIMS(%(h)s);
        const int img_channels = images_dims[0];
        const int imgSizeY = images_dims[1];
        const int imgSizeX = images_dims[2];
        const int batch_size = images_dims[3];

        if(imgSizeY != imgSizeX){
            PyErr_Format(PyExc_ValueError,
                "images must be square(dims[1] == dims[2]). Shape (%%i,%%i,%%i,%%i)",
                img_channels, imgSizeY, imgSizeX, batch_size);
            %(fail)s;
        }
        if(%(ds)s > imgSizeY){
            PyErr_Format(PyExc_ValueError,
                "ds(%%d) must be <= imgSizeX(%%d) and imgSizeY(%%d).",
                %(ds)s, imgSizeX, imgSizeY);
            %(fail)s;
        }
        if (CudaNdarray_HOST_DIMS(%(h)s)[0] %% 16 != 0)
        {
            PyErr_Format(PyExc_ValueError,
                "h must have a number of channels that is a multiple of 16. Got %%d",
                CudaNdarray_HOST_DIMS(%(gh)s)[0]);
            %(fail)s;
        }


        NVMatrix nv_h(%(h)s, img_channels * imgSizeY * imgSizeX,
                          batch_size, "ProbMaxPool:nv_h");

        """
        num_braces += 1


        setup_nv_p = self._argument_contiguity_check("p") + """
        if (%(p)s->nd != 4)
        {
            PyErr_Format(PyExc_ValueError,
                "P must have nd=4, got nd=%%i", %(p)s->nd);
            %(fail)s;
        }

        { //setup_nv_images brace 1

        int _outputsX = ((int)(ceil((imgSizeY - %(start)s - %(ds)s) / ((float)%(stride)s)))) + 1;


        NVMatrix nv_p(%(p)s, img_channels * _outputsX * _outputsX, batch_size,
        "ProbMaxPool:nv_p");
        """
        num_braces += 1

        # Convert gh in nv_gh
        setup_nv_gh = self._argument_contiguity_check("gh") + """
        if (%(gh)s->nd != 4)
        {
            PyErr_Format(PyExc_ValueError,
                "gh must have nd=4, got nd=%%i", %(gh)s->nd);
            %(fail)s;
        }
        if (CudaNdarray_HOST_DIMS(%(gh)s)[0] %% 16 != 0)
        {
            PyErr_Format(PyExc_ValueError,
                "gh must have a number of channels that is a multiple of 16. Got %%d",
                CudaNdarray_HOST_DIMS(%(gh)s)[0]);
            %(fail)s;
        }

        { //setup_nv_gh brace 1

        const int * gh_dims = CudaNdarray_HOST_DIMS(%(gh)s);
        const int gh_channels = gh_dims[0];
        const int ghSizeY = gh_dims[1];
        const int ghSizeX = gh_dims[2];

        NVMatrix nv_gh(%(gh)s, gh_channels * ghSizeY * ghSizeX,
                       batch_size, "ProbMaxPool:nv_gh");
        """
        num_braces += 1

        setup_nv_gp = self._argument_contiguity_check("gp") + """
        if (%(gp)s->nd != 4)
        {
            PyErr_Format(PyExc_ValueError,
                "gp must have nd=4, got nd=%%i", %(gp)s->nd);
            %(fail)s;
        }

        { //setup_nv_images brace 1

        int _outputsX = ((int)(ceil((imgSizeY - %(start)s - %(ds)s) / ((float)%(stride)s)))) + 1;


        NVMatrix nv_gp(%(gp)s, img_channels * _outputsX * _outputsX, batch_size,
        "ProbMaxPool:nv_gp");
        """
        num_braces += 1


        setup_nv_targets_z = """
        int target_z_dims [] = {
            img_channels,
            imgSizeX,
            imgSizeY,
            batch_size };

        if (CudaNdarray_prep_output(& %(targets_z)s, 4, target_z_dims))
        {
            %(fail)s;
        }

        { // setup_nv_target brace # 1

        NVMatrix nv_targets_z(%(targets_z)s,
                            target_z_dims[0] * target_z_dims[1] * target_z_dims[2],
                            target_z_dims[3], "ProbMaxPool:nv_targets_z");

        """

        num_braces += 1


        setup_nv_targets_t = """
        int target_t_dims [] = {
            img_channels,
            _outputsX,
            _outputsX,
            batch_size };

        if (CudaNdarray_prep_output(& %(targets_t)s, 4, target_t_dims))
        {
            %(fail)s;
        }

        { // setup_nv_target brace # 1

        NVMatrix nv_targets_t(%(targets_t)s, target_t_dims[0] * target_t_dims[1] * target_t_dims[2],
                            target_t_dims[3], "ProbMaxPool:nv_targets_t");


        float * gp_iszero = CudaNdarray_DEV_DATA(%(gp_iszero)s);
        float * gh_iszero = CudaNdarray_DEV_DATA(%(gh_iszero)s);
        """
        num_braces += 1


        undo_pool = """
        localProbMaxUndo(nv_h, nv_p, nv_gh, nv_gp, nv_targets_z, nv_targets_t,
                         %(ds)s, %(start)s, %(stride)s, _outputsX, imgSizeX, gp_iszero, gh_iszero);
        """

        braces = '}' * num_braces

        rval = (basic_setup +
                setup_nv_h +
                setup_nv_p +
                setup_nv_gh +
                setup_nv_gp +
                setup_nv_targets_z +
                setup_nv_targets_t +
                undo_pool +
                braces)
        start = self.start
        stride = self.stride
        ds = self.ds
        rval = rval % locals()

        return rval

    # Make sure the cuda_convnet library is compiled and up-to-date
.. todo::
dataset/ETHPy150Open lisa-lab/pylearn2/pylearn2/sandbox/cuda_convnet/probabilistic_max_pooling.py/ProbMaxPoolGrad.c_code