-
Notifications
You must be signed in to change notification settings - Fork 0
/
Gamma.m
98 lines (82 loc) · 2.35 KB
/
Gamma.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
function [f] = Gamma(z)
% GAMMA Gamma function valid in the entire complex plane.
% Accuracy is 15 significant digits along the real axis
% and 13 significant digits elsewhere.
% This routine uses a superb Lanczos series
% approximation for the complex Gamma function.
%
% z may be complex and of any size.
% Also n! = prod(1:n) = gamma(n+1)
%
%usage: [f] = gamma(z)
%
%tested on versions 6.0 and 5.3.1 under Sun Solaris 5.5.1
%
%References: C. Lanczos, SIAM JNA 1, 1964. pp. 86-96
% Y. Luke, "The Special ... approximations", 1969 pp. 29-31
% Y. Luke, "Algorithms ... functions", 1977
% J. Spouge, SIAM JNA 31, 1994. pp. 931-944
% W. Press, "Numerical Recipes"
% S. Chang, "Computation of special functions", 1996
% W. J. Cody "An Overview of Software Development for Special
% Functions", 1975
%
%see also: GAMMA GAMMALN GAMMAINC PSI
%see also: mhelp GAMMA
%
%Paul Godfrey
%http://winnie.fit.edu/~gabdo/gamma.txt
%Sept 11, 2001
siz = size(z);
z=z(:);
zz=z;
f = 0.*z; % reserve space in advance
p=find(real(z)<0);
if ~isempty(p)
z(p)=-z(p);
end
% 15 sig. digits for 0<=real(z)<=171
% coeffs should sum to about g*g/2+23/24
g=607/128; % best results when 4<=g<=5
c = [ 0.99999999999999709182;
57.156235665862923517;
-59.597960355475491248;
14.136097974741747174;
-0.49191381609762019978;
.33994649984811888699e-4;
.46523628927048575665e-4;
-.98374475304879564677e-4;
.15808870322491248884e-3;
-.21026444172410488319e-3;
.21743961811521264320e-3;
-.16431810653676389022e-3;
.84418223983852743293e-4;
-.26190838401581408670e-4;
.36899182659531622704e-5];
%Num Recipes used g=5 with 7 terms
%for a less effective approximation
z=z-1;
zh =z+0.5;
zgh=zh+g;
%trick for avoiding FP overflow above z=141
zp=zgh.^(zh*0.5);
ss=0.0;
for pp=size(c,1)-1:-1:1
ss=ss+c(pp+1)./(z+pp);
end
%sqrt(2Pi)
sq2pi= 2.5066282746310005024157652848110;
f=(sq2pi*(c(1)+ss)).*((zp.*exp(-zgh)).*zp);
f(z==0 | z==1) = 1.0;
%adjust for negative real parts
if ~isempty(p)
f(p)=-pi./(zz(p).*f(p).*sin(pi*zz(p)));
end
%adjust for negative poles
p=find(round(zz)==zz & imag(zz)==0 & real(zz)<=0);
if ~isempty(p)
f(p)=Inf;
end
f=reshape(f,siz);
return