Predictive step of Kalman filter.

    Parameters
    ----------
    F:  (dx, dx) numpy array
        Mean of X_t | X_{t-1} is F * X_{t-1} 
    covX: (dx, dx) numpy array 
        covariance of X_t | X_{t-1}
    filt: MeanAndCov object
        filtering distribution at time t-1

    Returns
    -------
    pred: MeanAndCov object
        predictive distribution at time t
    
    Note
    ----
    filt.mean may either be of shape (dx,) or (N, dx); in the latter case 
    N predictive steps are performed in parallel.

def predict_step(F, covX, filt):
    """Predictive step of Kalman filter.

    Parameters
    ----------
    F:  (dx, dx) numpy array
        Mean of X_t | X_{t-1} is F * X_{t-1} 
    covX: (dx, dx) numpy array 
        covariance of X_t | X_{t-1}
    filt: MeanAndCov object
        filtering distribution at time t-1

    Returns
    -------
    pred: MeanAndCov object
        predictive distribution at time t
    
    Note
    ----
    filt.mean may either be of shape (dx,) or (N, dx); in the latter case 
    N predictive steps are performed in parallel. 
    """
    pred_mean = np.matmul(filt.mean, F.T)
    pred_cov = dotdot(F, filt.cov, F.T) + covX
    return MeanAndCov(mean=pred_mean, cov=pred_cov)