class_docstr: Ufunc signature, restricted format suitable for special functions.
  
  Parameters
  ----------
  name
      Name of the ufunc to create
  signature
      String of form 'func: fff*ff->f, func2: ddd->*i' describing
      the C-level functions and types of their input arguments
      and return values.
  
      The syntax is
      'function_name: inputparams*outputparams->output_retval*ignored_retval'
  
  Attributes
  ----------
  name : str
      Python name for the Ufunc
  signatures : list of (func_name, inarg_spec, outarg_spec, ret_spec, header_name)
      List of parsed signatures
  doc : str
      Docstring, obtained from add_newdocs
  function_name_overrides : dict of str->str
      Overrides for the function names in signatures
code: def _get_signatures_and_loops(self, all_loops):
      inarg_num = None
      outarg_num = None
  
      seen = set()
      variants = []
  
      def add_variant(func_name, inarg, outarg, ret, inp, outp):
          if inp in seen:
              return
          seen.add(inp)
  
          sig = (func_name, inp, outp)
          if "v" in outp:
              raise ValueError(f"{self.name}: void signature {sig!r}")
          if len(inp) != inarg_num or len(outp) != outarg_num:
              raise ValueError(
                  "%s: signature %r does not have %d/%d input/output args"
                  % (self.name, sig, inarg_num, outarg_num)
              )
  
          loop_name, loop = generate_loop(inarg, outarg, ret, inp, outp)
          all_loops[loop_name] = loop
          variants.append((func_name, loop_name, inp, outp))
  
      # First add base variants
      for func_name, inarg, outarg, ret, header in self.signatures:
          outp = re.sub(r"\*.*", "", ret) + outarg
          ret = ret.replace("*", "")
          if inarg_num is None:
              inarg_num = len(inarg)
              outarg_num = len(outp)
  
          inp, outp = list(iter_variants(inarg, outp))[0]
          add_variant(func_name, inarg, outarg, ret, inp, outp)
  
      # Then the supplementary ones
      for func_name, inarg, outarg, ret, header in self.signatures:
          outp = re.sub(r"\*.*", "", ret) + outarg
          ret = ret.replace("*", "")
          for inp, outp in iter_variants(inarg, outp):
              add_variant(func_name, inarg, outarg, ret, inp, outp)
  
      # Then sort variants to input argument cast order
      # -- the sort is stable, so functions earlier in the signature list
      #    are still preferred
      variants.sort(key=lambda v: cast_order(v[2]))
  
      return variants, inarg_num, outarg_num
  
imports: import itertools
  import json
  import os
  from stat import ST_MTIME
  import argparse
  import re
  import textwrap
  import numpy
label_desc: Use image node_id 2 for calling the Ufunc obj's underlying member method code with example usage: obj._get_signatures_and_loops(all_loops) and returns: variants,  inarg_num,  outarg_num