class OneStepAheadPredictionErrors {

    public static DataBlock errors(RegArimaModel regarima) {
        IArimaModel arima = regarima.getArima();
        if (regarima.isMeanCorrection()) {
            // increase differencing order and ma polynomial
            arima = new ArimaModel(arima.getStationaryAR(), arima.getNonStationaryAR().times(BackFilter.D1),
                    arima.getMA().times(BackFilter.D1), arima.getInnovationVariance());
        }
        ISsf ssf;
        SsfArima ssfarima = new SsfArima(arima);
        DataBlock y = regarima.getY().deepClone();
        int nx = regarima.getXCount();
        if (nx > 0) {
            Matrix x = new Matrix(y.getLength(), nx);
            for (int i = 0; i < nx; ++i) {
                x.column(i).copy(regarima.X(i));
            }
            ssf = new RegSsf(ssfarima, x.all());
        } else {
            ssf = ssfarima;
        }
        Filter filter = new Filter();
        filter.setSsf(ssf);
        filter.setInitializer(new DiffuseSquareRootInitializer());

        int[] missings = regarima.getMissings();
        if (missings != null) {
            for (int i = 0; i < missings.length; ++i) {
                y.set(missings[i], Double.NaN);
            }
        }
        DiffusePredictionErrorDecomposition ped=new DiffusePredictionErrorDecomposition(true);
        
        filter.process(new SsfData(y, null), ped);
        return new DataBlock(ped.residuals(false));
    }

}