import torch


def smooth_l1_loss(pred, targets, beta=2.8):
    """
    SmoothL1(x) = 0.5 * x^2 / beta      if |x| < beta
                  |x| - 0.5 * beta      otherwise.
    """
    diff = pred - targets

    dis_trans = torch.norm(diff, dim=1)

    inbox_idx = torch.tensor(dis_trans <= 2.8, dtype=torch.float32).cuda()
    outbox_idx = torch.tensor(dis_trans > 2.8, dtype=torch.float32).cuda()

    in_pow_diff = 0.5 * torch.pow(diff, 2) / beta
    in_loss = in_pow_diff.sum(dim=1) * inbox_idx

    out_abs_diff = torch.abs(diff)
    out_loss = (out_abs_diff.sum(dim=1) - beta / 2) * outbox_idx

    loss = in_loss + out_loss
    N = loss.size(0)
    loss = loss.view(-1).sum(0) / N
    return loss