def METHOD_NAME(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)  # pylint: disable=W0632
        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