class_docstr: the Mem-LSTM of SkiM
  
  args:
      hidden_size: int, dimension of the hidden state.
      dropout: float, dropout ratio. Default is 0.
      bidirectional: bool, whether the LSTM layers are bidirectional.
          Default is False.
      mem_type: 'hc', 'h', 'c' or 'id'.
          It controls whether the hidden (or cell) state of
          SegLSTM will be processed by MemLSTM.
          In 'id' mode, both the hidden and cell states will
          be identically returned.
      norm_type: gLN, cLN. cLN is for causal implementation.
class_docstr_tok: ["the","Mem-LSTM","of","SkiM","args",":","hidden_size",":","int",",","dimension","of","the","hidden","state",".","dropout",":","float",",","dropout","ratio",".","Default","is","0.","bidirectional",":","bool",",","whether","the","LSTM","layers","are","bidirectional",".","Default","is","False",".","mem_type",":","'hc","'",",","'","h","'",",","'","c","'","or","'id","'",".","It","controls","whether","the","hidden","(","or","cell",")","state","of","SegLSTM","will","be","processed","by","MemLSTM",".","In","'id","'","mode",",","both","the","hidden","and","cell","states","will","be","identically","returned",".","norm_type",":","gLN",",","cLN",".","cLN","is","for","causal","implementation","."]
code: def forward(self, hc, S):
      # hc = (h, c), tuple of hidden and cell states from SegLSTM
      # shape of h and c: (d, B*S, H)
      # S: number of segments in SegLSTM
  
      if self.mem_type == "id":
          ret_val = hc
          h, c = hc
          d, BS, H = h.shape
          B = BS // S
      else:
          h, c = hc
          d, BS, H = h.shape
          B = BS // S
          h = (
              h.transpose(1, 0).contiguous().view(B, S, d * H)
          )  # B, S, dH
          c = (
              c.transpose(1, 0).contiguous().view(B, S, d * H)
          )  # B, S, dH
          if self.mem_type == "hc":
              h = h + self.h_norm(self.h_net(h)[0])
              c = c + self.c_norm(self.c_net(c)[0])
          elif self.mem_type == "h":
              h = h + self.h_norm(self.h_net(h)[0])
              c = torch.zeros_like(c)
          elif self.mem_type == "c":
              h = torch.zeros_like(h)
              c = c + self.c_norm(self.c_net(c)[0])
  
          h = h.view(B * S, d, H).transpose(1, 0).contiguous()
          c = c.view(B * S, d, H).transpose(1, 0).contiguous()
          ret_val = (h, c)
  
      if not self.bidirectional:
          # for causal setup
          causal_ret_val = []
          for x in ret_val:
              x = x.transpose(1, 0).contiguous().view(B, S, d * H)
              x_ = torch.zeros_like(x)
              x_[:, 1:, :] = x[:, :-1, :]
              x_ = x_.view(B * S, d, H).transpose(1, 0).contiguous()
              causal_ret_val.append(x_)
          ret_val = tuple(causal_ret_val)
  
      return ret_val
  
file_path: espnet/espnet2/enh/layers/skim.py
imports: import torch
  import torch.nn
  from espnet2.enh.layers.dprnn import SingleRNN, merge_feature, split_feature
  from espnet2.enh.layers.tcn import choose_norm
label_desc: Use image node_id 3 for calling the MemLSTM obj's underlying member method code with example usage: obj.forward(hc, S) and returns: ret_val