class_docstr: Creates a Generalized Universal Function by wrapping a user
  provided function with the signature.
  
  ``signature`` determines if the function consumes or produces core
  dimensions. The remaining dimensions in given input arrays (``*args``)
  are considered loop dimensions and are required to broadcast
  naturally against each other.
  
  Args:
      func (callable):
          Function to call like ``func(*args, **kwargs)`` on input arrays
          (``*args``) that returns an array or tuple of arrays. If
          multiple arguments with non-matching dimensions are supplied,
          this function is expected to vectorize (broadcast) over axes of
          positional arguments in the style of NumPy universal functions.
      signature (string):
          Specifies what core dimensions are consumed and produced by
          ``func``.  According to the specification of numpy.gufunc
          signature.
      supports_batched (bool, optional):
          If the wrapped function supports to pass the complete input
          array with the loop and the core dimensions.
          Defaults to `False`. Dimensions will be iterated in the
          `GUFunc` processing code.
      supports_out (bool, optional):
          If the wrapped function supports out as one of its kwargs.
          Defaults to `False`.
      signatures (list of tuple of str):
          Contains strings in the form of 'ii->i' with i being the char of a
          dtype. Each element of the list is a tuple with the string
          and a alternative function to `func` to be executed when the inputs
          of the function can be casted as described by this function.
      name (str, optional):
          Name for the GUFunc object. If not specified, ``func``'s name
          is used.
      doc (str, optional):
          Docstring for the GUFunc object. If not specified, ``func.__doc__``
          is used.
code: def __init__(self, func, signature, **kwargs):
      # We would like to create gufuncs from cupy regular ufuncs
      # so we can avoid most of the __call__ stuff
      self._func = func
      self._signature = signature
      self.__name__ = kwargs.pop("name", func.__name__)
      self.__doc__ = kwargs.pop("doc", func.__doc__)
  
      # The following are attributes to avoid applying certain steps
      # when wrapping cupy functions that do some of the gufunc
      # stuff internally due to CUDA libraries requirements
      self._supports_batched = kwargs.pop("supports_batched", False)
      self._supports_out = kwargs.pop("supports_out", False)
      signatures = kwargs.pop("signatures", [])
  
      if kwargs:
          raise TypeError(
              "got unexpected keyword arguments: "
              + ", ".join([repr(k) for k in kwargs])
          )
  
      # Preprocess the signature here
      input_coredimss, output_coredimss = _parse_gufunc_signature(
          self._signature
      )
      self._input_coredimss = input_coredimss
      self._output_coredimss = output_coredimss
      # This is pre-calculated to later check the minimum number of
      # dimensions required per input
      self._min_dims = [0] * len(input_coredimss)
      for i, inp in enumerate(input_coredimss):
          for d in inp:
              if d[-1] != "?":
                  self._min_dims[i] += 1
  
      # Determine nout: nout = None for functions of one
      # direct return; nout = int for return tuples
      self._nout = (
          0
          if not isinstance(output_coredimss, list)
          else len(output_coredimss)
      )
      self._nin = (
          0
          if not isinstance(input_coredimss, list)
          else len(input_coredimss)
      )
      # Determines the function that will be run depending on the datatypes
      # Pass a list of signatures that are either the types in format
      # ii->o or a tuple with the string and a function other than func to be
      # executed for those types
      # For some reason _nout is a tuple and now we get it with 0s
      self._ops_register = _OpsRegister(
          signatures, self._func, self._nin, self._nout, self.__name__
      )
  
imports: import re
  import numpy
  import cupy
  import cupy._core._routines_manipulation
  from cupy._core._dtype import get_dtype, _raise_if_invalid_cast
  from cupy._core import internal
label_desc: Use image node_id 1 to create a new _GUFunc object  with example: obj = _GUFunc(func, signature)