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: :arg arguments: A string of comma-separated C argument declarations.
      If *arguments* is specified, then *input_expr* must also be
      specified. All types used here must be known to PyOpenCL.
      (see :func:`pyopencl.tools.get_or_register_dtype`).
  :arg key_expr: An integer-valued C expression returning the
      key based on which the sort is performed. The array index
      for which the key is to be computed is available as ``i``.
      The expression may refer to any of the *arguments*.
  :arg sort_arg_names: A list of argument names whose corresponding
      array arguments will be sorted according to *key_expr*.
code: def __init__(
      self,
      context,
      arguments,
      key_expr,
      sort_arg_names,
      bits_at_a_time=2,
      index_dtype=np.int32,
      key_dtype=np.uint32,
      scan_kernel=GenericScanKernel,
      options=None,
  ):
      """
      :arg arguments: A string of comma-separated C argument declarations.
          If *arguments* is specified, then *input_expr* must also be
          specified. All types used here must be known to PyOpenCL.
          (see :func:`pyopencl.tools.get_or_register_dtype`).
      :arg key_expr: An integer-valued C expression returning the
          key based on which the sort is performed. The array index
          for which the key is to be computed is available as ``i``.
          The expression may refer to any of the *arguments*.
      :arg sort_arg_names: A list of argument names whose corresponding
          array arguments will be sorted according to *key_expr*.
      """
  
      # {{{ arg processing
  
      from pyopencl.tools import parse_arg_list
  
      self.arguments = parse_arg_list(arguments)
      del arguments
  
      self.sort_arg_names = sort_arg_names
      self.bits = int(bits_at_a_time)
      self.index_dtype = np.dtype(index_dtype)
      self.key_dtype = np.dtype(key_dtype)
  
      self.options = options
  
      # }}}
  
      # {{{ kernel creation
  
      scan_ctype, scan_dtype, scan_t_cdecl = _make_sort_scan_type(
          context.devices[0], self.bits, self.index_dtype
      )
  
      from pyopencl.tools import VectorArg, ScalarArg
  
      scan_arguments = (
          list(self.arguments)
          + [
              VectorArg(arg.dtype, "sorted_" + arg.name)
              for arg in self.arguments
              if arg.name in sort_arg_names
          ]
          + [ScalarArg(np.int32, "base_bit")]
      )
  
      def get_count_branch(known_bits):
          if len(known_bits) == self.bits:
              return "s.c%s" % known_bits
  
          boundary_mnr = (
              known_bits + "1" + (self.bits - len(known_bits) - 1) * "0"
          )
  
          return "((mnr < {}) ? {} : {})".format(
              int(boundary_mnr, 2),
              get_count_branch(known_bits + "0"),
              get_count_branch(known_bits + "1"),
          )
  
      codegen_args = {
          "bits": self.bits,
          "key_ctype": dtype_to_ctype(self.key_dtype),
          "key_expr": key_expr,
          "index_ctype": dtype_to_ctype(self.index_dtype),
          "index_type_max": np.iinfo(self.index_dtype).max,
          "padded_bin": _padded_bin,
          "scan_ctype": scan_ctype,
          "sort_arg_names": sort_arg_names,
          "get_count_branch": get_count_branch,
      }
  
      preamble = scan_t_cdecl + RADIX_SORT_PREAMBLE_TPL.render(
          **codegen_args
      )
      scan_preamble = preamble + RADIX_SORT_SCAN_PREAMBLE_TPL.render(
          **codegen_args
      )
  
      self.scan_kernel = scan_kernel(
          context,
          scan_dtype,
          arguments=scan_arguments,
          input_expr="scan_t_from_value(%s, base_bit, i)" % key_expr,
          scan_expr="scan_t_add(a, b, across_seg_boundary)",
          neutral="scan_t_neutral()",
          output_statement=RADIX_SORT_OUTPUT_STMT_TPL.render(
              **codegen_args
          ),
          preamble=scan_preamble,
          options=self.options,
      )
  
      for i, arg in enumerate(self.arguments):
          if isinstance(arg, VectorArg):
              self.first_array_arg_idx = i
  
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 RadixSort object  with example: obj = RadixSort(context, arguments, key_expr, sort_arg_names, bits_at_a_time, index_dtype, key_dtype, scan_kernel, options)