import torch


def fgsm_attack(image: torch.Tensor, epsilon: float, data_grad: torch.Tensor, data_range=(-1., 1.)):
    """
    Fast gradient sign method attack as proposed by:
    https://arxiv.org/pdf/1712.07107.pdf

    FGSM is an attack for an infinity-norm bounded adversary.
    """
    sign_data_grad = data_grad.sign()
    perturbed_image = image + epsilon * sign_data_grad
    perturbed_image = torch.clamp(perturbed_image, data_range[0], data_range[1])
    return perturbed_image