def METHOD_NAME(
    self,
    X: np.ndarray,
    R: np.ndarray,
    B: np.ndarray,
    W: np.ndarray,
    H_0: np.ndarray,
    C_0: np.ndarray,
    P: np.ndarray,
    num_directions: int,
) -> Tuple[np.ndarray, np.ndarray]:
    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 = []
    [p_i, p_o, p_f] = np.split(P, 3)
    H_t = H_0
    C_t = C_0
    for x in np.split(X, X.shape[0], axis=0):
        gates = (
            np.dot(x, np.transpose(W))
            + np.dot(H_t, np.transpose(R))
            + np.add(*np.split(B, 2))
        )
        i, o, f, c = np.split(gates, 4, -1)
        i = self.f(i + p_i * C_t)
        f = self.f(f + p_f * C_t)
        c = self.g(c)
        C = f * C_t + i * c
        o = self.f(o + p_o * C)
        H = o * self.h(C)
        h_list.append(H)
        H_t = H
        C_t = C
    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  # type: ignore