function xcum = cdf(o, x)

% Evaluate the marginal prior CDF at x (vectorised over parameters).
%
% INPUTS
% - o      [dprior]   Prior object.
% - x      [double]   n×m matrix (n samples, m parameters).
%
% OUTPUTS
% - xcum   [double]   n×m matrix of cumulative probabilities.

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

xcum = NaN(size(x));

if o.has('beta')
    id = o.idbeta;
    xcum(:,id) = betainc((x(:,id)-o.p3(id)')./(o.p4(id)'-o.p3(id)'), o.p6(id)', o.p7(id)');
end

if o.has('gamma')
    id = o.idgamma;
    xcum(:,id) = gamcdf(x(:,id)-o.p3(id)', o.p6(id)', o.p7(id)');
end

if o.has('gaussian')
    id = o.idgaussian;
    xcum(:,id) = 0.5 * erfc(-(x(:,id)-o.p6(id)')./o.p7(id)' ./ sqrt(2));
end

if o.has('invgamma1')
    id = o.idinvgamma1;
    xcum(:,id) = gamcdf(1./(x(:,id)-o.p3(id)').^2, o.p7(id)'/2, 2./o.p6(id)');
end

if o.has('uniform')
    id = o.iduniform;
    xcum(:,id) = (x(:,id)-o.p3(id)')./(o.p4(id)'-o.p3(id)');
end

if o.has('invgamma2')
    id = o.idinvgamma2;
    xcum(:,id) = gamcdf(1./(x(:,id)-o.p3(id)'), o.p7(id)'/2, 2./o.p6(id)');
end

if o.has('weibull')
    id = o.idweibull;
    xcum(:,id) = wblcdf(x(:,id)-o.p3(id)', o.p7(id)', o.p6(id)');
end

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

%@test:1
% Test that cdf returns values in [0,1] and is consistent with from_uniform
% (i.e. cdf is the inverse of from_uniform) on a 7-parameter prior covering
% every distribution family. Built incrementally with add().
Prior = dprior();
Prior.add('p_beta',      'shape', 'beta',       'mean', 0.4, 'std', 0.2, 'prior_trunc', 1e-10);
Prior.add('p_gamma',     'shape', 'gamma',      'mean', 0.4, 'std', 0.2, 'prior_trunc', 1e-10);
Prior.add('p_normal',    'shape', 'normal',     'mean', 0.0, 'std', 1.0, 'prior_trunc', 1e-10);
Prior.add('p_invgamma1', 'shape', 'inv_gamma',  'mean', 0.4, 'std', 0.2, 'prior_trunc', 1e-10);
Prior.add('p_uniform',   'shape', 'uniform',    'lower_bound', 0, 'upper_bound', 1, 'prior_trunc', 1e-10);
Prior.add('p_invgamma2', 'shape', 'inv_gamma2', 'mean', 0.4, 'std', 0.2, 'prior_trunc', 1e-10);
Prior.add('p_weibull',   'shape', 'weibull',    'mean', 0.4, 'std', 0.2, 'prior_trunc', 1e-10);
try
    n = 100;
    X = NaN(n, 7);
    for j = 1:n
        X(j,:) = Prior.draw()';
    end
    C = Prior.cdf(X);
    t(1) = true;
    t(2) = all(C(:) >= 0 & C(:) <= 1);
    t(3) = ~any(isnan(C(:)));
    Xrt = Prior.from_uniform(C);
    t(4) = max(abs(Xrt(:) - X(:))) < 1e-6;
catch
    t(1) = false;
end
T = all(t);
%@eof:1
