class_docstr: Generates and executes code to produce a large number of variable-size
  lists, simply.
  
  .. note:: This functionality is provided as a preview. Its interface
      is subject to change until this notice is removed.
  
  .. versionadded:: 2013.1
  
  Here's a usage example::
  
      from pyopencl.algorithm import ListOfListsBuilder
      builder = ListOfListsBuilder(context, [("mylist", np.int32)], """
              void generate(LIST_ARG_DECL USER_ARG_DECL index_type i)
              {
                  int count = i % 4;
                  for (int j = 0; j < count; ++j)
                  {
                      APPEND_mylist(count);
                  }
              }
              """, arg_decls=[])
  
      result, event = builder(queue, 2000)
  
      inf = result["mylist"]
      assert inf.count == 3000
      assert (inf.list.get()[-6:] == [1, 2, 2, 3, 3, 3]).all()
  
  The function ``generate`` above is called once for each "input object".
  Each input object can then generate zero or more list entries.
  The number of these input objects is given to :meth:`__call__` as *n_objects*.
  List entries are generated by calls to ``APPEND_<list name>(value)``.
  Multiple lists may be generated at once.
  
  .. automethod:: __init__
  .. automethod:: __call__
docstr: :arg context: A :class:`pyopencl.Context`.
  :arg list_names_and_dtypes: a list of ``(name, dtype)`` tuples
      indicating the lists to be built.
  :arg generate_template: a snippet of C as described below
  :arg arg_decls: A string of comma-separated C argument declarations.
  :arg count_sharing: A mapping consisting of ``(child, mother)``
      indicating that ``mother`` and ``child`` will always have the
      same number of indices, and the ``APPEND`` to ``mother``
      will always happen *before* the ``APPEND`` to the child.
  :arg name_prefix: the name prefix to use for the compiled kernels
  :arg options: OpenCL compilation options for kernels using
      *generate_template*.
  :arg complex_kernel: If *True*, prevents vectorization on CPUs.
  :arg eliminate_empty_output_lists: A Python list of list names
      for which the empty output lists are eliminated.
  
  *generate_template* may use the following C macros/identifiers:
  
  * ``index_type``: expands to C identifier for the index type used
    for the calculation
  * ``USER_ARG_DECL``: expands to the C declarator for ``arg_decls``
  * ``USER_ARGS``: a list of C argument values corresponding to
    ``user_arg_decl``
  * ``LIST_ARG_DECL``: expands to a C argument list representing the
    data for the output lists. These are escaped prefixed with
    ``"plg_"`` so as to not interfere with user-provided names.
  * ``LIST_ARGS``: a list of C argument values corresponding to
    ``LIST_ARG_DECL``
  * ``APPEND_name(entry)``: inserts ``entry`` into the list ``name``.
    *entry* must be a valid C expression of the correct type.
  
  All argument-list related macros have a trailing comma included
  if they are non-empty.
  
  *generate_template* must supply a function:
  
  .. code-block:: c
  
      void generate(USER_ARG_DECL LIST_ARG_DECL index_type i)
      {
          APPEND_mylist(5);
      }
  
  Internally, the ``kernel_template`` is expanded (at least) twice. Once,
  for a 'counting' stage where the size of all the lists is determined,
  and a second time, for a 'generation' stage where the lists are
  actually filled. A ``generate`` function that has side effects beyond
  calling ``append`` is therefore ill-formed.
  
  .. versionchanged:: 2018.1
  
      Change *eliminate_empty_output_lists* argument type from ``bool`` to
      ``list``.
