dynare/matlab/distributions/lpdfgweibull.m

442 lines
7.4 KiB
Matlab

function [ldens,Dldens,D2ldens] = lpdfgweibull(x,a,b,c)
% Evaluates the logged Weibull PDF at x.
%
% INPUTS
% - x [double] m*n matrix of points where the (logged) density will be evaluated,
% - a [double] m*n matrix of First Weibull distribution parameters (shape parameter, k),
% - b [double] m*n matrix of Second Weibull distribution parameters (scale parameter, λ),
% - c [double] m*n matrix of Third Weibull distribution parameters (location parameter, default is 0).
%
% OUTPUTS
% - ldens [double] m*n matrix of logged (generalized) Weibull densities.
% - Dldens [double] m*n matrix (first order derivatives w.r.t. x)
% - D2ldens [double] m*n matrix (second order derivatives w.r.t. x)
%
% SPECIAL REQUIREMENTS
% none
% Copyright © 2015-2023 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/>.
% Initialize output arguments
ldens = -Inf(size(x));
if nargout>1
Dldens = NaN(size(x));
D2ldens = NaN(size(x));
end
% Check the number of input arguments
if nargin<3
error('CheckInputArgs','At least three input arguments required!')
end
% Set default value for location parameter(s).
if nargin<4
c = zeros(size(x));
end
% Reshape inputs if needed (and possible)
if ~isscalar(x)
if isscalar(a)
a = repmat(a, size(x));
end
if isscalar(b)
b = repmat(b, size(x));
end
if isscalar(c)
c = repmat(c, size(x));
end
end
% Get indices for which the densty is defined
idx = find((x-c)>=0);
% Check size of the inputs
if (~isequal(size(x), size(a)) || ~isequal(size(x), size(b)) || ~isequal(size(x), size(c)))
error('CheckInputArgs','All input arguments must have the same dimensions!')
end
if isempty(idx), return, end
% Compute the logged density
jdx = find( abs(a-1)<1e-12 & x>=c & (x-c)<1e-12) ;
ldens(jdx) = 1.0;
if ~isempty(idx)
x0 = x(idx)-c(idx);
x1 = x0./b(idx);
x2 = x1.^a(idx);
idx = setdiff(idx, jdx);
ldens(idx) = log(a(idx)) - a(idx).*log(b(idx)) + (a(idx)-1).*log(x0) - x2 ;
end
% Compute the first and second derivatives.
if nargout>1
x3 = (a(idx)-1)./x0;
x4 = a(idx).*x2./x1./b(idx);
Dldens(idx) = x3 - x4;
if nargout>2
D2ldens(idx) = -x3./x0 - (a(idx)-1).*x4./x1./b(idx);
end
end
return % --*-- Unit tests --*--
%@test:1
try
lpdfgweibull(1.0);
t(1) = false;
catch
t(1) = true;
end
T = all(t);
%@eof:1
%@test:2
try
lpdfgweibull(1.0, .5);
t(1) = false;
catch
t(1) = true;
end
T = all(t);
%@eof:2
%@test:3
try
lpdfgweibull(ones(2,2), .5*ones(2,1), .1*ones(3,1));
t(1) = false;
catch
t(1) = true;
end
T = all(t);
%@eof:3
%@test:4
try
a = lpdfgweibull(-1, .5, .1);
t(1) = true;
catch
t(1) = false;
end
if t(1)
t(2) = isinf(a);
end
T = all(t);
%@eof:4
%@test:5
try
a = lpdfgweibull(0, 1, 1);
t(1) = true;
catch
t(1) = false;
end
if t(1)
t(2) = abs(a-1.0)<1e-10;
end
T = all(t);
%@eof:5
%@test:6
try
a = lpdfgweibull([0, -1], [1 1], [1 1]);
t(1) = true;
catch
t(1) = false;
end
if t(1)
t(2) = abs(a(1)-1.0)<1e-10;
t(3) = isinf(a(2));
end
T = all(t);
%@eof:6
%@test:7
scale = 1;
shape = 2;
mode = scale*((shape-1)/shape)^(1/shape);
try
[a, b, c] = lpdfgweibull(mode, shape, scale);
p = rand(1000,1)*4;
am = lpdfgweibull(p, shape*ones(size(p)), scale*ones(size(p)));
t(1) = true;
catch
t(1) = false;
end
if t(1)
t(2) = abs(b)<1e-8;
t(3) = c<0;
t(4) = all(am<a);
end
T = all(t);
%@eof:7
%@test:8
scale = 1;
shape = 2;
density = @(x) exp(lpdfgweibull(x,shape,scale));
try
if isoctave
s = quadl(density, .0000000001, 100000, 1e-10);
else
s = integral(density, 0, 100000);
end
t(1) = true;
catch
t(1) = false;
end
if t(1)
t(2) = abs(s-1)<1e-6;
end
T = all(t);
%@eof:8
%@test:9
scale = 1;
shape = 1;
density = @(x) exp(lpdfgweibull(x,shape,scale));
try
if isoctave
s = quadl(density, .0000000001, 100000, 1e-10);
else
s = integral(density, 0, 100000);
end
t(1) = true;
catch
t(1) = false;
end
if t(1)
t(2) = abs(s-1)<1e-6;
end
T = all(t);
%@eof:9
%@test:10
scale = 1;
shape = .5;
density = @(x) exp(lpdfgweibull(x,shape,scale));
try
if isoctave
s = quadl(density, .0000000001, 100000, 1e-10);
else
s = integral(density, 0, 100000);
end
t(1) = true;
catch
t(1) = false;
end
if t(1)
if isoctave
t(2) = abs(s-1)<5e-5;
else
t(2) = abs(s-1)<1e-6;
end
end
T = all(t);
%@eof:10
%@test:11
scale = 1;
shape = 2;
xdens = @(x) x.*exp(lpdfgweibull(x,shape,scale));
try
if isoctave
s = quadgk(xdens, .0000000001, 100000, 1e-10);
else
s = integral(xdens, 0, 100000);
end
t(1) = true;
catch
t(1) = false;
end
if t(1)
t(2) = abs(s-scale*gamma(1+1/shape))<1e-6;
end
T = all(t);
%@eof:11
%@test:12
scale = 1;
shape = 1;
xdens = @(x) x.*exp(lpdfgweibull(x,shape,scale));
try
if isoctave
s = quadl(xdens, .0000000001, 100000, 1e-10);
else
s = integral(xdens, 0, 100000);
end
t(1) = true;
catch
t(1) = false;
end
if t(1)
t(2) = abs(s-scale*gamma(1+1/shape))<1e-6;
end
T = all(t);
%@eof:12
%@test:13
scale = 1;
shape = .5;
xdens = @(x) x.*exp(lpdfgweibull(x,shape,scale));
try
if isoctave
s = quadl(xdens, .0000000001, 100000, 1e-10);
else
s = integral(xdens, 0, 100000);
end
t(1) = true;
catch
t(1) = false;
end
if t(1)
t(2) = abs(s-scale*gamma(1+1/shape))<1e-6;
end
T = all(t);
%@eof:13
%@test:14
scale = 1;
shape = 2;
density = @(x) exp(lpdfgweibull(x,shape,scale));
n = 200;
try
s = NaN(n, 1);
for i=1:n
if isoctave
s(i) = quadl(density, .0000000001, .1*i, 1e-10);
else
s(i) = integral(density, 0, .1*i);
end
end
t(1) = true;
catch
t(1) = false;
end
if t(1)
for i=1:n
x = .1*i;
q = 1-exp(-(x/scale)^shape);
t(i+1) = abs(s(i)-q)<1e-6;
end
end
T = all(t);
%@eof:14
%@test:15
scale = 1;
shape = 1;
density = @(x) exp(lpdfgweibull(x,shape,scale));
n = 200;
try
s = NaN(n, 1);
for i=1:n
if isoctave
s(i) = quadl(density, .0000000001, .1*i, 1e-10);
else
s(i) = integral(density, 0, .1*i);
end
end
t(1) = true;
catch
t(1) = false;
end
if t(1)
for i=1:n
x = .1*i;
q = 1-exp(-(x/scale)^shape);
t(i+1) = abs(s(i)-q)<1e-6;
end
end
T = all(t);
%@eof:15
%@test:16
scale = 1;
shape = .5;
density = @(x) exp(lpdfgweibull(x,shape,scale));
n = 200;
try
s = NaN(n, 1);
for i=1:n
if isoctave
s(i) = quadl(density, .0000000001, .1*i, 1e-10);
else
s(i) = integral(density, 0, .1*i);
end
end
t(1) = true;
catch
t(1) = false;
end
if t(1)
for i=1:n
x = .1*i;
q = 1-exp(-(x/scale)^shape);
if isoctave
t(i+1) = abs(s(i)-q)<5e-5;
else
t(i+1) = abs(s(i)-q)<1e-6;
end
end
end
T = all(t);
%@eof:16