function r = vertcat(varargin)

% Overloads [p1; p2; ...] for @dprior objects.
%
% Concatenates several @dprior objects into a single one, re-offsetting the
% id* index vectors so that they keep pointing to the right entries of the
% joint parameter vector.
%
% INPUTS
% - varargin   cell array of @dprior objects
%
% OUTPUTS
% - r          [@dprior]  concatenated prior

% Copyright © 2026 Dynare Team
%
% This file is part of Dynare.
%
% Dynare is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare.  If not, see <https://www.gnu.org/licenses/>.

r = dprior();
offset = 0;

for k = 1:numel(varargin)
    o = varargin{k};
    if ~isa(o, 'dprior')
        error('dprior::vertcat: argument %d is not a @dprior object.', k)
    end
    r.p1   = [r.p1;   o.p1];
    r.p2   = [r.p2;   o.p2];
    r.p3   = [r.p3;   o.p3];
    r.p4   = [r.p4;   o.p4];
    r.p5   = [r.p5;   o.p5];
    r.p6   = [r.p6;   o.p6];
    r.p7   = [r.p7;   o.p7];
    r.p11  = [r.p11;  o.p11];
    r.lb   = [r.lb;   o.lb];
    r.ub   = [r.ub;   o.ub];
    r.name = [r.name; o.name];
    r.idbeta      = [r.idbeta;      o.idbeta(:)      + offset];
    r.idgamma     = [r.idgamma;     o.idgamma(:)     + offset];
    r.idgaussian  = [r.idgaussian;  o.idgaussian(:)  + offset];
    r.idinvgamma1 = [r.idinvgamma1; o.idinvgamma1(:) + offset];
    r.iduniform   = [r.iduniform;   o.iduniform(:)   + offset];
    r.idinvgamma2 = [r.idinvgamma2; o.idinvgamma2(:) + offset];
    r.idweibull   = [r.idweibull;   o.idweibull(:)   + offset];
    offset = offset + length(o);
end

return % --*-- Unit tests --*--

%@test:1
% Concatenate three single-parameter priors.
a = dprior('a', 'shape', 'beta',   'mean', 0.4, 'std', 0.2);
b = dprior('b', 'shape', 'gamma',  'mean', 0.5, 'std', 0.1);
c = dprior('c', 'shape', 'normal', 'mean', 0.0, 'std', 1.0);
try
    r = [a; b; c];
    t(1) = true;
catch
    t(1) = false;
end
if t(1)
    t(2) = length(r) == 3;
    t(3) = isequal(r.name, {'a'; 'b'; 'c'});
    t(4) = isequal(r.idbeta, 1);
    t(5) = isequal(r.idgamma, 2);
    t(6) = isequal(r.idgaussian, 3);
    t(7) = isempty(r.iduniform);
end
T = all(t);
%@eof:1

%@test:2
% Concatenate a multi-parameter Path 2 prior with a single-parameter Path 3 prior.
estim_params_ = struct('var_exo', zeros(0,10), 'var_endo', zeros(0,10), ...
                       'corrx', zeros(0,10), 'corrn', zeros(0,10), ...
                       'skew_exo', zeros(0,10), 'endo_init_vals', zeros(0,10), ...
                       'param_vals', [1, 0.4, 0, 1, 1, 0.4, 0.2, 0, 1, NaN; ...
                                      2, 0.5, 0, Inf, 2, 0.5, 0.1, NaN, NaN, NaN]);
M_ = struct('exo_names', {{}}, 'endo_names', {{}}, 'param_names', {{'x'; 'y'}});
a = dprior(estim_params_, M_, 0);
b = dprior('z', 'shape', 'normal', 'mean', 0.0, 'std', 1.0);
try
    r = [a; b];
    t(1) = true;
catch
    t(1) = false;
end
if t(1)
    t(2) = length(r) == 3;
    t(3) = isequal(r.name, {'x'; 'y'; 'z'});
    t(4) = isequal(r.idbeta, 1);
    t(5) = isequal(r.idgamma, 2);
    t(6) = isequal(r.idgaussian, 3);
end
T = all(t);
%@eof:2
