class_docstr: Convolutional flow module.
class_docstr_tok: ["Convolutional","flow","module","."]
docstr: Calculate forward propagation.
  
  Args:
      x (Tensor): Input tensor (B, channels, T).
      x_mask (Tensor): Mask tensor (B,).
      g (Optional[Tensor]): Global conditioning tensor (B, channels, 1).
      inverse (bool): Whether to inverse the flow.
  
  Returns:
      Tensor: Output tensor (B, channels, T).
      Tensor: Log-determinant tensor for NLL (B,) if not inverse.
docstr_tok: ["Calculate","forward","propagation",".","Args",":","x","(","Tensor",")",":","Input","tensor","(","B",",","channels",",","T",")",".","x_mask","(","Tensor",")",":","Mask","tensor","(","B",",",")",".","g","(","Optional","[","Tensor","]",")",":","Global","conditioning","tensor","(","B",",","channels",",","1",")",".","inverse","(","bool",")",":","Whether","to","inverse","the","flow",".","Returns",":","Tensor",":","Output","tensor","(","B",",","channels",",","T",")",".","Tensor",":","Log-determinant","tensor","for","NLL","(","B",",",")","if","not","inverse","."]
code: def forward(
      self,
      x: torch.Tensor,
      x_mask: torch.Tensor,
      g: Optional[torch.Tensor] = None,
      inverse: bool = False,
  ) -> Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]:
      """Calculate forward propagation.
  
      Args:
          x (Tensor): Input tensor (B, channels, T).
          x_mask (Tensor): Mask tensor (B,).
          g (Optional[Tensor]): Global conditioning tensor (B, channels, 1).
          inverse (bool): Whether to inverse the flow.
  
      Returns:
          Tensor: Output tensor (B, channels, T).
          Tensor: Log-determinant tensor for NLL (B,) if not inverse.
  
      """
      xa, xb = x.split(x.size(1) // 2, 1)
      h = self.input_conv(xa)
      h = self.dds_conv(h, x_mask, g=g)
      h = (
          self.proj(h) * x_mask
      )  # (B, half_channels * (bins * 3 - 1), T)
  
      b, c, t = xa.shape
      # (B, half_channels, bins * 3 - 1, T) -> (B, half_channels, T, bins * 3 - 1)
      h = h.reshape(b, c, -1, t).permute(0, 1, 3, 2)
  
      # TODO(kan-bayashi): Understand this calculation
      denom = math.sqrt(self.hidden_channels)
      unnorm_widths = h[..., : self.bins] / denom
      unnorm_heights = h[..., self.bins : 2 * self.bins] / denom
      unnorm_derivatives = h[..., 2 * self.bins :]
      xb, logdet_abs = piecewise_rational_quadratic_transform(
          xb,
          unnorm_widths,
          unnorm_heights,
          unnorm_derivatives,
          inverse=inverse,
          tails="linear",
          tail_bound=self.tail_bound,
      )
      x = torch.cat([xa, xb], 1) * x_mask
      logdet = torch.sum(logdet_abs * x_mask, [1, 2])
      if not inverse:
          return x, logdet
      else:
          return x
  
imports: import math
  from typing import Optional, Tuple, Union
  import torch
  from espnet2.gan_tts.vits.transform import piecewise_rational_quadratic_transform
label_desc: Use image node_id 2 for calling the ConvFlow obj's underlying member method code with example usage: obj.forward(x, x_mask, g, inverse) and returns: x,  logdet, x