import torch


def compute_iou(pred, gt):
    """ Calculates IoU (Jaccard index) of two sets of bboxes:
            IOU = pred ∩ gt / (area(pred) + area(gt) - pred ∩ gt)
        Parameters:
            Coordinates of bboxes are supposed to be in the following form: [x1, y1, x2, y2]
            pred (torch.tensor): predicted bboxes
            gt (torch.tensor): ground truth bboxes
        Return value:
            iou (torch.tensor): intersection over union
    """
    def get_box_area(box):
        return (box[:, 2] - box[:, 0] + 1.) * (box[:, 3] - box[:, 1] + 1.)

    #_gt = torch.tile(gt, (pred.shape[0], 1))
    _gt = gt.repeat(pred.shape[0], 1)
    _pred = torch.repeat_interleave(pred, gt.shape[0], dim=0)

    ixmin = torch.maximum(_gt[:, 0], _pred[:, 0])
    iymin = torch.maximum(_gt[:, 1], _pred[:, 1])
    ixmax = torch.minimum(_gt[:, 2], _pred[:, 2])
    iymax = torch.minimum(_gt[:, 3], _pred[:, 3])

    width = torch.maximum(ixmax - ixmin + 1., torch.tensor(0))
    height = torch.maximum(iymax - iymin + 1., torch.tensor(0))

    intersection_area = width * height
    union_area = get_box_area(_gt) + get_box_area(_pred) - intersection_area
    iou = (intersection_area / union_area).reshape(pred.shape[0], gt.shape[0])
    return iou