def circle(
    y_true,
    y_pred,
    ref_labels=None,
    ref_embeddings=None,
    remove_diagonal=True,
    gamma=80,
    margin=0.4,
):
    """Computes the Circle loss.

    It is designed to minimize within-class distances and maximize between-class
    distances in L2 normalized embedding space.

    Args:
        y_true: Tensor with ground truth labels in integer format.
        y_pred: Tensor with predicted L2 normalized embeddings.
        ref_labels: Optional integer tensor with labels for reference
            embeddings. If `None`, defaults to `y_true`.
        ref_embeddings: Optional tensor with L2 normalized reference embeddings.
            If `None`, defaults to `y_pred`.
        remove_diagonal: Boolean, whether to remove self-similarities from
            positive mask. Defaults to `True`.
        gamma: Float, scaling factor for the loss. Defaults to `80`.
        margin: Float, relaxation factor for the loss. Defaults to `0.4`.

    Returns:
        Circle loss value.
    """
    y_pred = ops.convert_to_tensor(y_pred)
    y_true = ops.cast(y_true, "int32")
    ref_embeddings = (
        y_pred
        if ref_embeddings is None
        else ops.convert_to_tensor(ref_embeddings)
    )
    ref_labels = y_true if ref_labels is None else ops.cast(ref_labels, "int32")

    optim_pos = margin
    optim_neg = 1 + margin
    delta_pos = margin
    delta_neg = 1 - margin

    pairwise_cosine_distances = 1 - ops.matmul(
        y_pred, ops.transpose(ref_embeddings)
    )

    pairwise_cosine_distances = ops.maximum(pairwise_cosine_distances, 0.0)
    positive_mask, negative_mask = build_pos_neg_masks(
        y_true,
        ref_labels,
        remove_diagonal=remove_diagonal,
    )
    positive_mask = ops.cast(
        positive_mask, dtype=pairwise_cosine_distances.dtype
    )
    negative_mask = ops.cast(
        negative_mask, dtype=pairwise_cosine_distances.dtype
    )

    pos_weights = optim_pos + pairwise_cosine_distances
    pos_weights = pos_weights * positive_mask
    pos_weights = ops.maximum(pos_weights, 0.0)
    neg_weights = optim_neg - pairwise_cosine_distances
    neg_weights = neg_weights * negative_mask
    neg_weights = ops.maximum(neg_weights, 0.0)

    pos_dists = delta_pos - pairwise_cosine_distances
    neg_dists = delta_neg - pairwise_cosine_distances

    pos_wdists = -1 * gamma * pos_weights * pos_dists
    neg_wdists = gamma * neg_weights * neg_dists

    p_loss = ops.logsumexp(
        ops.where(positive_mask, pos_wdists, float("-inf")),
        axis=1,
    )
    n_loss = ops.logsumexp(
        ops.where(negative_mask, neg_wdists, float("-inf")),
        axis=1,
    )

    circle_loss = ops.softplus(p_loss + n_loss)
    backend.set_keras_mask(circle_loss, circle_loss > 0)
    return circle_loss
Computes the Circle loss.

    It is designed to minimize within-class distances and maximize between-class
    distances in L2 normalized embedding space.

    Args:
        y_true: Tensor with ground truth labels in integer format.
        y_pred: Tensor with predicted L2 normalized embeddings.
        ref_labels: Optional integer tensor with labels for reference
            embeddings. If `None`, defaults to `y_true`.
        ref_embeddings: Optional tensor with L2 normalized reference embeddings.
            If `None`, defaults to `y_pred`.
        remove_diagonal: Boolean, whether to remove self-similarities from
            positive mask. Defaults to `True`.
        gamma: Float, scaling factor for the loss. Defaults to `80`.
        margin: Float, relaxation factor for the loss. Defaults to `0.4`.

    Returns:
        Circle loss value.
    
keras/src/losses/losses.py