function [T,R,A] = system(THIS,DATA,TIME,REQ,IALT)
% system  [Not a public function] Evaluate derivatives of equations wrt variables and shocks.
%
% Backend IRIS function.
% No help provided.

% -IRIS Toolbox.
% -Copyright (c) 2007-2012 Jaromir Benes.

% Input arguments
%
% * `DATA` is 1-by-nname-by-nper.
%
% * `REQ` is either of 'T', 'R', 'TR'.

try
    IALT; %#ok<VUNUS>
catch %#ok<CTCH>
    IALT = 1;
end

%**************************************************************************

ny = sum(THIS.nametype == 1);
nx = sum(THIS.nametype == 2);
ne = sum(THIS.nametype == 3);
maxlag = -THIS.mint;
maxlead = THIS.maxt;
neqtn = length(THIS.eqtn);

try
    DATA; %#ok<VUNUS>
catch %#ok<CTCH>
    DATA = [];
end

try
    TIME; %#ok<VUNUS>
catch %#ok<CTCH>
    TIME = maxlag + 1;
end

try
    REQ; %#ok<VUNUS>
catch %#ok<CTCH>
    REQ = 'TR';
end

if isempty(DATA)
    DATA = zeros(1,ny+nx+ne,max(TIME)+maxlead);
    DATA(1,THIS.log(1:ny+nx+ne),:) = 1;
end
nper = length(TIME);

%**************************************************************************

% Reset shocks to zero.
DATA(:,THIS.nametype == 3,:) = 0;

rett = ~isempty(strfind(REQ,'T'));
retr = ~isempty(strfind(REQ,'R'));
T = [];
R = [];

if rett
    A = zeros(ny,ny,nper);
end
if retr
    R = zeros(ny,ne,nper);
end
L = real(THIS.Assign(1,:,IALT));

% Evaluate derivatives of equations wrt variables and shocks.
for ieq = 1 : neqtn
    if rett
        if isnumeric(THIS.deqtnx{ieq})
            x = THIS.deqtnx{ieq};
        else
            x = THIS.deqtnx{ieq}(DATA,TIME,L);
            if size(x,3) == 1 && nper > 1
                x = x(:,:,ones(1,nper));
            end
            x = permute(x,[2,1,3]);
        end
        nmocc = myfindoccur(THIS,ieq,'variables');
        A(ieq,nmocc,:) = x;
        if ~isnan(THIS.ident(ieq))
            A(ieq,THIS.ident(ieq),:) = -1;
        end
    end
    % Only non-identities will be differentiated wrt shocks.
    if retr && isnan(THIS.ident(ieq))
        if isnumeric(THIS.deqtne{ieq})
            e = THIS.deqtne{ieq};
        else
            e = THIS.deqtne{ieq}(DATA,TIME,L);
            if size(e,3) == 1 && nper > 1
                e = e(:,:,ones(1,nper));
            end
            e = permute(e,[2,1,3]);
        end
        nmocc = myfindoccur(THIS,ieq,'shocks');
        nmocc = nmocc - ny - nx;
        R(ieq,nmocc,:) = e; %#ok<AGROW>
    end
end

% Index of ident equations within transition equations.
identeqtn = ~isnan(THIS.ident);

if rett
    % Index of ident variables.
    identname = false(1,ny);
    identname(THIS.ident(~isnan(THIS.ident))) = true;
    identname = identname(THIS.nametype == 1);
    
    % Split the matrix `A` conformably with identities and non-identities, i.e.
    % [A11,A12;A21,A22]*[ident,nonident]
    A11 = A(identeqtn,identname,:);
    A12 = A(identeqtn,~identname,:);
    A21 = A(~identeqtn,identname,:);
    A22 = A(~identeqtn,~identname,:);
    
    T = nan(size(A22));
    for t = 1 : nper
        T(:,:,t) = A22(:,:,t) + A21(:,:,t)/A11(:,:,t)*A12(:,:,t);
    end
end

if retr
    R = R(~identeqtn,:,:);
end

end