comparison PsiCLASS-1.0.2/stats.cpp @ 0:903fc43d6227 draft default tip

Uploaded
author lsong10
date Fri, 26 Mar 2021 16:52:45 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:903fc43d6227
1 #include "stats.hpp"
2
3 /** The digamma function in long double precision.
4 * @param x the real value of the argument
5 * @return the value of the digamma (psi) function at that point
6 * @author Richard J. Mathar
7 * @since 2005-11-24
8 */
9 long double digammal(long double x)
10 {
11 /* force into the interval 1..3 */
12 if( x < 0.0L )
13 return digammal(1.0L-x)+M_PIl/tanl(M_PIl*(1.0L-x)) ; /* reflection formula */
14 else if( x < 1.0L )
15 return digammal(1.0L+x)-1.0L/x ;
16 else if ( x == 1.0L)
17 return -M_GAMMAl ;
18 else if ( x == 2.0L)
19 return 1.0L-M_GAMMAl ;
20 else if ( x == 3.0L)
21 return 1.5L-M_GAMMAl ;
22 else if ( x > 3.0L)
23 /* duplication formula */
24 return 0.5L*(digammal(x/2.0L)+digammal((x+1.0L)/2.0L))+M_LN2l ;
25 else
26 {
27 /* Just for your information, the following lines contain
28 * the Maple source code to re-generate the table that is
29 * eventually becoming the Kncoe[] array below
30 * interface(prettyprint=0) :
31 * Digits := 63 :
32 * r := 0 :
33 *
34 * for l from 1 to 60 do
35 * d := binomial(-1/2,l) :
36 * r := r+d*(-1)^l*(Zeta(2*l+1) -1) ;
37 * evalf(r) ;
38 * print(%,evalf(1+Psi(1)-r)) ;
39 *o d :
40 *
41 * for N from 1 to 28 do
42 * r := 0 :
43 * n := N-1 :
44 *
45 * for l from iquo(n+3,2) to 70 do
46 * d := 0 :
47 * for s from 0 to n+1 do
48 * d := d+(-1)^s*binomial(n+1,s)*binomial((s-1)/2,l) :
49 * od :
50 * if 2*l-n > 1 then
51 * r := r+d*(-1)^l*(Zeta(2*l-n) -1) :
52 * fi :
53 * od :
54 * print(evalf((-1)^n*2*r)) ;
55 *od :
56 *quit :
57 */
58 static long double Kncoe[] = { .30459198558715155634315638246624251L,
59 .72037977439182833573548891941219706L, -.12454959243861367729528855995001087L,
60 .27769457331927827002810119567456810e-1L, -.67762371439822456447373550186163070e-2L,
61 .17238755142247705209823876688592170e-2L, -.44817699064252933515310345718960928e-3L,
62 .11793660000155572716272710617753373e-3L, -.31253894280980134452125172274246963e-4L,
63 .83173997012173283398932708991137488e-5L, -.22191427643780045431149221890172210e-5L,
64 .59302266729329346291029599913617915e-6L, -.15863051191470655433559920279603632e-6L,
65 .42459203983193603241777510648681429e-7L, -.11369129616951114238848106591780146e-7L,
66 .304502217295931698401459168423403510e-8L, -.81568455080753152802915013641723686e-9L,
67 .21852324749975455125936715817306383e-9L, -.58546491441689515680751900276454407e-10L,
68 .15686348450871204869813586459513648e-10L, -.42029496273143231373796179302482033e-11L,
69 .11261435719264907097227520956710754e-11L, -.30174353636860279765375177200637590e-12L,
70 .80850955256389526647406571868193768e-13L, -.21663779809421233144009565199997351e-13L,
71 .58047634271339391495076374966835526e-14L, -.15553767189204733561108869588173845e-14L,
72 .41676108598040807753707828039353330e-15L, -.11167065064221317094734023242188463e-15L } ;
73
74 register long double Tn_1 = 1.0L ; /* T_{n-1}(x), started at n=1 */
75 register long double Tn = x-2.0L ; /* T_{n}(x) , started at n=1 */
76 register long double resul = Kncoe[0] + Kncoe[1]*Tn ;
77
78 x -= 2.0L ;
79 int n ;
80
81 for( n = 2 ; n < int( sizeof(Kncoe)/sizeof(long double) ) ; n++)
82 {
83 const long double Tn1 = 2.0L * x * Tn - Tn_1 ; /* Chebyshev recursion, Eq. 22.7.4 Abramowitz-Stegun */
84 resul += Kncoe[n]*Tn1 ;
85 Tn_1 = Tn ;
86 Tn = Tn1 ;
87 }
88 return resul ;
89 }
90 }
91
92
93
94 double trigamma ( double x, int *ifault )
95
96 //****************************************************************************
97 // purpose:
98 //
99 // trigamma calculates trigamma(x) = d**2 log(gamma(x)) / dx**2
100 //
101 // licensing:
102 //
103 // this code is distributed under the gnu lgpl license.
104 //
105 // modified:
106 //
107 // 19 january 2008
108 //
109 // author:
110 //
111 // original fortran77 version by be schneider.
112 // c++ version by john burkardt.
113 //
114 // reference:
115 //
116 // be schneider,
117 // algorithm as 121:
118 // trigamma function,
119 // applied statistics,
120 // volume 27, number 1, pages 97-99, 1978.
121 //
122 // parameters:
123 //
124 // input, double x, the argument of the trigamma function.
125 // 0 < x.
126 //
127 // output, int *ifault, error flag.
128 // 0, no error.
129 // 1, x <= 0.
130 //
131 // output, double trigamma, the value of the trigamma function at x.
132 //
133 {
134 double a = 0.0001;
135 double b = 5.0;
136 double b2 = 0.1666666667;
137 double b4 = -0.03333333333;
138 double b6 = 0.02380952381;
139 double b8 = -0.03333333333;
140 double value;
141 double y;
142 double z;
143 //
144 // check the input.
145 //
146 if ( x <= 0.0 )
147 {
148 *ifault = 1;
149 value = 0.0;
150 return value;
151 }
152
153 *ifault = 0;
154 z = x;
155 //
156 // use small value approximation if x <= a.
157 //
158 if ( x <= a )
159 {
160 value = 1.0 / x / x;
161 return value;
162 }
163 //
164 // increase argument to ( x + i ) >= b.
165 //
166 value = 0.0;
167
168 while ( z < b )
169 {
170 value = value + 1.0 / z / z;
171 z = z + 1.0;
172 }
173 //
174 // apply asymptotic formula if argument is b or greater.
175 //
176 y = 1.0 / z / z;
177
178 value = value + 0.5 *
179 y + ( 1.0 + y * ( b2+ y * ( b4 + y * ( b6+ y * b8 )))) / z;
180
181 return value;
182 }
183
184
185 double LogGammaDensity( double x, double k, double theta )
186 {
187 return -k * log( theta ) + ( k - 1 ) * log( x ) - x / theta - lgamma( k ) ;
188 }
189
190 double MixtureGammaAssignment( double x, double pi, double* k, double *theta )
191 {
192 if ( pi == 1 )
193 return 1 ;
194 else if ( pi == 0 )
195 return 0 ;
196
197 double lf0 = LogGammaDensity( x, k[0], theta[0] ) ;
198 double lf1 = LogGammaDensity( x, k[1], theta[1] ) ;
199 return (double)1.0 / ( 1.0 + exp( lf1 + log( 1 - pi ) - lf0 - log( pi ) ) ) ;
200 }
201
202 //****************************************************************************80
203
204 double alnorm ( double x, bool upper )
205
206 //****************************************************************************80
207 //
208 // Purpose:
209 //
210 // ALNORM computes the cumulative density of the standard normal distribution.
211 //
212 // Licensing:
213 //
214 // This code is distributed under the GNU LGPL license.
215 //
216 // Modified:
217 //
218 // 17 January 2008
219 //
220 // Author:
221 //
222 // Original FORTRAN77 version by David Hill.
223 // C++ version by John Burkardt.
224 //
225 // Reference:
226 //
227 // David Hill,
228 // Algorithm AS 66:
229 // The Normal Integral,
230 // Applied Statistics,
231 // Volume 22, Number 3, 1973, pages 424-427.
232 //
233 // Parameters:
234 //
235 // Input, double X, is one endpoint of the semi-infinite interval
236 // over which the integration takes place.
237 //
238 // Input, bool UPPER, determines whether the upper or lower
239 // interval is to be integrated:
240 // .TRUE. => integrate from X to + Infinity;
241 // .FALSE. => integrate from - Infinity to X.
242 //
243 // Output, double ALNORM, the integral of the standard normal
244 // distribution over the desired interval.
245 //
246 {
247 double a1 = 5.75885480458;
248 double a2 = 2.62433121679;
249 double a3 = 5.92885724438;
250 double b1 = -29.8213557807;
251 double b2 = 48.6959930692;
252 double c1 = -0.000000038052;
253 double c2 = 0.000398064794;
254 double c3 = -0.151679116635;
255 double c4 = 4.8385912808;
256 double c5 = 0.742380924027;
257 double c6 = 3.99019417011;
258 double con = 1.28;
259 double d1 = 1.00000615302;
260 double d2 = 1.98615381364;
261 double d3 = 5.29330324926;
262 double d4 = -15.1508972451;
263 double d5 = 30.789933034;
264 double ltone = 7.0;
265 double p = 0.398942280444;
266 double q = 0.39990348504;
267 double r = 0.398942280385;
268 bool up;
269 double utzero = 18.66;
270 double value;
271 double y;
272 double z;
273
274 up = upper;
275 z = x;
276
277 if ( z < 0.0 )
278 {
279 up = !up;
280 z = - z;
281 }
282
283 if ( ltone < z && ( ( !up ) || utzero < z ) )
284 {
285 if ( up )
286 {
287 value = 0.0;
288 }
289 else
290 {
291 value = 1.0;
292 }
293 return value;
294 }
295
296 y = 0.5 * z * z;
297
298 if ( z <= con )
299 {
300 value = 0.5 - z * ( p - q * y
301 / ( y + a1 + b1
302 / ( y + a2 + b2
303 / ( y + a3 ))));
304 }
305 else
306 {
307 value = r * exp ( - y )
308 / ( z + c1 + d1
309 / ( z + c2 + d2
310 / ( z + c3 + d3
311 / ( z + c4 + d4
312 / ( z + c5 + d5
313 / ( z + c6 ))))));
314 }
315
316 if ( !up )
317 {
318 value = 1.0 - value;
319 }
320
321 return value;
322 }
323
324 //****************************************************************************80
325
326 double gammad ( double x, double p, int *ifault )
327
328 //****************************************************************************80
329 //
330 // Purpose:
331 //
332 // GAMMAD computes the Incomplete Gamma Integral
333 //
334 // Licensing:
335 //
336 // This code is distributed under the GNU LGPL license.
337 //
338 // Modified:
339 //
340 // 20 January 2008
341 //
342 // Author:
343 //
344 // Original FORTRAN77 version by B Shea.
345 // C++ version by John Burkardt.
346 //
347 // Reference:
348 //
349 // B Shea,
350 // Algorithm AS 239:
351 // Chi-squared and Incomplete Gamma Integral,
352 // Applied Statistics,
353 // Volume 37, Number 3, 1988, pages 466-473.
354 //
355 // Parameters:
356 //
357 // Input, double X, P, the parameters of the incomplete
358 // gamma ratio. 0 <= X, and 0 < P.
359 //
360 // Output, int IFAULT, error flag.
361 // 0, no error.
362 // 1, X < 0 or P <= 0.
363 //
364 // Output, double GAMMAD, the value of the incomplete
365 // Gamma integral.
366 //
367 {
368 double a;
369 double an;
370 double arg;
371 double b;
372 double c;
373 double elimit = - 88.0;
374 double oflo = 1.0E+37;
375 double plimit = 1000.0;
376 double pn1;
377 double pn2;
378 double pn3;
379 double pn4;
380 double pn5;
381 double pn6;
382 double rn;
383 double tol = 1.0E-14;
384 bool upper;
385 double value;
386 double xbig = 1.0E+08;
387
388 value = 0.0;
389 //
390 // Check the input.
391 //
392 if ( x < 0.0 )
393 {
394 *ifault = 1;
395 return value;
396 }
397
398 if ( p <= 0.0 )
399 {
400 *ifault = 1;
401 return value;
402 }
403
404 *ifault = 0;
405
406 if ( x == 0.0 )
407 {
408 value = 0.0;
409 return value;
410 }
411 //
412 // If P is large, use a normal approximation.
413 //
414 if ( plimit < p )
415 {
416 pn1 = 3.0 * sqrt ( p ) * ( pow ( x / p, 1.0 / 3.0 )
417 + 1.0 / ( 9.0 * p ) - 1.0 );
418
419 upper = false;
420 value = alnorm ( pn1, upper );
421 return value;
422 }
423 //
424 // If X is large set value = 1.
425 //
426 if ( xbig < x )
427 {
428 value = 1.0;
429 return value;
430 }
431 //
432 // Use Pearson's series expansion.
433 // (Note that P is not large enough to force overflow in ALOGAM).
434 // No need to test IFAULT on exit since P > 0.
435 //
436 if ( x <= 1.0 || x < p )
437 {
438 arg = p * log ( x ) - x - lgamma ( p + 1.0 );
439 c = 1.0;
440 value = 1.0;
441 a = p;
442
443 for ( ; ; )
444 {
445 a = a + 1.0;
446 c = c * x / a;
447 value = value + c;
448
449 if ( c <= tol )
450 {
451 break;
452 }
453 }
454
455 arg = arg + log ( value );
456
457 if ( elimit <= arg )
458 {
459 value = exp ( arg );
460 }
461 else
462 {
463 value = 0.0;
464 }
465 }
466 //
467 // Use a continued fraction expansion.
468 //
469 else
470 {
471 arg = p * log ( x ) - x - lgamma ( p );
472 a = 1.0 - p;
473 b = a + x + 1.0;
474 c = 0.0;
475 pn1 = 1.0;
476 pn2 = x;
477 pn3 = x + 1.0;
478 pn4 = x * b;
479 value = pn3 / pn4;
480
481 for ( ; ; )
482 {
483 a = a + 1.0;
484 b = b + 2.0;
485 c = c + 1.0;
486 an = a * c;
487 pn5 = b * pn3 - an * pn1;
488 pn6 = b * pn4 - an * pn2;
489
490 if ( pn6 != 0.0 )
491 {
492 rn = pn5 / pn6;
493
494 if ( fabs ( value - rn ) <= r8_min ( tol, tol * rn ) )
495 {
496 break;
497 }
498 value = rn;
499 }
500
501 pn1 = pn3;
502 pn2 = pn4;
503 pn3 = pn5;
504 pn4 = pn6;
505 //
506 // Re-scale terms in continued fraction if terms are large.
507 //
508 if ( oflo <= fabs ( pn5 ) )
509 {
510 pn1 = pn1 / oflo;
511 pn2 = pn2 / oflo;
512 pn3 = pn3 / oflo;
513 pn4 = pn4 / oflo;
514 }
515 }
516
517 arg = arg + log ( value );
518
519 if ( elimit <= arg )
520 {
521 value = 1.0 - exp ( arg );
522 }
523 else
524 {
525 value = 1.0;
526 }
527 }
528
529 return value;
530 }
531
532 double r8_min ( double x, double y )
533
534 //****************************************************************************80
535 //
536 // Purpose:
537 //
538 // R8_MIN returns the minimum of two R8's.
539 //
540 // Licensing:
541 //
542 // This code is distributed under the GNU LGPL license.
543 //
544 // Modified:
545 //
546 // 31 August 2004
547 //
548 // Author:
549 //
550 // John Burkardt
551 //
552 // Parameters:
553 //
554 // Input, double X, Y, the quantities to compare.
555 //
556 // Output, double R8_MIN, the minimum of X and Y.
557 //
558 {
559 double value;
560
561 if ( y < x )
562 {
563 value = y;
564 }
565 else
566 {
567 value = x;
568 }
569 return value;
570 }
571
572 // This function is implemented by Li Song.
573 // If Y follows (theta, k)=(1/alpha, k)-gamma distribution, then P_Y(Y<t)=gammad(alpha*t, k).
574 // Furthurmore, chi-square with d.f. k is gamma distribution (2, k/2)
575 double chicdf( double x, double df )
576 {
577 int ifault ;
578 return gammad( x / 2.0, df / 2.0, &ifault ) ;
579 }
580