function compute_hyperparameters(o, pshape, prior_trunc)

% Computes hyperparameters (p5, p6, p7), fills default bounds (p3, p4),
% truncated bounds (lb, ub), and sets the id* index vectors on a dprior
% object whose p1-p4 and name properties are already populated.
%
% INPUTS
% - o            [dprior]   object with p1, p2, p3, p4, name already set
% - pshape       [double]   n×1 vector of shape codes
% - prior_trunc  [double]   probability mass to exclude from tails

% 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/>.

n = length(o.p1);
o.p5 = zeros(n, 1);
o.p6 = NaN(n, 1);
o.p7 = NaN(n, 1);
o.p11 = NaN(n, 1);

% Beta distribution
k = find(pshape == 1);
k1 = find(isnan(o.p3(k)));
o.p3(k(k1)) = zeros(length(k1), 1);
k1 = find(isnan(o.p4(k)));
o.p4(k(k1)) = ones(length(k1), 1);
for i = 1:length(k)
    [o.p6(k(i)), o.p7(k(i))] = beta_specification(o.p1(k(i)), o.p2(k(i))^2, o.p3(k(i)), o.p4(k(i)), o.name{k(i)});
    m = compute_prior_mode([o.p6(k(i)), o.p7(k(i)), o.p3(k(i)), o.p4(k(i))], 1);
    if isscalar(m)
        o.p5(k(i)) = m;
    else
        o.p5(k(i)) = m(1);
    end
end

% Gamma distribution
k = find(pshape == 2);
k1 = find(isnan(o.p3(k)));
k2 = find(isnan(o.p4(k)));
o.p3(k(k1)) = zeros(length(k1), 1);
o.p4(k(k2)) = Inf(length(k2), 1);
for i = 1:length(k)
    [o.p6(k(i)), o.p7(k(i))] = gamma_specification(o.p1(k(i)), o.p2(k(i))^2, o.p3(k(i)), o.name{k(i)});
    o.p5(k(i)) = compute_prior_mode([o.p6(k(i)), o.p7(k(i)), o.p3(k(i))], 2);
end

% Normal distribution
k = find(pshape == 3);
k1 = find(isnan(o.p3(k)));
k2 = find(isnan(o.p4(k)));
o.p3(k(k1)) = -Inf(length(k1), 1);
o.p4(k(k2)) = Inf(length(k2), 1);
o.p6(k) = o.p1(k);
o.p7(k) = o.p2(k);
o.p5(k) = o.p1(k);

% Inverse Gamma (type 1)
k = find(pshape == 4);
k1 = find(isnan(o.p3(k)));
k2 = find(isnan(o.p4(k)));
o.p3(k(k1)) = zeros(length(k1), 1);
o.p4(k(k2)) = Inf(length(k2), 1);
for i = 1:length(k)
    [o.p6(k(i)), o.p7(k(i))] = inverse_gamma_specification(o.p1(k(i)), o.p2(k(i))^2, o.p3(k(i)), 1, false, o.name{k(i)});
    o.p5(k(i)) = compute_prior_mode([o.p6(k(i)), o.p7(k(i)), o.p3(k(i))], 4);
end

% Uniform distribution
k = find(pshape == 5);
problem_parameters_1 = '';
problem_parameters_2 = '';
for i = 1:length(k)
    [o.p1(k(i)), o.p2(k(i)), o.p6(k(i)), o.p7(k(i)), error_indicator] = ...
        uniform_specification(o.p1(k(i)), o.p2(k(i)), o.p3(k(i)), o.p4(k(i)));
    if error_indicator == 1
        if isempty(problem_parameters_1)
            problem_parameters_1 = o.name{k(i)};
        else
            problem_parameters_1 = [problem_parameters_1 ', ' o.name{k(i)}];
        end
    elseif error_indicator == 2
        if isempty(problem_parameters_2)
            problem_parameters_2 = o.name{k(i)};
        else
            problem_parameters_2 = [problem_parameters_2 ', ' o.name{k(i)}];
        end
    end
    o.p3(k(i)) = o.p6(k(i));
    o.p4(k(i)) = o.p7(k(i));
    o.p5(k(i)) = NaN;
end
if ~isempty(problem_parameters_1)
    error(['uniform_specification: You defined lower and upper bounds for parameter ', problem_parameters_1, '. In this case, you need to leave mean and standard deviation empty.'])
end
if ~isempty(problem_parameters_2)
    error(['uniform_specification: Mean or standard deviation for parameter ', problem_parameters_2, ' is not finite. Please check your prior specification.'])
end

% Inverse Gamma (type 2)
k = find(pshape == 6);
k1 = find(isnan(o.p3(k)));
k2 = find(isnan(o.p4(k)));
o.p3(k(k1)) = zeros(length(k1), 1);
o.p4(k(k2)) = Inf(length(k2), 1);
for i = 1:length(k)
    [o.p6(k(i)), o.p7(k(i))] = inverse_gamma_specification(o.p1(k(i)), o.p2(k(i))^2, o.p3(k(i)), 2, false, o.name{k(i)});
    o.p5(k(i)) = compute_prior_mode([o.p6(k(i)), o.p7(k(i)), o.p3(k(i))], 6);
end

% Weibull distribution
k = find(pshape == 8);
k1 = find(isnan(o.p3(k)));
k2 = find(isnan(o.p4(k)));
o.p3(k(k1)) = zeros(length(k1), 1);
o.p4(k(k2)) = Inf(length(k2), 1);
for i = 1:length(k)
    [o.p6(k(i)), o.p7(k(i))] = weibull_specification(o.p1(k(i)), o.p2(k(i))^2, o.p3(k(i)), o.name{k(i)});
    o.p5(k(i)) = compute_prior_mode([o.p6(k(i)), o.p7(k(i)), o.p3(k(i))], 8);
end

% Truncated bounds
tmpstruct.pshape = pshape;
tmpstruct.p3 = o.p3;
tmpstruct.p4 = o.p4;
tmpstruct.p6 = o.p6;
tmpstruct.p7 = o.p7;
bounds = prior_bounds(tmpstruct, prior_trunc);
o.lb = bounds.lb;
o.ub = bounds.ub;

% Index vectors
o.idbeta      = find(pshape == 1);
o.idgamma     = find(pshape == 2);
o.idgaussian  = find(pshape == 3);
o.idinvgamma1 = find(pshape == 4);
o.iduniform   = find(pshape == 5);
o.idinvgamma2 = find(pshape == 6);
o.idweibull   = find(pshape == 8);
