class_docstr: Branchformer encoder layer module.
  
  Args:
      size (int): model dimension
      attn: standard self-attention or efficient attention, optional
      cgmlp: ConvolutionalGatingMLP, optional
      dropout_rate (float): dropout probability
      merge_method (str): concat, learned_ave, fixed_ave
      cgmlp_weight (float): weight of the cgmlp branch, between 0 and 1,
          used if merge_method is fixed_ave
      attn_branch_drop_rate (float): probability of dropping the attn branch,
          used if merge_method is learned_ave
      stochastic_depth_rate (float): stochastic depth probability
docstr: Compute encoded features.
  
  Args:
      x_input (Union[Tuple, torch.Tensor]): Input tensor w/ or w/o pos emb.
          - w/ pos emb: Tuple of tensors [(#batch, time, size), (1, time, size)].
          - w/o pos emb: Tensor (#batch, time, size).
      mask (torch.Tensor): Mask tensor for the input (#batch, 1, time).
      cache (torch.Tensor): Cache tensor of the input (#batch, time - 1, size).
  
  Returns:
      torch.Tensor: Output tensor (#batch, time, size).
      torch.Tensor: Mask tensor (#batch, time).
docstr_tok: ["Compute","encoded","features",".","Args",":","x_input","(","Union","[","Tuple",",","torch.Tensor","]",")",":","Input","tensor","w\/","or","w\/o","pos","emb",".","-","w\/","pos","emb",":","Tuple","of","tensors","[","(","#","batch",",","time",",","size",")",",","(","1",",","time",",","size",")","]",".","-","w\/o","pos","emb",":","Tensor","(","#","batch",",","time",",","size",")",".","mask","(","torch.Tensor",")",":","Mask","tensor","for","the","input","(","#","batch",",","1",",","time",")",".","cache","(","torch.Tensor",")",":","Cache","tensor","of","the","input","(","#","batch",",","time","-","1",",","size",")",".","Returns",":","torch.Tensor",":","Output","tensor","(","#","batch",",","time",",","size",")",".","torch.Tensor",":","Mask","tensor","(","#","batch",",","time",")","."]
code: def forward(self, x_input, mask, cache=None):
      """Compute encoded features.
  
      Args:
          x_input (Union[Tuple, torch.Tensor]): Input tensor w/ or w/o pos emb.
              - w/ pos emb: Tuple of tensors [(#batch, time, size), (1, time, size)].
              - w/o pos emb: Tensor (#batch, time, size).
          mask (torch.Tensor): Mask tensor for the input (#batch, 1, time).
          cache (torch.Tensor): Cache tensor of the input (#batch, time - 1, size).
  
      Returns:
          torch.Tensor: Output tensor (#batch, time, size).
          torch.Tensor: Mask tensor (#batch, time).
      """
  
      if cache is not None:
          raise NotImplementedError(
              "cache is not None, which is not tested"
          )
  
      if isinstance(x_input, tuple):
          x, pos_emb = x_input[0], x_input[1]
      else:
          x, pos_emb = x_input, None
  
      skip_layer = False
      # with stochastic depth, residual connection `x + f(x)` becomes
      # `x <- x + 1 / (1 - p) * f(x)` at training time.
      stoch_layer_coeff = 1.0
      if self.training and self.stochastic_depth_rate > 0:
          skip_layer = torch.rand(1).item() < self.stochastic_depth_rate
          stoch_layer_coeff = 1.0 / (1 - self.stochastic_depth_rate)
  
      if skip_layer:
          if cache is not None:
              x = torch.cat([cache, x], dim=1)
          if pos_emb is not None:
              return (x, pos_emb), mask
          return x, mask
  
      # Two branches
      x1 = x
      x2 = x
  
      # Branch 1: multi-headed attention module
      if self.attn is not None:
          x1 = self.norm_mha(x1)
  
          if isinstance(self.attn, FastSelfAttention):
              x_att = self.attn(x1, mask)
          else:
              if pos_emb is not None:
                  x_att = self.attn(x1, x1, x1, pos_emb, mask)
              else:
                  x_att = self.attn(x1, x1, x1, mask)
  
          x1 = self.dropout(x_att)
  
      # Branch 2: convolutional gating mlp
      if self.cgmlp is not None:
          x2 = self.norm_mlp(x2)
  
          if pos_emb is not None:
              x2 = (x2, pos_emb)
          x2 = self.cgmlp(x2, mask)
          if isinstance(x2, tuple):
              x2 = x2[0]
  
          x2 = self.dropout(x2)
  
      # Merge two branches
      if self.use_two_branches:
          if self.merge_method == "concat":
              x = x + stoch_layer_coeff * self.dropout(
                  self.merge_proj(torch.cat([x1, x2], dim=-1))
              )
          elif self.merge_method == "learned_ave":
              if (
                  self.training
                  and self.attn_branch_drop_rate > 0
                  and torch.rand(1).item() < self.attn_branch_drop_rate
              ):
                  # Drop the attn branch
                  w1, w2 = 0.0, 1.0
              else:
                  # branch1
                  score1 = (
                      self.pooling_proj1(x1).transpose(1, 2)
                      / self.size**0.5
                  )  # (batch, 1, time)
                  if mask is not None:
                      min_value = float(
                          numpy.finfo(
                              torch.tensor(0, dtype=score1.dtype)
                              .numpy()
                              .dtype
                          ).min
                      )
                      score1 = score1.masked_fill(mask.eq(0), min_value)
                      score1 = torch.softmax(
                          score1, dim=-1
                      ).masked_fill(mask.eq(0), 0.0)
                  else:
                      score1 = torch.softmax(score1, dim=-1)
                  pooled1 = torch.matmul(score1, x1).squeeze(
                      1
                  )  # (batch, size)
                  weight1 = self.weight_proj1(pooled1)  # (batch, 1)
  
                  # branch2
                  score2 = (
                      self.pooling_proj2(x2).transpose(1, 2)
                      / self.size**0.5
                  )  # (batch, 1, time)
                  if mask is not None:
                      min_value = float(
                          numpy.finfo(
                              torch.tensor(0, dtype=score2.dtype)
                              .numpy()
                              .dtype
                          ).min
                      )
                      score2 = score2.masked_fill(mask.eq(0), min_value)
                      score2 = torch.softmax(
                          score2, dim=-1
                      ).masked_fill(mask.eq(0), 0.0)
                  else:
                      score2 = torch.softmax(score2, dim=-1)
                  pooled2 = torch.matmul(score2, x2).squeeze(
                      1
                  )  # (batch, size)
                  weight2 = self.weight_proj2(pooled2)  # (batch, 1)
  
                  # normalize weights of two branches
                  merge_weights = torch.softmax(
                      torch.cat([weight1, weight2], dim=-1), dim=-1
                  )  # (batch, 2)
                  merge_weights = merge_weights.unsqueeze(-1).unsqueeze(
                      -1
                  )  # (batch, 2, 1, 1)
                  w1, w2 = (
                      merge_weights[:, 0],
                      merge_weights[:, 1],
                  )  # (batch, 1, 1)
  
              x = x + stoch_layer_coeff * self.dropout(
                  self.merge_proj(w1 * x1 + w2 * x2)
              )
          elif self.merge_method == "fixed_ave":
              x = x + stoch_layer_coeff * self.dropout(
                  self.merge_proj(
                      (1.0 - self.cgmlp_weight) * x1
                      + self.cgmlp_weight * x2
                  )
              )
          else:
              raise RuntimeError(
                  f"unknown merge method: {self.merge_method}"
              )
      else:
          if self.attn is None:
              x = x + stoch_layer_coeff * self.dropout(
                  self.merge_proj(x2)
              )
          elif self.cgmlp is None:
              x = x + stoch_layer_coeff * self.dropout(
                  self.merge_proj(x1)
              )
          else:
              # This should not happen
              raise RuntimeError(
                  "Both branches are not None, which is unexpected."
              )
  
      x = self.norm_final(x)
  
      if pos_emb is not None:
          return (x, pos_emb), mask
  
      return x, mask
  
imports: import logging
  from typing import List, Optional, Tuple, Union
  import numpy
  import torch
  from typeguard import check_argument_types
  from espnet2.asr.encoder.abs_encoder import AbsEncoder
  from espnet2.asr.layers.cgmlp import ConvolutionalGatingMLP
  from espnet2.asr.layers.fastformer import FastSelfAttention
  from espnet.nets.pytorch_backend.nets_utils import make_pad_mask
  from espnet.nets.pytorch_backend.transformer.attention import LegacyRelPositionMultiHeadedAttention, MultiHeadedAttention, RelPositionMultiHeadedAttention
  from espnet.nets.pytorch_backend.transformer.embedding import LegacyRelPositionalEncoding, PositionalEncoding, RelPositionalEncoding, ScaledPositionalEncoding
  from espnet.nets.pytorch_backend.transformer.layer_norm import LayerNorm
  from espnet.nets.pytorch_backend.transformer.repeat import repeat
  from espnet.nets.pytorch_backend.transformer.subsampling import Conv2dSubsampling, Conv2dSubsampling1, Conv2dSubsampling2, Conv2dSubsampling6, Conv2dSubsampling8, TooShortUttError, check_short_utt
label_desc: Use image node_id 2 for calling the BranchformerEncoderLayer obj's underlying member method code with example usage: obj.forward(x_input, mask, cache) and returns: x,  mask, x,  mask, x,  pos_emb,  mask, x,  pos_emb,  mask