📄 gammainc.m
字号:
function b = gammainc(x,a,tail)
%GAMMAINC Incomplete gamma function.
% Y = GAMMAINC(X,A) evaluates the incomplete gamma function for
% corresponding elements of X and A. X and A must be real and the same
% size (or either can be a scalar). A must also be non-negative.
%
% The incomplete gamma function is defined as:
%
% gammainc(x,a) = 1 ./ gamma(a) .*
% integral from 0 to x of t^(a-1) exp(-t) dt
%
% For any a>=0, as x approaches infinity, gammainc(x,a) approaches 1.
% For small x and a, gammainc(x,a) ~= x^a, so gammainc(0,0) = 1.
%
% Y = GAMMAINC(X,A,TAIL) specifies the tail of the incomplete gamma
% function when X is non-negative. Choices are 'lower' (the default)
% and 'upper'. The upper incomplete gamma function is defined as
% 1 - gammainc(x,a).
%
% Warning: When X is negative, Y can be inaccurate for abs(X) > A+1.
%
% Class support for inputs X,A:
% float: double, single
%
% See also GAMMA, GAMMALN, PSI.
% Copyright 1984-2004 The MathWorks, Inc.
% $Revision: 5.17.4.3 $ $Date: 2004/07/05 17:02:00 $
if nargin < 3
lower = true;
else
switch tail
case 'lower', lower = true;
case 'upper', lower = false;
otherwise, error('MATLAB:gammainc:InvalidTailArg', ...
'TAIL must be ''lower'' or ''upper''.');
end
end
% x and a must be compatible for addition.
try
b = x + a;
b(:) = NaN;
catch
error('MATLAB:gammainc:InputSizeMismatch', ...
'X and A must be the same size, or scalars.')
end
if any(a(:) < 0)
error('MATLAB:gammainc:NegativeArg', 'A must be non-negative.')
end
% If a is a vector, make sure x is too.
ascalar = isscalar(a);
if ~ascalar && isscalar(x)
x = repmat(x,size(a));
end
% Upper limit for series and continued fraction.
amax = 2^20;
% Approximation for a > amax. Accurate to about 5.e-5.
k = find(a > amax);
if ~isempty(k)
if ascalar
x = max(amax-1/3 + sqrt(amax/a).*(x-(a-1/3)),0);
a = amax;
else
x(k) = max(amax-1/3 + sqrt(amax./a(k)).*(x(k)-(a(k)-1/3)),0);
a(k) = amax;
end
end
% Series expansion for x < a+1
k = find(a ~= 0 & x ~= 0 & x < a+1);
if ~isempty(k)
xk = x(k);
if ascalar, ak = a; else ak = a(k); end
ap = ak;
del = 1;
sum = del;
while norm(del,'inf') >= 100*eps(norm(sum,'inf'))
ap = ap + 1;
del = xk .* del ./ ap;
sum = sum + del;
end
bk = sum .* exp(-xk + ak.*log(xk) - gammaln(ak+1));
% For very small a, the series may overshoot very slightly.
bk(xk > 0 & bk > 1) = 1;
if lower, b(k) = bk; else b(k) = 1-bk; end
end
% Continued fraction for x >= a+1
k = find(a ~= 0 & x >= a+1); % & x ~= 0
if ~isempty(k)
xk = x(k);
a0 = 1;
a1 = x(k);
b0 = 0;
b1 = a0;
if ascalar, ak = a; else ak = a(k); end
fac = 1 ./ a1;
n = 1;
g = b1 .* fac;
gold = b0;
while norm(g-gold,'inf') >= 100*eps(norm(g,'inf'));
gold = g;
ana = n - ak;
a0 = (a1 + a0 .*ana) .* fac;
b0 = (b1 + b0 .*ana) .* fac;
anf = n*fac;
a1 = xk .* a0 + anf .* a1;
b1 = xk .* b0 + anf .* b1;
fac = 1 ./ a1;
g = b1 .* fac;
n = n + 1;
end
bk = exp(-xk + ak.*log(xk) - gammaln(ak)) .* g;
if lower, b(k) = 1-bk; else b(k) = bk; end
end
k = find(x == 0);
if ~isempty(k)
if lower, b(k) = 0; else b(k) = 1; end
end
k = find(a == 0);
if ~isempty(k)
if ascalar
if lower, b(:) = 1; else b(:) = 0; end
else
if lower, b(k) = 1; else b(k) = 0; end
end
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -