code: def modes(valid_types):
      """Decorate a function to cast inputs/outputs to different precision.
  
      >>> support_modes = snt.mixed_precision.modes([tf.float32, tf.float16])
      >>> snt.Linear.__call__ = support_modes(snt.Linear.__call__)
      >>> mod = snt.Linear(10)
      >>> snt.mixed_precision.enable(tf.float16)
      >>> y = mod(tf.ones([1, 1]))  # First call will be done in F32.
      >>> y = mod(tf.ones([1, 1]))  # MatMul/Add will be done in F16.
      >>> snt.mixed_precision.disable()
  
      Args:
        valid_types: Collection of types that the function being decorated is legal
        to run in.
  
      Returns:
        A decorator that will cast the inputs and outputs of the decorated function
        according to the global mixed precision policy and the functions eligibility
        for mixed precision.
      """
      mp_id = uuid.uuid4()
  
      @utils.decorator
      def _wrapper(f, instance, args, kwargs):
          """Decorator to cast inputs and outputs for mixed precision.
  
          Args:
            f: function to handle mixed precision casting for.
            instance: instance of f.
            args: positional arguments to f.
            kwargs: keyword arguments to f.
  
          Returns:
            A wrapped version of `f` that casts input Variables and Tensors to the
            global mixed_precision_mode dtype if that dtype is legal for this function
            as determined by `valid_types`.
          """
          new_dtype = _get_mixed_precision_mode()
          if new_dtype is None or new_dtype not in valid_types:
              # TODO(loreno): consider throwing an error or doing nothing if input dtype
              # doesn't match any valid types
              return f(*args, **kwargs)
  
          if instance is None:
              if not _wrapper.seen_none:
                  # TODO(loreno): Make this thread safe
                  res = f(*args, **kwargs)
                  _wrapper.seen_none = True
                  return res
              return _cast_call(f, new_dtype, args, kwargs)
  
          else:
              seen = getattr(instance, _MP_SEEN_PROPERTY, None)
              if seen is None:
                  seen = set()
                  # TODO(loreno): use a weakrefset to address instances that define slots
                  setattr(instance, _MP_SEEN_PROPERTY, seen)
              if mp_id not in seen:
                  res = f(*args, **kwargs)
                  seen.add(mp_id)
                  return res
              return _cast_call(f, new_dtype, args, kwargs)
  
      _wrapper.seen_none = False
      return _wrapper
  
file_path: sonnet/sonnet/src/mixed_precision.py
imports: import uuid
  import contextlib
  from sonnet.src import custom_getter
  from sonnet.src import utils
  import tensorflow
  import tree
label_desc: Use image node_id 7 for calling a global function with example usage: modes(valid_types) and returns: _wrapper, f, _cast_call, _cast_call, res, res