import torch


def curl(u, f, method='finitediff', eps=1e-4):
    """Compute the curl of the vector field `f` with respect to the input `u`.

    Args:
        u (torch.Tensor) : the input to the function f of shape [..., D]
        f (function) : some vector field (must support autodiff if using method='autodiff') with output dim [D]
        method (str) : method for calculating the curl. 
            options: ['autodiff', 'finitediff']

        Finite diff currently assumes that `u` represents a 2D vector field.

        Returns:
            (torch.Tensor) : curl of shape [..., 1]
    """
    if method == 'autodiff':
        raise NotImplementedError
    if method == 'finitediff':
        eps_x = torch.tensor([eps, 0.0], device=u.device)
        eps_y = torch.tensor([0.0, eps], device=u.device)
        dfyux = f(u + eps_x)[...,1:2] - f(u - eps_x)[...,1:2] 
        dfxuy = f(u + eps_y)[...,0:1] - f(u - eps_y)[...,0:1]
        return (dfyux+dfxuy)/(eps*2.0)