#NEWLINE# def c_code( self , node , name , inp , out , sub ) : #NEWLINE# #INDENT# ( dnll , sm , y_idx ) = inp #NEWLINE# ( dx , ) = out #NEWLINE# y_idx_type = node . inputs [ 2 ] . type . dtype_specs ( ) [ 1 ] #NEWLINE# return ( '\n        if ((PyArray_TYPE(%(dnll)s) != NPY_DOUBLE) &&\n            (PyArray_TYPE(%(dnll)s) != NPY_FLOAT))\n        {\n            PyErr_SetString(PyExc_TypeError,\n                 "dnll type should be float32 or float64");\n            %(fail)s;\n        }\n        if ((PyArray_TYPE(%(sm)s) != NPY_DOUBLE) &&\n            (PyArray_TYPE(%(sm)s) != NPY_FLOAT))\n        {\n            PyErr_SetString(PyExc_TypeError,\n                 "sm type should be float32 or float64");\n            %(fail)s;\n        }\n\n        // new scope because of variable declaration\n        // TODO: proper indentation, but the diff will get messy\n        {\n        // Get `dnll.shape[0]` or set it to zero if `dnll` is a scalar.\n        const npy_intp %(dnll)s_dims0 = (PyArray_NDIM(%(dnll)s) > 0 ?\n                                         PyArray_DIMS(%(dnll)s)[0] :\n                                         (npy_intp) 0);\n\n        // Get `dnll.strides[0]` and set it to zero if `dnll` is a scalar\n        // or a vector with just one element.\n        const npy_intp %(dnll)s_strides0 = (%(dnll)s_dims0 > 1 ?\n                                            PyArray_STRIDES(%(dnll)s)[0] :\n                                            (npy_intp) 0);\n\n        if ((PyArray_NDIM(%(dnll)s) > 1)\n            || (PyArray_NDIM(%(sm)s) != 2)\n            || (PyArray_NDIM(%(y_idx)s) != 1))\n        {\n            PyErr_SetString(PyExc_ValueError, "rank error");\n            %(fail)s;\n        }\n        if (%(dnll)s_dims0 != PyArray_DIMS(%(sm)s)[0] && %(dnll)s_dims0 > 1)\n        {\n            PyErr_Format(PyExc_ValueError,\n                         "dnll.shape[0] (%%ld) != sm.shape[0] (%%ld)",\n                         (long int)%(dnll)s_dims0,\n                         (long int)PyArray_DIMS(%(sm)s)[0]);\n            %(fail)s;\n        }\n        if (%(dnll)s_dims0 != PyArray_DIMS(%(y_idx)s)[0] && %(dnll)s_dims0 > 1)\n        {\n            PyErr_Format(PyExc_ValueError,\n                         "dnll.shape[0] (%%ld) != y_idx.shape[0] (%%ld)",\n                         (long int)%(dnll)s_dims0,\n                         (long int)PyArray_DIMS(%(y_idx)s)[0]);\n            %(fail)s;\n        }\n        if (PyArray_DIMS(%(sm)s)[0] !=\n            PyArray_DIMS(%(y_idx)s)[0])\n        {\n            PyErr_SetString(PyExc_ValueError,\n                            "sm.shape[0] != y_idx.shape[0]");\n            %(fail)s;\n        }\n        if ((NULL == %(dx)s)\n            || (PyArray_DIMS(%(dx)s)[0] != PyArray_DIMS(%(sm)s)[0])\n            || (PyArray_DIMS(%(dx)s)[1] != PyArray_DIMS(%(sm)s)[1]))\n        {\n            if (NULL != %(dx)s) Py_XDECREF(%(dx)s);\n            %(dx)s = (PyArrayObject*) PyArray_SimpleNew(2,\n                                                        PyArray_DIMS(%(sm)s),\n                                                        PyArray_TYPE(%(sm)s));\n            if(!%(dx)s) {\n                PyErr_SetString(PyExc_MemoryError,\n                     "failed to alloc dx output");\n                %(fail)s\n            }\n        }\n\n        for (size_t i = 0; i < PyArray_DIMS(%(dx)s)[0]; ++i)\n        {\n            const dtype_%(dnll)s dnll_i = ((dtype_%(dnll)s*)(PyArray_BYTES(%(dnll)s) + %(dnll)s_strides0 * i))[0];\n\n            const %(y_idx_type) s y_i = ((%(y_idx_type)s*)(PyArray_BYTES(%(y_idx)s) + PyArray_STRIDES(%(y_idx)s)[0] * i))[0];\n\n            const dtype_%(sm)s* __restrict__ sm_i = (dtype_%(sm)s*)(PyArray_BYTES(%(sm)s) + PyArray_STRIDES(%(sm)s)[0] * i);\n            npy_intp Ssm = PyArray_STRIDES(%(sm)s)[1]/sizeof(dtype_%(sm)s);\n\n            dtype_%(dx) s* __restrict__ dx_i = (dtype_%(dx)s*)(PyArray_BYTES(%(dx)s) + PyArray_STRIDES(%(dx)s)[0] * i);\n            npy_intp Sdx = PyArray_STRIDES(%(dx)s)[1]/sizeof(dtype_%(dx)s);\n\n            for (size_t j = 0; j < PyArray_DIMS(%(dx)s)[1]; ++j)\n            {\n                dx_i[j * Sdx] = dnll_i * sm_i[j * Ssm];\n            }\n            if (y_i >= PyArray_DIMS(%(dx)s)[1] || (y_i < 0))\n            {\n                PyErr_SetString(PyExc_ValueError, "y_i >= dx dimensions[1] or y_i < 0.");\n                %(fail)s;\n            }\n            dx_i[y_i * Sdx] -= dnll_i;\n        }\n        }\n        ' % dict ( locals ( ) , ** sub ) )