def METHOD_NAME(self, features, classes):
    def histogram(inds, size):
        s_repeat_ = s_repeat.clone()
        inds = c_f.to_device(inds, tensor=s_repeat_floor)  # Added to avoid errors
        self.t = c_f.to_device(
            self.t, tensor=s_repeat_floor
        )  # Added to avoid errors
        indsa = (
            (s_repeat_floor - (self.t - self.step) > -self.eps)
            & (s_repeat_floor - (self.t - self.step) < self.eps)
            & inds
        )
        assert (
            indsa.nonzero().size()[0] == size
        ), "Another number of bins should be used"
        zeros = torch.zeros((1, indsa.size()[1])).to(
            device=indsa.device, dtype=torch.uint8
        )
        if self.cuda:
            zeros = zeros.cuda()
        indsb = torch.cat((indsa, zeros))[1:, :].to(
            dtype=torch.bool
        )  # Added to avoid bug with masks of uint8
        s_repeat_[~(indsb | indsa)] = 0
        # indsa corresponds to the first condition of the second equation of the paper
        self.t = self.t.to(
            dtype=s_repeat_.dtype
        )  # Added to avoid errors when using Half precision
        s_repeat_[indsa] = (s_repeat_ - self.t + self.step)[indsa] / self.step
        # indsb corresponds to the second condition of the second equation of the paper
        s_repeat_[indsb] = (-s_repeat_ + self.t + self.step)[indsb] / self.step
        return s_repeat_.sum(1) / size
    classes_size = classes.size()[0]
    classes_eq = (
        classes.repeat(classes_size, 1)
        == classes.view(-1, 1).repeat(1, classes_size)
    ).data
    dists = torch.mm(features, features.transpose(0, 1))
    assert (
        (dists > 1 + self.eps).sum().item() + (dists < -1 - self.eps).sum().item()
    ) == 0, "L2 normalization should be used"
    s_inds = torch.triu(torch.ones(classes_eq.size()), 1).byte()
    if self.cuda:
        s_inds = s_inds.cuda()
    classes_eq = classes_eq.to(
        device=s_inds.device
    )  # Added to avoid errors when using only cpu
    pos_inds = classes_eq[s_inds].repeat(self.tsize, 1)
    neg_inds = ~classes_eq[s_inds].repeat(self.tsize, 1)
    pos_size = classes_eq[s_inds].sum().item()
    neg_size = (~classes_eq[s_inds]).sum().item()
    s = dists[s_inds].view(1, -1)
    s_repeat = s.repeat(self.tsize, 1)
    s_repeat_floor = (torch.floor(s_repeat.data / self.step) * self.step).float()
    histogram_pos = histogram(pos_inds, pos_size)
    assert_almost_equal(
        histogram_pos.sum().item(),
        1,
        decimal=1,
        err_msg="Not good positive histogram",
        verbose=True,
    )
    histogram_neg = histogram(neg_inds, neg_size)
    assert_almost_equal(
        histogram_neg.sum().item(),
        1,
        decimal=1,
        err_msg="Not good negative histogram",
        verbose=True,
    )
    histogram_pos_repeat = histogram_pos.view(-1, 1).repeat(
        1, histogram_pos.size()[0]
    )
    histogram_pos_inds = torch.tril(
        torch.ones(histogram_pos_repeat.size()), -1
    ).byte()
    if self.cuda:
        histogram_pos_inds = histogram_pos_inds.cuda()
    histogram_pos_repeat[histogram_pos_inds] = 0
    histogram_pos_cdf = histogram_pos_repeat.sum(0)
    loss = torch.sum(histogram_neg * histogram_pos_cdf)
    return loss