]> git.uio.no Git - u/mrichter/AliRoot.git/blame - RALICE/AliMath.cxx
This commit was generated by cvs2svn to compensate for changes in r165,
[u/mrichter/AliRoot.git] / RALICE / AliMath.cxx
CommitLineData
d88f97cc 1#include "AliMath.h"
2
3ClassImp(AliMath) // Class implementation to enable ROOT I/O
4
5AliMath::AliMath()
6{
7// Default constructor
8}
9///////////////////////////////////////////////////////////////////////////
10AliMath::~AliMath()
11{
12// Destructor
13}
14///////////////////////////////////////////////////////////////////////////
15Float_t AliMath::Gamma(Float_t z)
16{
17// Computation of gamma(z) for all z>0.
18//
19// The algorithm is based on the article by C.Lanczos [1] as denoted in
20// Numerical Recipes 2nd ed. on p. 207 (W.H.Press et al.).
21//
22// [1] C.Lanczos, SIAM Journal of Numerical Analysis B1 (1964), 86.
23//
24//--- Nve 14-nov-1998 UU-SAP Utrecht
25
26 if (z<=0.)
27 {
28 cout << "*Gamma(z)* Wrong argument z = " << z << endl;
29 return 0;
30 }
31
32 Float_t v=LnGamma(z);
33 return exp(v);
34}
35///////////////////////////////////////////////////////////////////////////
36Float_t AliMath::Gamma(Float_t a,Float_t x)
37{
38// Computation of the incomplete gamma function P(a,x)
39//
40// The algorithm is based on the formulas and code as denoted in
41// Numerical Recipes 2nd ed. on p. 210-212 (W.H.Press et al.).
42//
43//--- Nve 14-nov-1998 UU-SAP Utrecht
44
45 if (a<=0.)
46 {
47 cout << "*Gamma(a,x)* Invalid argument a = " << a << endl;
48 return 0;
49 }
50
51 if (x<=0.)
52 {
53 if (x<0) cout << "*Gamma(a,x)* Invalid argument x = " << x << endl;
54 return 0;
55 }
56
57 if (x<(a+1.))
58 {
59 return GamSer(a,x);
60 }
61 else
62 {
63 return GamCf(a,x);
64 }
65}
66///////////////////////////////////////////////////////////////////////////
67Float_t AliMath::LnGamma(Float_t z)
68{
69// Computation of ln[gamma(z)] for all z>0.
70//
71// The algorithm is based on the article by C.Lanczos [1] as denoted in
72// Numerical Recipes 2nd ed. on p. 207 (W.H.Press et al.).
73//
74// [1] C.Lanczos, SIAM Journal of Numerical Analysis B1 (1964), 86.
75//
76// The accuracy of the result is better than 2e-10.
77//
78//--- Nve 14-nov-1998 UU-SAP Utrecht
79
80 if (z<=0.)
81 {
82 cout << "*LnGamma(z)* Wrong argument z = " << z << endl;
83 return 0;
84 }
85
86 // Coefficients for the series expansion
87 Double_t c[7];
88 c[0]= 2.5066282746310005;
89 c[1]= 76.18009172947146;
90 c[2]=-86.50532032941677;
91 c[3]= 24.01409824083091;
92 c[4]= -1.231739572450155;
93 c[5]= 0.1208650973866179e-2;
94 c[6]= -0.5395239384953e-5;
95
96 Double_t x=z;
97 Double_t y=x;
98 Double_t tmp=x+5.5;
99 tmp=(x+0.5)*log(tmp)-tmp;
100 Double_t ser=1.000000000190015;
101 for (Int_t i=1; i<7; i++)
102 {
103 y+=1.;
104 ser+=c[i]/y;
105 }
106 Float_t v=tmp+log(c[0]*ser/x);
107 return v;
108}
109///////////////////////////////////////////////////////////////////////////
110Float_t AliMath::GamSer(Float_t a,Float_t x)
111{
112// Computation of the incomplete gamma function P(a,x)
113// via its series representation.
114//
115// The algorithm is based on the formulas and code as denoted in
116// Numerical Recipes 2nd ed. on p. 210-212 (W.H.Press et al.).
117//
118//--- Nve 14-nov-1998 UU-SAP Utrecht
119
120 Int_t itmax=100; // Maximum number of iterations
121 Float_t eps=3.e-7; // Relative accuracy
122
123 if (a<=0.)
124 {
125 cout << "*GamSer(a,x)* Invalid argument a = " << a << endl;
126 return 0;
127 }
128
129 if (x<=0.)
130 {
131 if (x<0) cout << "*GamSer(a,x)* Invalid argument x = " << x << endl;
132 return 0;
133 }
134
135 Float_t gln=LnGamma(a);
136 Float_t ap=a;
137 Float_t sum=1./a;
138 Float_t del=sum;
139 for (Int_t n=1; n<=itmax; n++)
140 {
141 ap+=1.;
142 del=del*x/ap;
143 sum+=del;
144 if (fabs(del)<fabs(sum*eps)) break;
145 if (n==itmax) cout << "*GamSer(a,x)* a too large or itmax too small" << endl;
146 }
147 Float_t v=sum*exp(-x+a*log(x)-gln);
148 return v;
149}
150///////////////////////////////////////////////////////////////////////////
151Float_t AliMath::GamCf(Float_t a,Float_t x)
152{
153// Computation of the incomplete gamma function P(a,x)
154// via its continued fraction representation.
155//
156// The algorithm is based on the formulas and code as denoted in
157// Numerical Recipes 2nd ed. on p. 210-212 (W.H.Press et al.).
158//
159//--- Nve 14-nov-1998 UU-SAP Utrecht
160
161 Int_t itmax=100; // Maximum number of iterations
162 Float_t eps=3.e-7; // Relative accuracy
163 Float_t fpmin=1.e-30; // Smallest Float_t value allowed here
164
165 if (a<=0.)
166 {
167 cout << "*GamCf(a,x)* Invalid argument a = " << a << endl;
168 return 0;
169 }
170
171 if (x<=0.)
172 {
173 if (x<0) cout << "*GamCf(a,x)* Invalid argument x = " << x << endl;
174 return 0;
175 }
176
177 Float_t gln=LnGamma(a);
178 Float_t b=x+1.-a;
179 Float_t c=1./fpmin;
180 Float_t d=1./b;
181 Float_t h=d;
182 Float_t an,del;
183 for (Int_t i=1; i<=itmax; i++)
184 {
185 an=float(-i)*(float(i)-a);
186 b+=2.;
187 d=an*d+b;
188 if (fabs(d)<fpmin) d=fpmin;
189 c=b+an/c;
190 if (fabs(c)<fpmin) c=fpmin;
191 d=1./d;
192 del=d*c;
193 h=h*del;
194 if (fabs(del-1.)<eps) break;
195 if (i==itmax) cout << "*GamCf(a,x)* a too large or itmax too small" << endl;
196 }
197 Float_t v=exp(-x+a*log(x)-gln)*h;
198 return (1.-v);
199}
200///////////////////////////////////////////////////////////////////////////
201Float_t AliMath::Erf(Float_t x)
202{
203// Computation of the error function erf(x).
204//
205//--- NvE 14-nov-1998 UU-SAP Utrecht
206
207 return (1.-Erfc(x));
208}
209///////////////////////////////////////////////////////////////////////////
210Float_t AliMath::Erfc(Float_t x)
211{
212// Computation of the complementary error function erfc(x).
213//
214// The algorithm is based on a Chebyshev fit as denoted in
215// Numerical Recipes 2nd ed. on p. 214 (W.H.Press et al.).
216//
217// The fractional error is always less than 1.2e-7.
218//
219//--- Nve 14-nov-1998 UU-SAP Utrecht
220
221 // The parameters of the Chebyshev fit
222 const Float_t a1=-1.26551223, a2=1.00002368,
223 a3= 0.37409196, a4=0.09678418,
224 a5=-0.18628806, a6=0.27886807,
225 a7=-1.13520398, a8=1.48851587,
226 a9=-0.82215223, a10=0.17087277;
227
228 Float_t v=1.; // The return value
229
230 Float_t z=fabs(x);
231
232 if (z <= 0.) return v; // erfc(0)=1
233
234 Float_t t=1./(1.+0.5*z);
235
236 v=t*exp((-z*z)
237 +a1+t*(a2+t*(a3+t*(a4+t*(a5+t*(a6+t*(a7+t*(a8+t*(a9+t*a10)))))))));
238
239 if (x < 0.) v=2.-v; // erfc(-x)=2-erfc(x)
240
241 return v;
242}
243///////////////////////////////////////////////////////////////////////////
244Float_t AliMath::Prob(Float_t chi2,Int_t ndf)
245{
246// Computation of the probability for a certain Chi-squared (chi2)
247// and number of degrees of freedom (ndf).
248//
249// Calculations are based on the incomplete gamma function P(a,x),
250// where a=ndf/2 and x=chi2/2.
251//
252// P(a,x) represents the probability that the observed Chi-squared
253// for a correct model should be less than the value chi2.
254//
255// The returned probability corresponds to 1-P(a,x),
256// which denotes the probability that an observed Chi-squared exceeds
257// the value chi2 by chance, even for a correct model.
258//
259//--- NvE 14-nov-1998 UU-SAP Utrecht
260
261 if (ndf <= 0) return 0; // Set CL to zero in case ndf<=0
262
263 if (chi2 <= 0.)
264 {
265 if (chi2 < 0.)
266 {
267 return 0;
268 }
269 else
270 {
271 return 1;
272 }
273 }
274
275// Alternative which is exact
276// This code may be activated in case the gamma function gives problems
277// if (ndf==1)
278// {
279// Float_t v=1.-Erf(sqrt(chi2)/sqrt(2.));
280// return v;
281// }
282
283// Gaussian approximation for large ndf
284// This code may be activated in case the gamma function shows a problem
285// Float_t q=sqrt(2.*chi2)-sqrt(float(2*ndf-1));
286// if (n>30 && q>0.)
287// {
288// Float_t v=0.5*(1.-Erf(q/sqrt(2.)));
289// return v;
290// }
291
292 // Evaluate the incomplete gamma function
293 Float_t a=float(ndf)/2.;
294 Float_t x=chi2/2.;
295 return (1.-Gamma(a,x));
296}
297///////////////////////////////////////////////////////////////////////////