import torch


def cosine_similarity(x, y=None, eps=1e-8):
  """Calculate cosine similarity between two matrices; 

  Args:
    x: N*p tensor
    y: M*p tensor or None; if None, set y = x
    This function do not broadcast
  
  Returns:
    N*M tensor

  """
  w1 = torch.norm(x, p=2, dim=1, keepdim=True)
  if y is None:
    w2 = w1.squeeze(dim=1)
    y = x
  else:
    w2 = torch.norm(y, p=2, dim=1)
  w12 = torch.mm(x, y.t())
  return w12 / (w1*w2).clamp(min=eps)