code: def gpu_kernels(self, node, name):
      write = write_w(self.output_type.dtype)
      if self.output_type.dtype == "float16":
          otype = "ga_half"
          # limit the values of the state that we use.
          mask = "& 0x7fff"
          offset = "+ 1"
          NORM = "3.0458e-05f"  # numpy.float16(1.0/(2**15+33))
          # this was determined by finding the biggest number such that
          # numpy.float16(number * ((M1 & 0x7fff) + 1)) < 1.0
      elif self.output_type.dtype == "float32":
          otype = "float"
          mask = ""
          offset = ""
          NORM = "4.6566126e-10f"  # numpy.float32(1.0/(2**31+65))
          # this was determined by finding the biggest number such that
          # numpy.float32(number * M1) < 1.0
      elif self.output_type.dtype == "float64":
          otype = "double"
          mask = ""
          offset = ""
          NORM = "4.656612873077392578125e-10"
      else:
          raise ValueError(
              "Unsupported data type for output", self.output_type.dtype
          )
      code = (
          """#include "cluda.h"
  
          KERNEL void mrg_uniform(
                  GLOBAL_MEM %(otype)s *sample_data,
                  ga_size sample_offset,
                  GLOBAL_MEM ga_int *state_data,
                  ga_size state_offset,
                  const ga_uint Nsamples,
                  const ga_uint Nstreams_used)
          {
              sample_data = (GLOBAL_MEM %(otype)s *)(((GLOBAL_MEM char *)sample_data) + sample_offset);
              state_data = (GLOBAL_MEM ga_int *)(((GLOBAL_MEM char *)state_data) + state_offset);
              /*
               * The cluda backend makes sure that ga_int corresponds to
               * a 32 bit signed type on the target device.  It is not a
               * variable width type.
               */
              const ga_int i7 = 7;
              const ga_int i9 = 9;
              const ga_int i15 = 15;
              const ga_int i16 = 16;
              const ga_int i22 = 22;
              const ga_int i24 = 24;
  
              const ga_int M1 = 2147483647;      //2^31 - 1
              const ga_int M2 = 2147462579;      //2^31 - 21069
              const ga_int MASK12 = 511;       //2^9 - 1
              const ga_int MASK13 = 16777215;  //2^24 - 1
              const ga_int MASK2 = 65535;      //2^16 - 1
              const ga_int MULT2 = 21069;
  
              const ga_uint idx = GID_0 * LDIM_0 + LID_0;
              ga_int y1, y2, x11, x12, x13, x21, x22, x23;
  
              if (idx < Nstreams_used)
              {
              x11 = state_data[idx*6+0];
              x12 = state_data[idx*6+1];
              x13 = state_data[idx*6+2];
              x21 = state_data[idx*6+3];
              x22 = state_data[idx*6+4];
              x23 = state_data[idx*6+5];
  
              for (ga_uint i = idx; i < Nsamples; i += Nstreams_used)
              {
                  y1 = ((x12 & MASK12) << i22) + (x12 >> i9) + ((x13 & MASK13) << i7) + (x13 >> i24);
                  y1 -= (y1 < 0 || y1 >= M1) ? M1 : 0;
                  y1 += x13;
                  y1 -= (y1 < 0 || y1 >= M1) ? M1 : 0;
                  x13 = x12;
                  x12 = x11;
                  x11 = y1;
  
                  y1 = ((x21 & MASK2) << i15) + (MULT2 * (x21 >> i16));
                  y1 -= (y1 < 0 || y1 >= M2) ? M2 : 0;
                  y2 = ((x23 & MASK2) << i15) + (MULT2 * (x23 >> i16));
                  y2 -= (y2 < 0 || y2 >= M2) ? M2 : 0;
                  y2 += x23;
                  y2 -= (y2 < 0 || y2 >= M2) ? M2 : 0;
                  y2 += y1;
                  y2 -= (y2 < 0 || y2 >= M2) ? M2 : 0;
  
                  x23 = x22;
                  x22 = x21;
                  x21 = y2;
  
                  if (x11 <= x21) {
                      sample_data[i] = %(write)s((((x11 - x21 + M1) %(mask)s) %(offset)s) * %(NORM)s);
                  }
                  else
                  {
                      sample_data[i] = %(write)s((((x11 - x21) %(mask)s) %(offset)s) * %(NORM)s);
                  }
              }
  
              state_data[idx*6+0]= x11;
              state_data[idx*6+1]= x12;
              state_data[idx*6+2]= x13;
              state_data[idx*6+3]= x21;
              state_data[idx*6+4]= x22;
              state_data[idx*6+5]= x23;
              }
          }
  
          """
          % locals()
      )
  
      # we shouldn't get to this line if it's about to fail
      from pygpu import gpuarray
  
      return [
          Kernel(
              code=code,
              name="mrg_uniform",
              params=[
                  gpuarray.GpuArray,
                  gpuarray.SIZE,
                  gpuarray.GpuArray,
                  gpuarray.SIZE,
                  "uint32",
                  "uint32",
              ],
              flags=Kernel.get_flags(self.output_type.dtype, "int32"),
          )
      ]
  
imports: from __future__ import absolute_import, print_function, division
  from theano import Apply, tensor
  from theano.gof import local_optimizer
  from theano.sandbox.rng_mrg import mrg_uniform_base, mrg_uniform
  from theano.tensor import as_tensor_variable, get_vector_length
  from theano.scalar import int32
  from .basic_ops import GpuKernelBase, Kernel, infer_context_name, GpuFromHost, host_from_gpu, as_gpuarray_variable
  from .type import GpuArrayType, gpu_context_type
  from .fp16_help import write_w
  from .opt import register_opt, register_opt2
label_desc: Use image node_id 5 for calling the GPUA_mrg_uniform obj's underlying member method code with example usage: obj.gpu_kernels(node, name) and returns: list