'Evaluates the forward through a recurrent layer
:type state_below: theano variable
:param state_below: the input of the recurrent layer
:type mask: None or theano variable
:param mask: mask describing the length of each sequence in a
minibatch
:type init_state: theano variable or None
:param init_state: initial state for the hidden layer
:type n_steps: None or int or theano scalar
:param n_steps: Number of steps the recurrent netowrk does
:type batch_size: int
:param batch_size: the size of the minibatch over which scan runs
:type use_noise: bool
:param use_noise: flag saying if weight noise should be used in
computing the output of this layer
:type truncate_gradient: int
:param truncate_gradient: If negative, no truncation is used,
otherwise truncated BPTT is used, where you go backwards only this
amount of steps
:type no_noise_bias: bool
:param no_noise_bias: flag saying if weight noise should be added to
the bias as well'

def fprop(self, state_below, mask=None, init_state=None, n_steps=None, batch_size=None, use_noise=True, truncate_gradient=(-1), no_noise_bias=False):

    if (theano.config.floatX == 'float32'):
        floatX = numpy.float32
    else:
        floatX = numpy.float64
    if (n_steps is None):
        n_steps = state_below.shape[0]
        if (batch_size and (batch_size != 1)):
            n_steps = (n_steps / batch_size)
    if ((batch_size is None) and (state_below.ndim == 3)):
        batch_size = state_below.shape[1]
    if ((state_below.ndim == 2) and ((not isinstance(batch_size, int)) or (batch_size > 1))):
        state_below = state_below.reshape((n_steps, batch_size, self.n_in))
    if (not init_state):
        if ((not isinstance(batch_size, int)) or (batch_size != 1)):
            init_state = TT.alloc(floatX(0), batch_size, self.n_hids[0])
        else:
            init_state = TT.alloc(floatX(0), self.n_hids[0])
    if mask:
        inps = [state_below, mask]
        fn = (lambda x, y, z: self.step_fprop(x, y, None, z, use_noise=use_noise, no_noise_bias=no_noise_bias))
    else:
        inps = [state_below]
        fn = (lambda tx, ty: self.step_fprop(tx, None, None, ty, use_noise=use_noise, no_noise_bias=no_noise_bias))
    if ((self.dropout < 1.0) and use_noise):
        allhid = numpy.sum(self.n_hids)
        shape = state_below.shape
        if (state_below.ndim == 3):
            alldpmask = self.trng.binomial((n_steps, batch_size, allhid), n=1, p=self.dropout, dtype=state_below.dtype)
        else:
            alldpmask = self.trng.binomial((n_steps, allhid), n=1, p=self.dropout, dtype=state_below.dtype)
        inps.append(alldpmask)
        if mask:
            fn = (lambda x, y, z, u: self.step_fprop(x, y, z, u, use_noise=use_noise))
        else:
            fn = (lambda tx, ty, tu: self.step_fprop(tx, None, ty, tu, use_noise=use_noise))
    (rval, updates) = theano.scan(fn, sequences=inps, outputs_info=(([None] * (self.n_layers - 1)) + [init_state]), name=('layer_%s' % self.name), profile=self.profile, truncate_gradient=truncate_gradient, n_steps=n_steps)
    if (not isinstance(rval, (list, tuple))):
        rval = [rval]
    new_h = rval[(-1)]
    self.out = rval[(-1)]
    self.rval = rval
    self.updates = updates
    return self.out
