code: def forward(self, inputs):
      xr, xi = torch.chunk(inputs, 2, axis=self.complex_axis)
      exponential_average_factor = 0.0
  
      if self.training and self.track_running_stats:
          self.num_batches_tracked += 1
          if self.momentum is None:  # use cumulative moving average
              exponential_average_factor = (
                  1.0 / self.num_batches_tracked.item()
              )
          else:  # use exponential moving average
              exponential_average_factor = self.momentum
  
      # NOTE: The precise meaning of the "training flag" is:
      #       True:  Normalize using batch   statistics, update running statistics
      #              if they are being collected.
      #       False: Normalize using running statistics, ignore batch   statistics.
      training = self.training or not self.track_running_stats
      redux = [i for i in reversed(range(xr.dim())) if i != 1]
      vdim = [1] * xr.dim()
      vdim[1] = xr.size(1)
  
      # Mean M Computation and Centering
      # Includes running mean update if training and running.
      if training:
          Mr, Mi = xr, xi
          for d in redux:
              Mr = Mr.mean(d, keepdim=True)
              Mi = Mi.mean(d, keepdim=True)
          if self.track_running_stats:
              self.RMr.lerp_(Mr.squeeze(), exponential_average_factor)
              self.RMi.lerp_(Mi.squeeze(), exponential_average_factor)
      else:
          Mr = self.RMr.view(vdim)
          Mi = self.RMi.view(vdim)
      xr, xi = xr - Mr, xi - Mi
  
      # Variance Matrix V Computation
      # Includes epsilon numerical stabilizer/Tikhonov regularizer.
      # Includes running variance update if training and running.
      if training:
          Vrr = xr * xr
          Vri = xr * xi
          Vii = xi * xi
          for d in redux:
              Vrr = Vrr.mean(d, keepdim=True)
              Vri = Vri.mean(d, keepdim=True)
              Vii = Vii.mean(d, keepdim=True)
          if self.track_running_stats:
              self.RVrr.lerp_(Vrr.squeeze(), exponential_average_factor)
              self.RVri.lerp_(Vri.squeeze(), exponential_average_factor)
              self.RVii.lerp_(Vii.squeeze(), exponential_average_factor)
      else:
          Vrr = self.RVrr.view(vdim)
          Vri = self.RVri.view(vdim)
          Vii = self.RVii.view(vdim)
      Vrr = Vrr + self.eps
      Vri = Vri
      Vii = Vii + self.eps
  
      # Matrix Inverse Square Root U = V^-0.5
      # sqrt of a 2x2 matrix,
      # - https://en.wikipedia.org/wiki/Square_root_of_a_2_by_2_matrix
      tau = Vrr + Vii
      delta = torch.addcmul(Vrr * Vii, -1, Vri, Vri)
      s = delta.sqrt()
      t = (tau + 2 * s).sqrt()
  
      # matrix inverse, http://mathworld.wolfram.com/MatrixInverse.html
      rst = (s * t).reciprocal()
      Urr = (s + Vii) * rst
      Uii = (s + Vrr) * rst
      Uri = (-Vri) * rst
  
      # Optionally left-multiply U by affine weights W to produce combined
      # weights Z, left-multiply the inputs by Z, then optionally bias them.
      #
      # y = Zx + B
      # y = WUx + B
      # y = [Wrr Wri][Urr Uri] [xr] + [Br]
      #     [Wir Wii][Uir Uii] [xi]   [Bi]
      if self.affine:
          Wrr, Wri, Wii = (
              self.Wrr.view(vdim),
              self.Wri.view(vdim),
              self.Wii.view(vdim),
          )
          Zrr = (Wrr * Urr) + (Wri * Uri)
          Zri = (Wrr * Uri) + (Wri * Uii)
          Zir = (Wri * Urr) + (Wii * Uri)
          Zii = (Wri * Uri) + (Wii * Uii)
      else:
          Zrr, Zri, Zir, Zii = Urr, Uri, Uri, Uii
  
      yr = (Zrr * xr) + (Zri * xi)
      yi = (Zir * xr) + (Zii * xi)
  
      if self.affine:
          yr = yr + self.Br.view(vdim)
          yi = yi + self.Bi.view(vdim)
  
      outputs = torch.cat([yr, yi], self.complex_axis)
      return outputs
  
imports: import torch
  import torch.nn
  import torch.nn.functional
label_desc: Use image node_id 5 for calling the ComplexBatchNorm obj's underlying member method code with example usage: obj.forward(inputs) and returns: outputs