function THIS = subsasgn(THIS,S,B)
% subsasgn  Subscripted assignment for model and syeq objects.
%
% Syntax for assigning parameterisations from other object
% =========================================================
%
%     M(INDEX) = N
%
% Syntax for deleting specified parameterisations
% ================================================
%
%     M(INDEX) = []
%
% Syntax for assigning parameter values or steady-state values
% =============================================================
%
%     M.NAME = X
%     M(INDEX).NAME = X
%     M.NAME(INDEX) = X
%
% Syntax for assigning std deviations or cross-correlations of shocks
% ====================================================================
%
%     M.STD_NAME = X
%     M.CORR_NAME1__NAME2 = X
%
% Note that a double underscore is used to separate the names of shocks in
% correlation coefficients.
%
% Input arguments
% ================
%
% * `M` [ model | syeq ] - Model or syeq object that will be assigned new
% parameterisations or new parameter values or new steady-state values.
%
% * `N` [ model | syeq ] - Model or syeq object compatible with `M` whose
% parameterisations will be assigned (copied) into `M`.
%
% * `INDEX` [ numeric ] - Index of parameterisations that will be assigned
% or deleted.
%
% * `NAME`, `NAME1`, `NAME2` [ char ] - Name of a variable, shock, or
% parameter.
%
% * `X` [ numeric ] - A value (or a vector of values) that will be assigned
% to a parameter or variable named `NAME`.
%
% Output arguments
% =================
%
% * `M` [ model | syeq ] - Model or syeq object with newly assigned or deleted
% parameterisations, or with newly assigned parameters, or steady-state
% values.
%
% Description
% ============
%
% Example
% ========
%
% Expand the number of parameterisations in a model or syeq object that has
% initially just one parameterisation:
%
%     m(1:10) = m;
%
% The parameterisation is simply copied ten times within the model or syeq
% object.
%

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

thisclass = class(THIS);

if ~isa(THIS,'metaobj') ...
        || (~isa(B,'metaobj') && ~isempty(B) && ~isnumeric(B))
    utils.error('metaobj', ...
        ['Invalid subscripted reference or assignment to ',thisclass, ...
        'object.']);
end

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

nalt = size(THIS.Assign,3);

% Fast assignment `THIS.name = x`.
if isnumeric(B) ...
        && (numel(B) == 1 || numel(B) == nalt) ...
        && numel(S) == 1 && S(1).type == '.'
    name = S(1).subs;
    Assign = THIS.Assign;
    [assignpos,stdcorrpos] = mynameposition(THIS,{name});
    if isnan(assignpos) && isnan(stdcorrpos)
        utils.error('metaobj', ...
            ['This name does not exist in the ',thisclass, ...
            ' object: ''%s''.'], ...
            name);
    elseif ~isnan(assignpos)
        Assign(1,assignpos,:) = B;
    else
        THIS.stdcorr(1,stdcorrpos,:) = B;
    end
    THIS.Assign = Assign;
    return
end

nalt = size(THIS.Assign,3);
S = utils.altersubs(S,nalt,class(THIS));

% THIS(index) = B,
% B must be model or empty.

if any(strcmp(S(1).type,{'()','{}'}))
    
    if ~ismodel(B) && ~isempty(B)
        utils.error('metaobj', ...
            ['Invalid subscripted reference or assignment ', ...
            'to ',thisclass,' object.']);
    end
    
    % Make sure the LHS and RHS model objects are compatible in yvector,
    % xvector, and evector.
    if ~iscompatible(THIS,B)
        utils.error('metaobj', ...
            ['Objects A and B are not compatible in ', ...
            'in subscripted assignment A(...) = B.']);
    end
    
    na = size(THIS.Assign,3);
    aindex = S(1).subs{1};
    
    % this([]) = b leaves this unchanged
    if isempty(aindex)
        return
    end
    
    naindex = length(aindex);

    if ismodel(B) && ~isempty(B)
        % this(index) = b
        % where b is this non-empty model
        nb = size(B.Assign,3);
        if nb == 1
            bindex = ones(1,naindex);
        else
            bindex = 1 : nb;
            if naindex ~= nb && nb > 0
                utils.error('metaobj', ...
                    ['Number of parameterisations on the LHS and RHS ', ...
                    'of an assignment to ',thisclass,' object must be the same.']);
            end
        end
        THIS = mysubsalt(THIS,aindex,B,bindex);
    else
        % this(index) = [] or this(index) = b
        % where b is an empty model
        THIS = mysubsalt(THIS,aindex,[]);
    end
    
elseif strcmp(S(1).type,'.')
    % this.name = b or this.name(index) = b
    % b must be numeric
    
    name = S(1).subs;
    
    % Find the position of the name in the Assign vector or stdcorr
    % vector.
    [assignpos,stdcorrpos] = mynameposition(THIS,{name});
    
    % Create the index for third dimension.
    if length(S) > 1
        % this.name(index) = b;
        index2 = S(2).subs{1};
    else
        % this.name = b;
        index2 = ':';
    end
    
    % Assign the value or throw an error.
    if ~isnan(assignpos)
        THIS.Assign(1,assignpos,index2) = B;
    elseif ~isnan(stdcorrpos)
        THIS.stdcorr(1,stdcorrpos,index2) = B;
    else
        utils.error('metaobj', ...
            ['This name does not exist in the ',thisclass, ...
            ' object: ''%s''.'], ...
            name);
    end
    
end

end