code: def _project_perturbation(perturbation, epsilon, input_image, clip_min=None,
                            clip_max=None):
    
  
    if clip_min is None or clip_max is None:
      raise NotImplementedError("_project_perturbation currently has clipping "
                                "hard-coded in.")
  
    # Ensure inputs are in the correct range
    with tf.control_dependencies([
        utils_tf.assert_less_equal(input_image,
                                   tf.cast(clip_max, input_image.dtype)),
        utils_tf.assert_greater_equal(input_image,
                                      tf.cast(clip_min, input_image.dtype))
    ]):
      clipped_perturbation = utils_tf.clip_by_value(
          perturbation, -epsilon, epsilon)
      new_image = utils_tf.clip_by_value(
          input_image + clipped_perturbation, clip_min, clip_max)
      return new_image - input_image
docs: Project `perturbation` onto L-infinity ball of radius `epsilon`.
    Also project into hypercube such that the resulting adversarial example
    is between clip_min and clip_max, if applicable.