function M = stack(arraydim,varargin)
%STACK  Stacks input/output models into model array.
%
%   M = STACK(ARRAYDIM,M1,M2,...) produces an array M of input/output models 
%   by stacking the models M1,M2,... along the array dimension ARRAYDIM.  
%   All models must have the same number of inputs and outputs and the I/O 
%   dimensions are not counted as array dimensions.
%
%   For example, if M1 and M2 are two models with the same I/O sizes,
%     * STACK(1,M1,M2) produces a 2-by-1 array
%     * STACK(2,M1,M2) produces a 1-by-2 array
%     * STACK(3,M1,M2) produces a 1-by-1-by-2 array.
%
%   You can also use STACK to concatenate the model arrays M1,M2,... along
%   the array dimension ARRAYDIM.
%
%   See also INPUTOUTPUTMODEL/HORZCAT, INPUTOUTPUTMODEL/VERTCAT, APPEND, 
%   INPUTOUTPUTMODEL.

%   Copyright 1986-2022 The MathWorks, Inc.
ni = nargin-1;

% Offset by the two I/O dimensions
if ~(isscalar(arraydim) && isnumeric(arraydim) && arraydim>0 && rem(arraydim,1)==0)
   error(message('Control:combination:stack1'))
elseif ni<2
   M = varargin{1};  return
end

try
   % Harmonize types
   if ~ltipack.hasMatchingType('stack',varargin{:})
      [varargin{1:ni}] = ltipack.matchType('stack',varargin{:});
   end
   
   % All operands are now of the same type
   M = varargin{1};
   for j=2:ni
      Mj = varargin{j};
      if ~isequal(M.IOSize_,Mj.IOSize_)
         error(message('Control:combination:stack2'))
      end
      % Combine data and metadata
      MMj = stack_(arraydim,M,Mj);
      M = plusMetaData(MMj,M,Mj);
   end
   
   % Consistency checks (e.g., consistent block definition in LFT arrays)
   checkModelArray_(M)
catch E
   if any(strcmp(E.identifier,{'MATLAB:class:undefinedMethod','MATLAB:noSuchMethodOrField'}))
      error(message('Control:combination:stack4',class(M)))
   else
      throw(E)
   end
end

