class_docstr: Provides a general `radix sort <https://en.wikipedia.org/wiki/Radix_sort>`__
  on the compute device.
  
  .. seealso:: :class:`pyopencl.bitonic_sort.BitonicSort`
  
  .. versionadded:: 2013.1
docstr: Run the radix sort. In addition to *args* which must match the
  *arguments* specification on the constructor, the following
  keyword arguments are supported:
  
  :arg key_bits: specify how many bits (starting from least-significant)
      there are in the key.
  :arg allocator: See the *allocator* argument of :func:`pyopencl.array.empty`.
  :arg queue: A :class:`pyopencl.CommandQueue`, defaulting to the
      one from the first argument array.
  :arg wait_for: |explain-waitfor|
  :returns: A tuple ``(sorted, event)``. *sorted* consists of sorted
      copies of the arrays named in *sorted_args*, in the order of that
      list. *event* is a :class:`pyopencl.Event` for dependency management.
code: def __call__(self, *args, **kwargs):
      """Run the radix sort. In addition to *args* which must match the
      *arguments* specification on the constructor, the following
      keyword arguments are supported:
  
      :arg key_bits: specify how many bits (starting from least-significant)
          there are in the key.
      :arg allocator: See the *allocator* argument of :func:`pyopencl.array.empty`.
      :arg queue: A :class:`pyopencl.CommandQueue`, defaulting to the
          one from the first argument array.
      :arg wait_for: |explain-waitfor|
      :returns: A tuple ``(sorted, event)``. *sorted* consists of sorted
          copies of the arrays named in *sorted_args*, in the order of that
          list. *event* is a :class:`pyopencl.Event` for dependency management.
      """
  
      wait_for = kwargs.pop("wait_for", None)
  
      # {{{ run control
  
      key_bits = kwargs.pop("key_bits", None)
      if key_bits is None:
          key_bits = int(np.iinfo(self.key_dtype).bits)
  
      n = len(args[self.first_array_arg_idx])
  
      allocator = kwargs.pop("allocator", None)
      if allocator is None:
          allocator = args[self.first_array_arg_idx].allocator
  
      queue = kwargs.pop("queue", None)
      if queue is None:
          queue = args[self.first_array_arg_idx].queue
  
      args = list(args)
  
      base_bit = 0
      while base_bit < key_bits:
          sorted_args = [
              cl.array.empty(
                  queue, n, arg_descr.dtype, allocator=allocator
              )
              for arg_descr in self.arguments
              if arg_descr.name in self.sort_arg_names
          ]
  
          scan_args = args + sorted_args + [base_bit]
  
          last_evt = self.scan_kernel(
              *scan_args, queue=queue, wait_for=wait_for
          )
          wait_for = [last_evt]
  
          # substitute sorted
          for i, arg_descr in enumerate(self.arguments):
              if arg_descr.name in self.sort_arg_names:
                  args[i] = sorted_args[
                      self.sort_arg_names.index(arg_descr.name)
                  ]
  
          base_bit += self.bits
  
      return [
          arg_val
          for arg_descr, arg_val in zip(self.arguments, args)
          if arg_descr.name in self.sort_arg_names
      ], last_evt
  
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 2 for calling the RadixSort obj's underlying member method code with example usage: obj.__call__() and returns: unknown,  last_evt