code: def c_code(self, node, name, inp, outputs, sub):
      pvals, unis = inp
      (out,) = outputs
      fail = sub["fail"]
      ctx = sub["params"]
      kname = self.gpu_kernels(node, name)[0].objvar
      out_typecode = pygpu.gpuarray.dtype_to_typecode(
          node.outputs[0].dtype
      )
      pvals_typecode = pygpu.gpuarray.dtype_to_typecode(
          node.inputs[0].dtype
      )
      unis_typecode = pygpu.gpuarray.dtype_to_typecode(
          node.inputs[1].dtype
      )
      s = (
          """
          PyGpuArrayObject * pvals = %(pvals)s;
          PyGpuArrayObject * unis = %(unis)s;
          PyGpuArrayObject * out = %(out)s;
  
      size_t dims[2];
      if (PyGpuArray_NDIM(pvals) != 2)
      {
          PyErr_Format(PyExc_TypeError, "pvals wrong rank");
          %(fail)s
      }
      if (PyGpuArray_NDIM(unis) != 1)
      {
          PyErr_Format(PyExc_TypeError, "unis wrong rank");
          %(fail)s
      }
      if (PyGpuArray_DIMS(unis)[0] != PyGpuArray_DIMS(pvals)[0])
      {
          PyErr_Format(PyExc_ValueError, "unis.shape[0] != pvals.shape[0]");
          %(fail)s
      }
  
      dims[0] = PyGpuArray_DIMS(pvals)[1];
      dims[1] = PyGpuArray_DIMS(pvals)[0];
      if (theano_prep_output(&out, 2, dims, %(out_typecode)s,
                             GA_C_ORDER, %(ctx)s) != 0){
        %(fail)s
      }
      %(out)s = out;
      GpuArray_memset(&(out->ga), 0);
      { // NESTED SCOPE
          int nb_multi = PyGpuArray_DIMS(pvals)[0];
          int nb_outcomes = PyGpuArray_DIMS(pvals)[1];
          //TODO : change this for a beautiful constant
          int max_nb_blocks = 2<<15 - 1;
          size_t nb_blocks = max_nb_blocks + 1;
          size_t nb_threads=16; // so it really starts at 32, because of the *2
          do
          {
              nb_threads*=2;
              if (nb_multi %% nb_threads == 0)
                  nb_blocks = nb_multi/nb_threads;
              else
                  nb_blocks = (int)((float)nb_multi/(float)nb_threads + 1.);
          } while (nb_blocks > max_nb_blocks);
  
          //printf("\\nN=%%i b=%%i t=%%i t*b=%%i",
          //         nb_multi, nb_blocks, nb_threads, nb_blocks*nb_threads);
  
          // TODO : next line is a bit hardcoded...
          if (nb_threads > 512)
          {
              PyErr_Format(
                  PyExc_ValueError,
                  "Multinomial is not implemented for so many rows in the matrix (%%i)",
                  nb_multi);
              %(fail)s
          }
  
          assert(nb_blocks*nb_threads >= nb_multi);
  
          int err = k_multi_warp_multinomial_call(
            1, &nb_blocks, &nb_threads, 0,
            PyGpuArray_DIMS(out)[1], PyGpuArray_DIMS(out)[0], pvals->ga.data, pvals->ga.offset,
            PyGpuArray_STRIDES(pvals)[0]/gpuarray_get_elsize(%(pvals_typecode)s),
            PyGpuArray_STRIDES(pvals)[1]/gpuarray_get_elsize(%(pvals_typecode)s),
            unis->ga.data, unis->ga.offset,
            PyGpuArray_STRIDES(unis)[0]/gpuarray_get_elsize(%(unis_typecode)s), out->ga.data,
            out->ga.offset, PyGpuArray_STRIDES(out)[0]/gpuarray_get_elsize(%(out_typecode)s),
            PyGpuArray_STRIDES(out)[1]/gpuarray_get_elsize(%(out_typecode)s));
  
          if (err != GA_NO_ERROR) {
             PyErr_Format(
                  PyExc_RuntimeError,
                  "gpuarray error: %%s: %%s.\\n",
                  "k_multi_warp_%(name)s",
                  GpuKernel_error(&%(kname)s, err));
              %(fail)s;
          }
  
      } // END NESTED SCOPE
          """
          % locals()
      )
  
      return s
  
imports: from __future__ import absolute_import, print_function, division
  import warnings
  import theano
  import theano.sandbox.multinomial
  from theano import Apply
  from theano.gof import Op
  from theano.tensor import NotScalarConstantError, get_scalar_constant_value
  from .basic_ops import as_gpuarray_variable, infer_context_name, GpuKernelBase, Kernel, gpuarray_helper_inc_dir
  from .opt import register_opt, op_lifter, register_opt2
  from .type import GpuArrayType
  from .elemwise import GpuDimShuffle
  from theano.scalar import as_scalar
  from .fp16_help import write_w, load_w, work_dtype
label_desc: Use image node_id 7 for calling the GPUAMultinomialFromUniform obj's underlying member method code with example usage: obj.c_code(node, name, inp, outputs, sub) and returns: s