import torch


def bbox_giou(box1, box2, x1y1x2y2=True, giou=False):
    """Compute the giou of box1 to box2. box1 is 4, box2 is nx4

    :param box1: box1
    :param box2: box2
    :param x1y1x2y2: xyxy or xywh
    :param giou: giou
    :return: iou or giou
    """
    box2 = box2.t()

    # Get the coordinates of bounding boxes
    if x1y1x2y2:
        # x1, y1, x2, y2 = box1
        box1_x1, box1_y1, box1_x2, box1_y2 = box1[0], box1[1], box1[2], box1[3]
        box2_x1, box2_y1, box2_x2, box2_y2 = box2[0], box2[1], box2[2], box2[3]
    else:
        # x, y, w, h = box1
        box1_x1, box1_x2 = box1[0] - box1[2] / 2, box1[0] + box1[2] / 2
        box1_y1, box1_y2 = box1[1] - box1[3] / 2, box1[1] + box1[3] / 2
        box2_x1, box2_x2 = box2[0] - box2[2] / 2, box2[0] + box2[2] / 2
        box2_y1, box2_y2 = box2[1] - box2[3] / 2, box2[1] + box2[3] / 2

    # Intersection area
    inter_area = (torch.min(box1_x2, box2_x2) - torch.max(box1_x1, box2_x1)).clamp(0) * \
                 (torch.min(box1_y2, box2_y2) - torch.max(box1_y1, box2_y1)).clamp(0)

    # Union Area
    union_area = ((box1_x2 - box1_x1) * (box1_y2 - box1_y1) + 1e-16) + \
                 (box2_x2 - box2_x1) * (box2_y2 - box2_y1) - inter_area

    iou = inter_area / union_area
    if giou:  # Generalized IoU https://arxiv.org/pdf/1902.09630.pdf
        c_x1, c_x2 = torch.min(box1_x1, box2_x1), torch.max(box1_x2, box2_x2)
        c_y1, c_y2 = torch.min(box1_y1, box2_y1), torch.max(box1_y2, box2_y2)
        c_area = (c_x2 - c_x1) * (c_y2 - c_y1) + 1e-16  # convex area
        return iou - (c_area - union_area) / c_area  # giou

    return iou