code: def __init__(
      self,
      context,
      list_names_and_dtypes,
      generate_template,
      arg_decls,
      count_sharing=None,
      devices=None,
      name_prefix="plb_build_list",
      options=None,
      preamble="",
      debug=False,
      complex_kernel=False,
      eliminate_empty_output_lists=False,
  ):
      """
      :arg context: A :class:`pyopencl.Context`.
      :arg list_names_and_dtypes: a list of ``(name, dtype)`` tuples
          indicating the lists to be built.
      :arg generate_template: a snippet of C as described below
      :arg arg_decls: A string of comma-separated C argument declarations.
      :arg count_sharing: A mapping consisting of ``(child, mother)``
          indicating that ``mother`` and ``child`` will always have the
          same number of indices, and the ``APPEND`` to ``mother``
          will always happen *before* the ``APPEND`` to the child.
      :arg name_prefix: the name prefix to use for the compiled kernels
      :arg options: OpenCL compilation options for kernels using
          *generate_template*.
      :arg complex_kernel: If *True*, prevents vectorization on CPUs.
      :arg eliminate_empty_output_lists: A Python list of list names
          for which the empty output lists are eliminated.
  
      *generate_template* may use the following C macros/identifiers:
  
      * ``index_type``: expands to C identifier for the index type used
        for the calculation
      * ``USER_ARG_DECL``: expands to the C declarator for ``arg_decls``
      * ``USER_ARGS``: a list of C argument values corresponding to
        ``user_arg_decl``
      * ``LIST_ARG_DECL``: expands to a C argument list representing the
        data for the output lists. These are escaped prefixed with
        ``"plg_"`` so as to not interfere with user-provided names.
      * ``LIST_ARGS``: a list of C argument values corresponding to
        ``LIST_ARG_DECL``
      * ``APPEND_name(entry)``: inserts ``entry`` into the list ``name``.
        *entry* must be a valid C expression of the correct type.
  
      All argument-list related macros have a trailing comma included
      if they are non-empty.
  
      *generate_template* must supply a function:
  
      .. code-block:: c
  
          void generate(USER_ARG_DECL LIST_ARG_DECL index_type i)
          {
              APPEND_mylist(5);
          }
  
      Internally, the ``kernel_template`` is expanded (at least) twice. Once,
      for a 'counting' stage where the size of all the lists is determined,
      and a second time, for a 'generation' stage where the lists are
      actually filled. A ``generate`` function that has side effects beyond
      calling ``append`` is therefore ill-formed.
  
      .. versionchanged:: 2018.1
  
          Change *eliminate_empty_output_lists* argument type from ``bool`` to
          ``list``.
      """
      if devices is None:
          devices = context.devices
  
      if count_sharing is None:
          count_sharing = {}
  
      self.context = context
      self.devices = devices
  
      self.list_names_and_dtypes = list_names_and_dtypes
      self.generate_template = generate_template
  
      from pyopencl.tools import parse_arg_list
  
      self.arg_decls = parse_arg_list(arg_decls)
  
      # To match with the signature of the user-supplied generate(), arguments
      # can't appear to have offsets.
      arg_decls_no_offset = []
      from pyopencl.tools import VectorArg
  
      for arg in self.arg_decls:
          if isinstance(arg, VectorArg) and arg.with_offset:
              arg = VectorArg(arg.dtype, arg.name)
          arg_decls_no_offset.append(arg)
      self.arg_decls_no_offset = arg_decls_no_offset
  
      self.count_sharing = count_sharing
  
      self.name_prefix = name_prefix
      self.preamble = preamble
      self.options = options
  
      self.debug = debug
  
      self.complex_kernel = complex_kernel
  
      if eliminate_empty_output_lists is True:
          eliminate_empty_output_lists = [
              name for name, _ in self.list_names_and_dtypes
          ]
  
      if eliminate_empty_output_lists is False:
          eliminate_empty_output_lists = []
  
      self.eliminate_empty_output_lists = eliminate_empty_output_lists
      for list_name in self.eliminate_empty_output_lists:
          if not any(
              list_name == name
              for name, _ in self.list_names_and_dtypes
          ):
              raise ValueError(
                  "invalid list name '%s' in eliminate_empty_output_lists"
                  % list_name
              )
  
imports: from dataclasses import dataclass
  from typing import Optional
  import numpy
  import pyopencl
  import pyopencl.array
  from pyopencl.elementwise import ElementwiseKernel
  from pyopencl.scan import ScanTemplate, GenericScanKernel
  from pyopencl.tools import dtype_to_ctype, get_arg_offset_adjuster_code
  from pytools import memoize, memoize_method
  from mako.template import Template
label_desc: Use image node_id 1 to create a new ListOfListsBuilder object  with example: obj = ListOfListsBuilder(context, list_names_and_dtypes, generate_template, arg_decls, count_sharing, devices, name_prefix, options, preamble, debug, complex_kernel, eliminate_empty_output_lists)