/*--------------------------------------------------------------------------
 * pcfiml.h - definitions/declarations for PcFiml class
 *
 *       (C) Jurgen Doornik 1994-99
 *
 *--------------------------------------------------------------------------*/

#ifndef PCFIML_INCLUDED
#define PCFIML_INCLUDED

#include <database.h>
#include <modelbase.h>
#include <maximize.h>

enum
{   Y_VAR,  X_VAR,  U_VAR,	A_VAR
};
enum
{   M_NONE, M_OLS, M_GIVE, M_FIML, M_3SLS, M_2SLS
};
const decl MN_FIML = 1e-200;


class PcFiml : Modelbase
{
    decl m_fPrintUrf;               // TRUE: print URF results
	decl m_cYlag;					// number of lagged dependent vars
    decl m_cW;                      // number of regressors
    decl m_cU;                      // no of unrestricted regressors
    decl m_cA;                      // no of additional instruments for GIVE
    decl m_asA;                     // names of additional instruments
    decl m_mW;                      // W = (Y_lagged : Z : U)       [m_cT][m_cW]
    decl m_mPi;                     // URF/RRF coefficient matrix   [m_cY][m_cW]
    decl m_mPiUrf;                  // URF coefficient matrix       [m_cY][m_cW]
    decl m_dLogLikUrf;              // URF log-likelihood:
    decl m_mVarPi;                  // variance of coefficients     [m_cY][m_cW]
    decl m_mResidual;               // matrix of residuals V        [m_cT][m_cY]
    decl m_mOmega;                  // URF/RRF residual covariance:V'V/(T-k)
    decl m_mVtVinv;                 // URF/RRF inv(V'V)             [m_cY][m_cY]
    decl m_mVtVinvUrf;              // URF inv(V'V)                 [m_cY][m_cY]
	decl m_mWtWinv;	                // URF inv(W'W)                 [m_cW][m_cW]
    decl m_fCointegration;          // TRUE if Cointegration done
    decl m_mEval;                   // Cointegration eigenvalues	[5][m_cY]
									// and trace statistics, pval,
									// and maxev statistic, pval (all in rows)
    decl m_mAlpha;                  // Cointegration m_mAlpha matrix
    decl m_mBeta;                   // Cointegration m_mBeta matrix
                                    // Model part: cX=m_cY+m_cW
    decl m_iModel;                  // TRUE if model estimated
    decl m_mModsel;                 // Model selection matrix       [m_cY][cX]
    decl m_mIndex;                  // ordered selection matrix     [m_cY][cX]
                                    // Y:Y_lagged:X:U
    decl m_vSelect;                 // indices of coefs in vec(A')  [1][cP]
    decl m_mA;                      // coef matrix: AX'=U'          [m_cY][cX]
    decl m_mSigma;                  // AX'XA/T                      [m_cY][m_cY]
    decl m_mXtX;                    // X'X                          [cX][cX]
    decl m_mVar;                    // var(theta)                   [cP][cP]
    decl m_cKbar;                   // average no of coefs per equation

    PcFiml();                           // constructor
    Estimate();                         // estimate the system
                                        // NB: use ->SetSample() first
	virtual Covar();
	GetModelStatus();					// returns M_.... model status
    SetPrintUrf(fPrintUrf);             // toggles URF print switch
	GetVarNames(const aasY, const aasW);// puts list of eqn and varnnames in args
	
    Cointegration();                    // estimate cointegrating space
    CointegrationI2();                  // I(2) analysis
	GetStatus(const aiConst, const aiTrend);// gets status of Constant&Trend
	Print();							// prints 
	IsUnivariate();
	virtual GetParNames();
	virtual GetPackageName();
	virtual GetPackageVersion();
    Output(const fSys, const fCoint);   // print System and/or Cointegration results
    Chow(const iYear, const iPeriod);   // Break point Chow tests for break
                                        // 2nd regression is up to iYear (iPeriod)
    Portmanteau(const iLag);            // Vector portmanteau test up to lag iLag
    ArTest(const iAr1, const iAr2);     // System vector AR test for lags iAr1...iAr2
    EgeArTest(const iAr1, const iAr2);  // Model vector AR test for lags iAr1...iAr2
    HeteroTest(const fStand,            // Vector heteroscedasticity test
        const fCross);
    NormalityTest();                    // Vector normality test
	UnitRootTest();
    GetPi();                            // returns m_mPi            [m_cY][m_cW]
    GetVarPi();                         // returns m_mVarPi			[m_cY][m_cW]
    GetVarTheta();                      // model: Var[theta] ([cP][cP]), system: Var[Pi] ([m_cW][m_cW])
	GetVarRf();							// model: Var[Pi_rrf] system: Var[Pi_urf] ([m_cY*m_cW][m_cY*m_cW])
    GetOmega();                         // returns m_mOmega
    GetResiduals();                     // returns m_mResidual (rf residuals)
    SetEquation(const sEquation,        // delete or add variable from model
        const aModel);
    TwoSLS();                           // do 2SLS estimation
    ThreeSLS();                         // do 3SLS estimation
    Fiml();                             // do FIML estimation

    printVariables(iGroup, sGroupname); // print names, lag lengths and status
    fCointData(const amDy, const amY_1);// gets partialled out dy and y_1
	iCointDataI2(const amDdy,			// gets data for I(2) analysis
		const amY_1, const amDy_1, const amDdy_1, const amX, const amDx, const amU);
    initializeEGE();
    fCheckRank();
    setModelIndices();
    solveEGE(m_mPi, m_mSigma);
    accumulateEGE(const iMethod);
    fFimlLogLik(const vP, const adFunc, const avScore, const amHessian);
    estimateEGE(iMethod, const fInit, const fAccumulate);
	olsRank(mDy, mY_1, const mW, const amEval, const amBeta, const amAlpha);
};

#endif /* PCFIML_INCLUDED */
