source: branches/ali/GDE/TREEPUZZLE/src/gamma.c

Last change on this file was 191, checked in by jobb, 24 years ago

treepuzzle

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.9 KB
Line 
1/*
2 * gamma.c
3 *
4 *
5 * Part of TREE-PUZZLE 5.0 (June 2000)
6 *
7 * (c) 1999-2000 by Heiko A. Schmidt, Korbinian Strimmer,
8 *                  M. Vingron, and Arndt von Haeseler
9 * (c) 1995-1999 by Korbinian Strimmer and Arndt von Haeseler
10 *
11 * All parts of the source except where indicated are distributed under
12 * the GNU public licence.  See http://www.opensource.org for details.
13 */
14
15#include <math.h>
16#include "util.h"
17#include "gamma.h"
18
19/* private prototypes */
20static double IncompleteGamma (double x, double alpha, double ln_gamma_alpha);
21static double PointNormal (double prob);
22static double PointChi2 (double prob, double v);
23
24/* Gamma density function */
25double densityGamma (double x, double shape)
26{
27        return pow (shape, shape) * pow (x, shape-1) /
28                exp (shape*x + LnGamma(shape));
29}
30
31/* Gamma cdf */
32double cdfGamma (double x, double shape)
33{
34        double result;
35       
36        result = IncompleteGamma (shape*x, shape, LnGamma(shape));
37       
38        return result;
39}
40
41/* Gamma inverse cdf */
42double icdfGamma (double y, double shape)
43{
44        double result;
45       
46        result = PointChi2 (y, 2.0*shape)/(2.0*shape);
47       
48        /* to avoid -1.0 */
49        if (result < 0.0)
50        {
51                result = 0.0;
52        }
53       
54        return result;
55}
56
57/* Gamma n-th moment */
58double momentGamma (int n, double shape)
59{
60        int i;
61        double tmp = 1.0;
62       
63        for (i = 1; i < n; i++)
64        {
65                tmp *= (shape + i)/shape;
66        }
67       
68        return tmp;
69}
70
71/* The following code comes from tools.c in Yang's PAML package */
72
73double LnGamma (double alpha)
74{
75/* returns ln(gamma(alpha)) for alpha>0, accurate to 10 decimal places. 
76   Stirling's formula is used for the central polynomial part of the procedure.
77   Pike MC & Hill ID (1966) Algorithm 291: Logarithm of the gamma function.
78   Communications of the Association for Computing Machinery, 9:684
79*/
80   double x=alpha, f=0, z;
81
82   if (x<7) {
83      f=1;  z=x-1;
84      while (++z<7)  f*=z;
85      x=z;   f=-log(f);
86   }
87   z = 1/(x*x);
88   return  f + (x-0.5)*log(x) - x + .918938533204673 
89          + (((-.000595238095238*z+.000793650793651)*z-.002777777777778)*z
90               +.083333333333333)/x; 
91}
92
93static double IncompleteGamma (double x, double alpha, double ln_gamma_alpha)
94{
95/* returns the incomplete gamma ratio I(x,alpha) where x is the upper
96           limit of the integration and alpha is the shape parameter.
97   returns (-1) if in error
98   (1) series expansion     if (alpha>x || x<=1)
99   (2) continued fraction   otherwise
100   RATNEST FORTRAN by
101   Bhattacharjee GP (1970) The incomplete gamma integral.  Applied Statistics,
102   19: 285-287 (AS32)
103*/
104   int i;
105   double p=alpha, g=ln_gamma_alpha;
106   double accurate=1e-8, overflow=1e30;
107   double factor, gin=0, rn=0, a=0,b=0,an=0,dif=0, term=0, pn[6];
108   
109   if (x==0) return (0);
110   if (x<0 || p<=0) return (-1);
111
112   factor=exp(p*log(x)-x-g);   
113   if (x>1 && x>=p) goto l30;
114   /* (1) series expansion */
115   gin=1;  term=1;  rn=p;
116 l20:
117   rn++;
118   term*=x/rn;   gin+=term;
119
120   if (term > accurate) goto l20;
121   gin*=factor/p;
122   goto l50;
123 l30:
124   /* (2) continued fraction */
125   a=1-p;   b=a+x+1;  term=0;
126   pn[0]=1;  pn[1]=x;  pn[2]=x+1;  pn[3]=x*b;
127   gin=pn[2]/pn[3];
128 l32:
129   a++;  b+=2;  term++;   an=a*term;
130   for (i=0; i<2; i++) pn[i+4]=b*pn[i+2]-an*pn[i];
131   if (pn[5] == 0) goto l35;
132   rn=pn[4]/pn[5];   dif=fabs(gin-rn);
133   if (dif>accurate) goto l34;
134   if (dif<=accurate*rn) goto l42;
135 l34:
136   gin=rn;
137 l35:
138   for (i=0; i<4; i++) pn[i]=pn[i+2];
139   if (fabs(pn[4]) < overflow) goto l32;
140   for (i=0; i<4; i++) pn[i]/=overflow;
141   goto l32;
142 l42:
143   gin=1-factor*gin;
144
145 l50:
146   return (gin);
147}
148
149
150/* functions concerning the CDF and percentage points of the gamma and
151   Chi2 distribution
152*/
153static double PointNormal (double prob)
154{
155/* returns z so that Prob{x<z}=prob where x ~ N(0,1) and (1e-12)<prob<1-(1e-12)
156   returns (-9999) if in error
157   Odeh RE & Evans JO (1974) The percentage points of the normal distribution.
158   Applied Statistics 22: 96-97 (AS70)
159
160   Newer methods:
161     Wichura MJ (1988) Algorithm AS 241: the percentage points of the
162       normal distribution.  37: 477-484.
163     Beasley JD & Springer SG  (1977).  Algorithm AS 111: the percentage
164       points of the normal distribution.  26: 118-121.
165
166*/
167   double a0=-.322232431088, a1=-1, a2=-.342242088547, a3=-.0204231210245;
168   double a4=-.453642210148e-4, b0=.0993484626060, b1=.588581570495;
169   double b2=.531103462366, b3=.103537752850, b4=.0038560700634;
170   double y, z=0, p=prob, p1;
171
172   p1 = (p<0.5 ? p : 1-p);
173   if (p1<1e-20) return (-9999);
174
175   y = sqrt (log(1/(p1*p1)));   
176   z = y + ((((y*a4+a3)*y+a2)*y+a1)*y+a0) / ((((y*b4+b3)*y+b2)*y+b1)*y+b0);
177   return (p<0.5 ? -z : z);
178}
179
180
181static double PointChi2 (double prob, double v)
182{
183/* returns z so that Prob{x<z}=prob where x is Chi2 distributed with df=v
184   returns -1 if in error.   0.000002<prob<0.999998
185   RATNEST FORTRAN by
186       Best DJ & Roberts DE (1975) The percentage points of the
187       Chi2 distribution.  Applied Statistics 24: 385-388.  (AS91)
188   Converted into C by Ziheng Yang, Oct. 1993.
189*/
190   double e=.5e-6, aa=.6931471805, p=prob, g;
191   double xx, c, ch, a=0,q=0,p1=0,p2=0,t=0,x=0,b=0,s1,s2,s3,s4,s5,s6;
192
193   if (p<.000002 || p>.999998 || v<=0) return (-1);
194
195   g = LnGamma (v/2);
196   xx=v/2;   c=xx-1;
197   if (v >= -1.24*log(p)) goto l1;
198
199   ch=pow((p*xx*exp(g+xx*aa)), 1/xx);
200   if (ch-e<0) return (ch);
201   goto l4;
202l1:
203   if (v>.32) goto l3;
204   ch=0.4;   a=log(1-p);
205l2:
206   q=ch;  p1=1+ch*(4.67+ch);  p2=ch*(6.73+ch*(6.66+ch));
207   t=-0.5+(4.67+2*ch)/p1 - (6.73+ch*(13.32+3*ch))/p2;
208   ch-=(1-exp(a+g+.5*ch+c*aa)*p2/p1)/t;
209   if (fabs(q/ch-1)-.01 <= 0) goto l4;
210   else                       goto l2;
211 
212l3: 
213   x=PointNormal (p);
214   p1=0.222222/v;   ch=v*pow((x*sqrt(p1)+1-p1), 3.0);
215   if (ch>2.2*v+6)  ch=-2*(log(1-p)-c*log(.5*ch)+g);
216l4:
217
218   do
219   {
220   q=ch;   p1=.5*ch;
221   if ((t=IncompleteGamma (p1, xx, g))<0) {
222      return (-1);
223   }
224   p2=p-t;
225   t=p2*exp(xx*aa+g+p1-c*log(ch));   
226   b=t/ch;  a=0.5*t-b*c;
227
228   s1=(210+a*(140+a*(105+a*(84+a*(70+60*a))))) / 420;
229   s2=(420+a*(735+a*(966+a*(1141+1278*a))))/2520;
230   s3=(210+a*(462+a*(707+932*a)))/2520;
231   s4=(252+a*(672+1182*a)+c*(294+a*(889+1740*a)))/5040;
232   s5=(84+264*a+c*(175+606*a))/2520;
233   s6=(120+c*(346+127*c))/5040;
234   ch+=t*(1+0.5*t*s1-b*c*(s1-b*(s2-b*(s3-b*(s4-b*(s5-b*s6))))));
235   }
236   while (fabs(q/ch-1) > e);
237
238   return (ch);
239}
240
241
242/* Incomplete Gamma function Q(a,x)
243   - this is a cleanroom implementation of NRs gammq(a,x)
244*/
245double IncompleteGammaQ (double a, double x)
246{
247        return 1.0-IncompleteGamma (x, a, LnGamma(a));
248}
249
250
251/* probability that the observed chi-square
252   exceeds chi2 even if model is correct */
253double chi2prob (int deg, double chi2)
254{
255        return IncompleteGammaQ (0.5*deg, 0.5*chi2);
256}
257
258
259
260/* chi square test
261   ef      expected frequencies (sum up to 1 !!)
262   of      observed frequencies (sum up to the number of samples)
263   numcat  number of categories
264   returns critical significance level */
265double chi2test(double *ef, int *of, int numcat, int *chi2fail)
266{       
267        double chi2, criticals, efn;
268        int i, below1, below5, reducedcat;
269        int samples;
270       
271        *chi2fail = FALSE;
272        reducedcat = numcat;
273        below1 = 0;
274        below5 = 0;
275       
276        /* compute number of samples */
277        samples = 0;
278        for (i = 0; i < numcat; i++)
279                samples = samples + of[i];
280       
281        /* compute chi square */
282        chi2 = 0;
283        for (i = 0; i < numcat; i++) {
284                efn = ef[i]*((double) samples);
285                if (efn < 1.0) below1++;
286                if (efn < 5.0) below5++;
287                if (efn == 0.0) {
288                        reducedcat--;
289                        fprintf(stdout, "FPE error: samples=%d, ef[%d]=%f, of[%d]=%d, efn=%f, nc=%d, rc=%d\n",
290                                        samples, i, ef[i], i, of[i], efn, numcat, reducedcat);
291                        fprintf(stdout, "PLEASE REPORT THIS ERROR TO DEVELOPERS !!!\n");
292                        fflush(stdout);
293                } else chi2 = chi2 + ((double) of[i]-efn)*((double) of[i]-efn)/efn;
294        }
295
296        /* compute significance */
297        criticals = chi2prob (numcat-1, chi2);
298       
299        /* no expected frequency category (sum up to # samples) below 1.0 */
300        if (below1 > 0) *chi2fail = TRUE;
301        /* no more than 1/5 of the frequency categories below 5.0 */
302        if (below5 > (int) floor(samples/5.0)) *chi2fail = TRUE;
303
304        return criticals;
305}
306
307
308/* chi square test
309   ef      expected frequencies (sum up to 1 !!)
310   of      observed frequencies (sum up to the number of samples)
311   numcat  number of categories
312   returns critical significance level */
313double altchi2test(double *ef, int *of, int numcat, int *chi2fail)
314{       
315        double chi2, criticals, efn;
316        int i, below1, below5;
317        int samples;
318       
319        *chi2fail = FALSE;
320        below1 = 0;
321        below5 = 0;
322       
323        /* compute number of samples */
324        samples = 0;
325        for (i = 0; i < numcat; i++)
326                samples = samples + of[i];
327       
328        /* compute chi square */
329        chi2 = 0;
330        for (i = 0; i < numcat; i++) {
331                efn = ef[i]*((double) samples);
332                if (efn < 1.0) below1++;
333                if (efn < 5.0) below5++;
334                chi2 = chi2 + ((double) of[i]-efn)*((double) of[i]-efn)/efn;
335        }
336
337        /* compute significance */
338        criticals = chi2prob (numcat-1, chi2);
339       
340        /* no expected frequency category (sum up to # samples) below 1.0 */
341        if (below1 > 0) *chi2fail = TRUE;
342        /* no more than 1/5 of the frequency categories below 5.0 */
343        if (below5 > (int) floor(samples/5.0)) *chi2fail = TRUE;
344
345        return criticals;
346}
Note: See TracBrowser for help on using the repository browser.