code: def _step(self, X, R, B, W, H_0, num_directions):  # type: ignore
      seq_length = X.shape[0]
      hidden_size = H_0.shape[-1]
      batch_size = X.shape[1]
  
      Y = np.empty(
          [seq_length, num_directions, batch_size, hidden_size]
      )
      h_list = []
  
      [w_z, w_r, w_h] = np.split(W, 3)
      [r_z, r_r, r_h] = np.split(R, 3)
      [w_bz, w_br, w_bh, r_bz, r_br, r_bh] = np.split(B, 6)
      gates_w = np.transpose(np.concatenate((w_z, w_r)))
      gates_r = np.transpose(np.concatenate((r_z, r_r)))
      gates_b = np.add(
          np.concatenate((w_bz, w_br)), np.concatenate((r_bz, r_br))
      )
  
      H_t = H_0
      for x in np.split(X, X.shape[0], axis=0):
          gates = np.dot(x, gates_w) + np.dot(H_t, gates_r) + gates_b
          z, r = np.split(gates, 2, -1)
          z = self.f(z)
          r = self.f(r)
          h_default = self.g(
              np.dot(x, np.transpose(w_h))
              + np.dot(r * H_t, np.transpose(r_h))
              + w_bh
              + r_bh
          )
          h_linear = self.g(
              np.dot(x, np.transpose(w_h))
              + r * (np.dot(H_t, np.transpose(r_h)) + r_bh)
              + w_bh
          )
          h = h_linear if self.linear_before_reset else h_default  # type: ignore
          H = (1 - z) * h + z * H_t
          h_list.append(H)
          H_t = H
  
      concatenated = np.concatenate(h_list)
      if num_directions == 1:
          Y[:, 0, :, :] = concatenated
  
      if self.layout == 0:  # type: ignore
          Y_h = Y[-1]
      else:
          Y = np.transpose(Y, [2, 0, 1, 3])
          Y_h = Y[:, :, -1, :]
  
      return Y, Y_h
  
file_path: onnx/onnx/reference/ops/op_gru.py
imports: import numpy
  from onnx.reference.op_run import OpRun
label_desc: Use image node_id 4 for calling the CommonGRU obj's underlying member method code with example usage: obj._step(X, R, B, W, H_0, num_directions) and returns: Y,  Y_h