import torch


def bbox_intersection(bboxes1, bboxes2, aligned=False):
    """
    Compute the intersections among bounding boxes.

    Args:
        bboxes1 (:obj:`nn.Tensor[N, 4]`): Bounding boxes to be computed. They
            are expected to be in ``(x1, y1, x2, y2)`` format.
        bboxes2 (:obj:`nn.Tensor[M, 4]`): Bounding boxes to be computed. They
            are expected to be in ``(x1, y1, x2, y2)`` format.
        aligned (bool, optional): Whether to only compute the intersections
            among aligned bounding boxes. Default: ``False``.

    Returns:
        :obj:`nn.Tensor[N, M]`: The computed intersection values.
    """
    if aligned:
        lt = torch.max(bboxes1[:, :2], bboxes2[:, :2])
        rb = torch.min(bboxes1[:, 2:], bboxes2[:, 2:])

        wh = (rb - lt).clamp(0)
        inter = wh[:, 0] * wh[:, 1]
    else:
        lt = torch.max(bboxes1[:, None, :2], bboxes2[:, :2])
        rb = torch.min(bboxes1[:, None, 2:], bboxes2[:, 2:])

        wh = (rb - lt).clamp(0)
        inter = wh[:, :, 0] * wh[:, :, 1]

    return inter