'Time step unrolling portion of recurrent layer fprop.
Arguments:
W_recur (Tensor): Recurrent weight matrix.
h_prev_s (Array): Array of per time step hidden state tensors. Each
element in the array is a single time step view into one tensor
containing all of the time steps in sequence.
h_ff_s (Array): Array of per time step hidden state tensors. Each
element in the array is a single time step view into one tensor
containing all of the time steps in sequence.
h_s (Array): Array of per time step hidden state tensors. Each
element in the array is a single time step view into one tensor
containing all of the time steps in sequence.
bias (Tensor): Bias tensor to add at each time step.
nout (integer): Number of output units for the layer.
num_steps (integer): Total number of time steps in the buffer.
num_used_steps (integer): Number of time steps being used for real
data.
activation (Transform): Activation function for the layer.
reverse (boolean): When true, unrolling will iterate over time steps
in reverse (for BiRNN).'

def compound_rnn_unroll_fprop(self, W_recur, h_prev_s, h_ff_s, h_s, bias, nout, num_steps, num_used_steps, activation, reverse=False):

    if ((nout <= 1152) and (self.bsz == 4) and ((nout % 48) == 0)):
        persistent_kernel = True
        num_blocks = (nout // 48)
    else:
        persistent_kernel = False
        num_blocks = ((- ((- h_s[0].shape[0]) // 128)) * (- ((- h_s[0].shape[1]) // 32)))
        num_blocks = (- ((- num_blocks) // 4))
    if ((activation.classnm == 'Rectlinclip') and (num_blocks <= self.sm_count) and (not self.use_cudac_kernels) and (activation.slope == 0)):
        if (h_s[0].base is not h_ff_s[0].base):
            if (len(h_s[0].base.shape) == 3):
                assert ((h_ff_s[0].base.shape[1] + 2) == h_s[0].base.shape[1])
                h_buffer = h_s[0].base[:, 1:(-1)].reshape(nout, (-1))
                h_ff_buffer = h_ff_s[0].base.reshape(nout, (-1))
                h_buffer[:] = h_ff_buffer
            else:
                h_s[0].base[:] = h_ff_s[0].base
        if ((num_used_steps is not None) and (num_used_steps < num_steps)):
            num_steps = num_used_steps
        if persistent_kernel:
            self._persistent_rnn_fprop(W_recur, h_prev_s[0], h_s[0], bias, nout, nout, self.bsz, num_steps, activation, reverse)
        else:
            self._compound_unrolled_gemm(W_recur, h_prev_s[0], h_s[0], bias, nout, nout, self.bsz, num_steps, activation, reverse)
    else:
        if ((num_used_steps is not None) and (num_used_steps < num_steps)):
            h_s = h_s[:num_used_steps]
            h_prev_s = h_prev_s[:num_used_steps]
            h_ff_s = h_ff_s[:num_used_steps]
        if reverse:
            steps = reversed(list(zip(h_s, h_prev_s, h_ff_s)))
        else:
            steps = list(zip(h_s, h_prev_s, h_ff_s))
        for (h, h_prev, h_ff) in steps:
            if (h_ff is h):
                self.compound_dot(W_recur, h_prev, h, beta=1.0)
                h[:] = activation((h + bias))
            else:
                self.compound_dot(W_recur, h_prev, h)
                h[:] = activation(((h + h_ff) + bias))
