import torch


def halfplane_to_disk(points):
    """Moebius map from the Poincare half-plane to the Poincare disk."""
    x = points[..., :-1]
    y = points[..., -1:]
    sqnorms = (points ** 2).sum(-1, keepdim=True)
    s = 1 / (1 + 2 * y + sqnorms)

    return torch.cat((2 * s * x, s * (sqnorms - 1)), dim=-1)