text: # encoding: utf-8
  """
  @author:  liaoxingyu
  @contact: sherlockliao01@gmail.com
  """
  
  import math
  
  import torch
  import torch.nn as nn
  import torch.nn.functional as F
  from torch.nn import Parameter
  
  from ..modeling.losses.loss_utils import one_hot
  
  
  class Circle(nn.Module):
      def __init__(self, cfg, in_feat):
          super().__init__()
          self._num_classes = cfg.MODEL.HEADS.NUM_CLASSES
          self._s = cfg.MODEL.HEADS.SCALE
          self._m = cfg.MODEL.HEADS.MARGIN
  
          self.weight = Parameter(torch.Tensor(self._num_classes, in_feat))
          self.reset_parameters()
  
      def reset_parameters(self):
          nn.init.kaiming_uniform_(self.weight, a=math.sqrt(5))
  
      def forward(self, features, targets):
          sim_mat = F.linear(F.normalize(features), F.normalize(self.weight))
          alpha_p = F.relu(-sim_mat.detach() + 1 + self._m)
          alpha_n = F.relu(sim_mat.detach() + self._m)
          delta_p = 1 - self._m
          delta_n = self._m
  
          s_p = self._s * alpha_p * (sim_mat - delta_p)
          s_n = self._s * alpha_n * (sim_mat - delta_n)
  
          targets = one_hot(targets, self._num_classes)
  
          pred_class_logits = targets * s_p + (1.0 - targets) * s_n
  
          return pred_class_logits
  