docstr: Naive iterative implementation of nearest neighbor and chamfer distance.
  x and y are assumed to be pointclouds objects with points and optionally normals.
  This functions supports heterogeneous pointclouds in a batch.
  Returns lists of the unreduced loss and loss_normals.
docstr_tok: ["Naive","iterative","implementation","of","nearest","neighbor","and","chamfer","distance",".","x","and","y","are","assumed","to","be","pointclouds","objects","with","points","and","optionally","normals",".","This","functions","supports","heterogeneous","pointclouds","in","a","batch",".","Returns","lists","of","the","unreduced","loss","and","loss_normals","."]
code: def chamfer_distance_naive_pointclouds(
      p1, p2, norm: int = 2, device="cpu", abs_cosine=True
  ):
      """
      Naive iterative implementation of nearest neighbor and chamfer distance.
      x and y are assumed to be pointclouds objects with points and optionally normals.
      This functions supports heterogeneous pointclouds in a batch.
      Returns lists of the unreduced loss and loss_normals.
      """
      x = p1.points_padded()
      y = p2.points_padded()
      N, P1, D = x.shape
      P2 = y.size(1)
      x_lengths = p1.num_points_per_cloud()
      y_lengths = p2.num_points_per_cloud()
      x_normals = p1.normals_padded()
      y_normals = p2.normals_padded()
  
      return_normals = x_normals is not None and y_normals is not None
  
      # Initialize all distances to + inf
      dist = (
          torch.ones((N, P1, P2), dtype=torch.float32, device=device)
          * np.inf
      )
  
      x_mask = (
          torch.arange(P1, device=x.device)[None] >= x_lengths[:, None]
      )  # shape [N, P1]
      y_mask = (
          torch.arange(P2, device=y.device)[None] >= y_lengths[:, None]
      )  # shape [N, P2]
  
      is_x_heterogeneous = (x_lengths != P1).any()
      is_y_heterogeneous = (y_lengths != P2).any()
      # Only calculate the distances for the points which are not masked
      for n in range(N):
          for i1 in range(x_lengths[n]):
              for i2 in range(y_lengths[n]):
                  if norm == 2:
                      dist[n, i1, i2] = torch.sum(
                          (x[n, i1, :] - y[n, i2, :]) ** 2
                      )
                  elif norm == 1:
                      dist[n, i1, i2] = torch.sum(
                          torch.abs(x[n, i1, :] - y[n, i2, :])
                      )
                  else:
                      raise ValueError(
                          "No support for norm %d" % (norm)
                      )
  
      x_dist = torch.min(dist, dim=2)[0]  # (N, P1)
      y_dist = torch.min(dist, dim=1)[0]  # (N, P2)
  
      if is_x_heterogeneous:
          x_dist[x_mask] = 0.0
      if is_y_heterogeneous:
          y_dist[y_mask] = 0.0
  
      loss = [x_dist, y_dist]
  
      lnorm = [x.new_zeros(()), x.new_zeros(())]
  
      if return_normals:
          x_index = dist.argmin(2).view(N, P1, 1).expand(N, P1, 3)
          y_index = dist.argmin(1).view(N, P2, 1).expand(N, P2, 3)
          cosine_sim1 = F.cosine_similarity(
              x_normals, y_normals.gather(1, x_index), dim=2, eps=1e-6
          )
          cosine_sim2 = F.cosine_similarity(
              y_normals, x_normals.gather(1, y_index), dim=2, eps=1e-6
          )
  
          if abs_cosine:
              lnorm1 = 1 - torch.abs(cosine_sim1)
              lnorm2 = 1 - torch.abs(cosine_sim2)
          else:
              lnorm1 = 1 - cosine_sim1
              lnorm2 = 1 - cosine_sim2
  
          if is_x_heterogeneous:
              lnorm1[x_mask] = 0.0
          if is_y_heterogeneous:
              lnorm2[y_mask] = 0.0
  
          lnorm = [lnorm1, lnorm2]  # [(N, P1), (N, P2)]
  
      return loss, lnorm
  
imports: import unittest
  from collections import namedtuple
  import numpy
  import torch
  import torch.nn.functional
  from pytorch3d.loss import chamfer_distance
  from pytorch3d.structures.pointclouds import Pointclouds
  from .common_testing import get_random_cuda_device, TestCaseMixin
label_desc: Use image node_id 3 for calling the TestChamfer obj's underlying member method code with example usage: obj.chamfer_distance_naive_pointclouds(p1, p2, norm, device, abs_cosine) and returns: loss,  lnorm