import torch


def compute_angles(
    conformer: torch.Tensor,
    atom_indices: torch.Tensor,
) -> torch.Tensor:
    """Computes the angles [rad] between each atom triplet specified by the
    ``atom_indices``.

    Returns:
        A tensor of the valence angles.
    """

    if len(atom_indices) == 0:
        return torch.tensor([])

    vector_ab = conformer[atom_indices[:, 1]] - conformer[atom_indices[:, 0]]
    vector_ac = conformer[atom_indices[:, 1]] - conformer[atom_indices[:, 2]]

    # tan theta = sin theta / cos theta
    #
    # ||a x b|| = ||a|| ||b|| sin theta
    #   a . b   = ||a|| ||b|| cos theta
    #
    # => tan theta = (a x b) / (a . b)
    angles = torch.atan2(
        torch.norm(torch.cross(vector_ab, vector_ac, dim=-1), dim=-1),
        (vector_ab * vector_ac).sum(dim=-1),
    )

    return angles