import torch


def transform_homogeneous(matrices, vertices):
    """Applies batched 4x4 homogenous matrix transformations to 3-D vertices.

    The vertices are input and output as as row-major, but are interpreted as
    column vectors multiplied on the right-hand side of the matrices. More
    explicitly, this function computes (MV^T)^T.
    Vertices are assumed to be xyz, and are extended to xyzw with w=1.

    Args:
        matrices: a [batch_size, 4, 4] tensor of matrices.
        vertices: a [batch_size, N, 3] tensor of xyz vertices.

    Returns:
        a [batch_size, N, 4] tensor of xyzw vertices.

    Raises:
        ValueError: if matrices or vertices have the wrong number of dimensions.
    """
    if len(matrices.shape) != 3:
        raise ValueError(
            'matrices must have 3 dimensions (missing batch dimension?)')
    if len(vertices.shape) != 3:
        raise ValueError(
            'vertices must have 3 dimensions (missing batch dimension?)')
    homogeneous_coord = torch.ones([vertices.shape[0], vertices.shape[1], 1]).to(vertices.device)
    vertices_homogeneous = torch.cat([vertices, homogeneous_coord], 2)

    return torch.matmul(vertices_homogeneous, matrices.transpose(1, 2))