class_docstr: Module which computes SIFT descriptors of given patches.
  
  Args:
      patch_size: Input patch size in pixels.
      num_ang_bins: Number of angular bins.
      num_spatial_bins: Number of spatial bins.
      clipval: clipping value to reduce single-bin dominance
      rootsift: if ``True``, RootSIFT (Arandjelović et. al, 2012) is computed.
  
  Returns:
      SIFT descriptor of the patches with shape.
  
  Shape:
      - Input: :math:`(B, 1, \text{num_spatial_bins}, \text{num_spatial_bins})`
      - Output: :math:`(B, \text{num_ang_bins * num_spatial_bins ** 2})`
  
  Example:
      >>> input = torch.rand(23, 1, 32, 32)
      >>> SIFT = SIFTDescriptor(32, 8, 4)
      >>> descs = SIFT(input) # 23x128
code: def forward(self, input: Tensor) -> Tensor:
      KORNIA_CHECK_SHAPE(
          input, ["B", "1", f"{self.patch_size}", f"{self.patch_size}"]
      )
      B: int = input.shape[0]
      self.pk = self.pk.to(input.dtype).to(input.device)
  
      grads = spatial_gradient(input, "diff")
      # unpack the edges
      gx = grads[:, :, 0]
      gy = grads[:, :, 1]
  
      mag = torch.sqrt(gx * gx + gy * gy + self.eps)
      ori = torch.atan2(gy, gx + self.eps) + 2.0 * pi
      mag = mag * self.gk.expand_as(mag).type_as(mag).to(mag.device)
      o_big = float(self.num_ang_bins) * ori / (2.0 * pi)
  
      bo0_big_ = torch.floor(o_big)
      wo1_big_ = o_big - bo0_big_
      bo0_big = bo0_big_ % self.num_ang_bins
      bo1_big = (bo0_big + 1) % self.num_ang_bins
      wo0_big = (1.0 - wo1_big_) * mag
      wo1_big = wo1_big_ * mag
  
      ang_bins = concatenate(
          [
              self.pk(
                  (bo0_big == i).to(input.dtype) * wo0_big
                  + (bo1_big == i).to(input.dtype) * wo1_big
              )
              for i in range(0, self.num_ang_bins)
          ],
          1,
      )
      ang_bins = ang_bins.view(B, -1)
      ang_bins = normalize(ang_bins, p=2)
      ang_bins = torch.clamp(ang_bins, 0.0, float(self.clipval))
      ang_bins = normalize(ang_bins, p=2)
      if self.rootsift:
          ang_bins = torch.sqrt(normalize(ang_bins, p=1) + self.eps)
      return ang_bins
  
imports: import math
  from typing import Tuple
  import torch
  from torch import nn
  from kornia.core import Module, Tensor, concatenate, eye, normalize
  from kornia.core.check import KORNIA_CHECK_SHAPE
  from kornia.filters import get_gaussian_kernel2d, spatial_gradient
  from kornia.geometry.conversions import pi
label_desc: Use image node_id 5 for calling the SIFTDescriptor obj's underlying member method code with example usage: obj.forward(input) and returns: ang_bins