function [ fp, fpWarning ] = FreeParams(db, k, r, p, FCVARoptions)

% function [ fp, fpWarning ] = FreeParams(db, k, r, p, FCVARoptions)
% Lee Morin & Morten Nielsen
% August 26, 2011
% 
% FreeParams(db, k, r, p, FCVARoptions) calculates the number of free parameters
%       for the fractional cointegrated VAR model.
% 
% input = scalar or vector db provides the fractional differencing parameters
%           d and b (d = b if db is a scalar).
%   	scalar k is the number of lags.
%  		scalar r is the cointegrating rank.
%   	scalar p is the dimension of the system.
%       cell array of options FCVARoptions = { dbEstnOptions, EstnOptions }, an array of 2 arrays 
%			of options, see DefaultEstnOptions(db0, k, r, p), 
%			RestrictEstnOptions(db0, k, r, p, defaultFCVARoptions), 
%			and AdjustEstnOptions(db0, k, r, p, initialFCVARoptions).
% 
% output = scalar fp is the number of free parameters for the fractional cointegrated VAR model.
%   scalar fpWarning is a binary variable to indicate when fp does not include 
%       the number of free parameters in alpha, beta, and rho. 
% 
% No function dependencies.
% 
% Note: When no restrictions are specified on alpha or beta, the estimation imposes the
% 	identifying restriction that the top rows of beta are equal the identity matrix. This 
%	restriction is included in the calculation of the number of free parameters. 
%   For restricted estimation, it is assumed that the user imposes enough restrictions 
%   such that the parameters are identified. 
% 
% Note: Whenever there are restrictions on both alpha and beta, the warning fpWarning is given 
%   to indicate that the output fp does not include the number of free parameters in alpha, beta, and rho.
%   This happens when there are restrictions placed on both alpha and beta together, 
%   in which case it is possible that some restrictions are redundant. 
%______________________________________________________



% Determine the restrictions on the cointegrating relations.

% Options for estimating fractional differencing parameters.
dbEstnOptions = FCVARoptions{1};
r_db = dbEstnOptions{5};

% Options for model specification and restrictions.
EstnOptions = FCVARoptions{2};
% EstnOptions = { N, M, deterministics, R_Gamma, r_Gamma, [], [], [], 
%                   nCols, A, H, a, b, [], Abar, Aperp, replaceCols, keepCols,
%                   [], [], [], print2screen, printGammas,
%                   restrictFminOptions }
deterministics = EstnOptions(3);
R_Gamma = EstnOptions{4};
r_Gamma = EstnOptions{5};
nCols = EstnOptions{9};
nRestns = length(nCols);
A = EstnOptions{10};
H = EstnOptions{11};
a = EstnOptions{12};
b = EstnOptions{13};

% Define p1 to be number of rows of betaStar.
p1 = p + strcmp(deterministics, 'restricted constant');


% For the unrestricted model.
% fp = length(db) + p*p*k + p*r + r*(p - r) + r*strcmp(deterministics, 'restricted constant');
% In case of restrictions, fp is calculated for each parameter in turn.

% First take the dimensions of the parameter matrices
fpdb = length(db);
fpGamma = p*p*k;
fpBeta = p*r;
fpAlpha = p*r;
fpRho = r*strcmp(deterministics, 'restricted constant');


% Adjust fp for restrictions or identification condition.

fpdb = fpdb - length(r_db);

if ~isempty(R_Gamma)
    % Restrictions on Gamma are represented by ones in the selection matrix R_Gamma.
    fpGamma = fpGamma - sum(sum( R_Gamma ));
end

fpWarning = 0;

% No restrictions on beta, alpha, or rho.
if ( nRestns == 0 )
    % Include the identification condition on beta in case of no restrictions.
    fpBeta = fpBeta - r*r;    

% Restrictions on alpha and beta (betaStar).
else
	fpWarningAlpha = 0;
	fpWarningBeta = 0;
    for i = 1:nRestns

        % Adjust alpha and beta (betaStar) here.
        Ai = A{i};
        if size(Ai,2) < p
            fpAlpha = fpAlpha - p*nCols(i) + size(Ai, 2)*nCols(i);
			fpWarningAlpha = 1;
        end

        Hi = H{i};
        if size(Hi,2) < p1
            fpBeta = fpBeta - size(Hi, 1)*nCols(i) + size(Hi, 2)*nCols(i);
            % Note: If there are restrictions on rho, H is actually Hstar, 
            %   where betaStar = Hstar*phi.
			fpWarningBeta = 1;
        end

        ai = a{i};
        if ~isempty(ai)
            fpAlpha = fpAlpha - p*nCols(i);
			fpWarningAlpha = 1;
        end

        bi = b{i};
        if ~isempty(bi)
            fpBeta = fpBeta - p1*nCols(i);
			fpWarningBeta = 1;
        end

    end
	
	fpWarning = fpWarningAlpha * fpWarningBeta;
    
end

if (fpWarning == 1)
    fpBeta = 0;
    fpAlpha = 0;
	fpRho = 0;
end

fp = fpdb + fpGamma + fpAlpha + fpBeta + fpRho;



% end