bpp-core3  3.0.0
RandomTools.cpp
Go to the documentation of this file.
1 #include <iostream>
2 
3 #include "../NumConstants.h"
4 #include "../VectorTools.h"
5 #include "RandomTools.h"
6 
7 using namespace bpp;
8 using namespace std;
9 
10 std::random_device RandomTools::RANDOM_DEVICE;
12 
13 std::vector<size_t> RandomTools::randMultinomial(size_t n, const std::vector<double>& probs)
14 {
15  double s = VectorTools::sum(probs);
16  double r;
17  double cumprob;
18  vector<size_t> sample(n);
19  for (size_t i = 0; i < n; ++i)
20  {
22  cumprob = 0;
23  bool test = true;
24  for (size_t j = 0; test& (j < probs.size()); ++j)
25  {
26  cumprob += probs[j] / s;
27  if (r <= cumprob)
28  {
29  sample[i] = j;
30  test = false;
31  }
32  }
33  // This test should never be true if probs sum to one:
34  if (test)
35  sample[i] = probs.size();
36  }
37  return sample;
38 }
39 
40 // ------------------------------------------------------------------------------
41 
42 
43 double RandomTools::DblGammaGreaterThanOne(double dblAlpha)
44 {
45  // Code adopted from David Heckerman
46  // -----------------------------------------------------------
47  // DblGammaGreaterThanOne(dblAlpha)
48  //
49  // routine to generate a gamma random variable with unit scale and
50  // alpha > 1
51  // reference: Ripley, Stochastic Simulation, p.90
52  // Chang and Feast, Appl.Stat. (28) p.290
53  // -----------------------------------------------------------
54  double rgdbl[6];
55 
56  rgdbl[1] = dblAlpha - 1.0;
57  rgdbl[2] = (dblAlpha - (1.0 / (6.0 * dblAlpha))) / rgdbl[1];
58  rgdbl[3] = 2.0 / rgdbl[1];
59  rgdbl[4] = rgdbl[3] + 2.0;
60  rgdbl[5] = 1.0 / sqrt(dblAlpha);
61 
62  for ( ; ;)
63  {
64  double dblRand1;
65  double dblRand2;
66  do
67  {
70  if (dblAlpha > 2.5)
71  dblRand1 = dblRand2 + rgdbl[5] * (1.0 - 1.86 * dblRand1);
72  }
73  while (!(0.0 < dblRand1 && dblRand1 < 1.0));
74 
75  double dblTemp = rgdbl[2] * dblRand2 / dblRand1;
76 
77  if (rgdbl[3] * dblRand1 + dblTemp + 1.0 / dblTemp <= rgdbl[4] ||
78  rgdbl[3] * log(dblRand1) + dblTemp - log(dblTemp) < 1.0)
79  {
80  return dblTemp * rgdbl[1];
81  }
82  }
83  assert(false);
84  return 0.0;
85 }
86 
87 double RandomTools::DblGammaLessThanOne(double dblAlpha)
88 {
89  // routine to generate a gamma random variable with
90  // unit scale and alpha < 1
91  // reference: Ripley, Stochastic Simulation, p.88
92  double dblTemp;
93  const double dblexp = exp(1.0);
94  for ( ; ;)
95  {
96  double dblRand0 = giveRandomNumberBetweenZeroAndEntry(1.0);
97  double dblRand1 = giveRandomNumberBetweenZeroAndEntry(1.0);
98  if (dblRand0 <= (dblexp / (dblAlpha + dblexp)))
99  {
100  dblTemp = pow(((dblAlpha + dblexp) * dblRand0) /
101  dblexp, 1.0 / dblAlpha);
102  if (dblRand1 <= exp(-1.0 * dblTemp))
103  return dblTemp;
104  }
105  else
106  {
107  dblTemp = -1.0 * log((dblAlpha + dblexp) * (1.0 - dblRand0) / (dblAlpha * dblexp));
108  if (dblRand1 <= pow(dblTemp, dblAlpha - 1.0))
109  return dblTemp;
110  }
111  }
112  assert(false);
113  return 0.0;
114 }
115 
116 /******************************************************************************/
117 
118 // From Yang's PAML package:
119 
120 /******************************************************************************/
121 
122 double RandomTools::qNorm(double prob)
123 {
124  double a0 = -.322232431088, a1 = -1, a2 = -.342242088547, a3 = -.0204231210245;
125  double a4 = -.453642210148e-4, b0 = .0993484626060, b1 = .588581570495;
126  double b2 = .531103462366, b3 = .103537752850, b4 = .0038560700634;
127  double y, z = 0, p = prob, p1;
128 
129  p1 = (p < 0.5 ? p : 1 - p);
130  if (p1 < 1e-20)
131  return -9999;
132 
133  y = sqrt (log(1 / (p1 * p1)));
134  z = y + ((((y * a4 + a3) * y + a2) * y + a1) * y + a0) / ((((y * b4 + b3) * y + b2) * y + b1) * y + b0);
135  return p < 0.5 ? -z : z;
136 }
137 
138 double RandomTools::qNorm(double prob, double mu, double sigma)
139 {
140  return RandomTools::qNorm(prob) * sigma + mu;
141 }
142 
143 double RandomTools::incompleteGamma (double x, double alpha, double ln_gamma_alpha)
144 {
145  size_t i;
146  double p = alpha, g = ln_gamma_alpha;
147  double accurate = 1e-8, overflow = 1e30;
148  double factor, gin = 0, rn = 0, a = 0, b = 0, an = 0, dif = 0, term = 0;
149  vector<double> pn(6);
150 
151  if (x == 0)
152  return 0;
153  if (x < 0 || p <= 0)
154  return -1;
155 
156  factor = exp(p * log(x) - x - g);
157  if (x > 1 && x >= p)
158  goto l30;
159  /* (1) series expansion */
160  gin = 1; term = 1; rn = p;
161 l20:
162  rn++;
163  term *= x / rn; gin += term;
164 
165  if (term > accurate)
166  goto l20;
167  gin *= factor / p;
168  goto l50;
169 l30:
170  /* (2) continued fraction */
171  a = 1 - p; b = a + x + 1; term = 0;
172  pn[0] = 1; pn[1] = x; pn[2] = x + 1; pn[3] = x * b;
173  gin = pn[2] / pn[3];
174 l32:
175  a++; b += 2; term++; an = a * term;
176  for (i = 0; i < 2; i++)
177  {
178  pn[i + 4] = b * pn[i + 2] - an * pn[i];
179  }
180  if (pn[5] == 0)
181  goto l35;
182  rn = pn[4] / pn[5]; dif = fabs(gin - rn);
183  if (dif > accurate)
184  goto l34;
185  if (dif <= accurate * rn)
186  goto l42;
187 l34:
188  gin = rn;
189 l35:
190  for (i = 0; i < 4; i++)
191  {
192  pn[i] = pn[i + 2];
193  }
194  if (fabs(pn[4]) < overflow)
195  goto l32;
196  for (i = 0; i < 4; i++)
197  {
198  pn[i] /= overflow;
199  }
200  goto l32;
201 l42:
202  gin = 1 - factor * gin;
203 
204 l50:
205 
206  return gin;
207 }
208 
209 
210 double RandomTools::qChisq(double prob, double v)
211 {
212  double e = .5e-6, aa = .6931471805, p = prob, g;
213  double xx, c, ch, a = 0, q = 0, p1 = 0, p2 = 0, t = 0, x = 0, b = 0, s1, s2, s3, s4, s5, s6;
214 
215  if (p < .000002 || p > .999998 || v <= 0)
216  return -1;
217 
218  g = lnGamma (v / 2);
219  xx = v / 2; c = xx - 1;
220  if (v >= -1.24 * log(p))
221  goto l1;
222 
223  ch = pow((p * xx * exp(g + xx * aa)), 1 / xx);
224  if (ch - e < 0)
225  return ch;
226  goto l4;
227 l1:
228  if (v > .32)
229  goto l3;
230  ch = 0.4; a = log(1 - p);
231 l2:
232  q = ch; p1 = 1 + ch * (4.67 + ch); p2 = ch * (6.73 + ch * (6.66 + ch));
233  t = -0.5 + (4.67 + 2 * ch) / p1 - (6.73 + ch * (13.32 + 3 * ch)) / p2;
234  ch -= (1 - exp(a + g + .5 * ch + c * aa) * p2 / p1) / t;
235  if (fabs(q / ch - 1) - .01 <= 0)
236  goto l4;
237  else
238  goto l2;
239 
240 l3:
241  x = qNorm (p);
242  p1 = 0.222222 / v; ch = v * pow((x * sqrt(p1) + 1 - p1), 3.0);
243  if (ch > 2.2 * v + 6)
244  ch = -2 * (log(1 - p) - c * log(.5 * ch) + g);
245 l4:
246  q = ch; p1 = .5 * ch;
247  if ((t = incompleteGamma (p1, xx, g)) < 0)
248  {
249  std::cerr << "err IncompleteGamma" << std::endl;
250  return -1;
251  }
252  p2 = p - t;
253  t = p2 * exp(xx * aa + g + p1 - c * log(ch));
254  b = t / ch; a = 0.5 * t - b * c;
255 
256  s1 = (210 + a * (140 + a * (105 + a * (84 + a * (70 + 60 * a))))) / 420;
257  s2 = (420 + a * (735 + a * (966 + a * (1141 + 1278 * a)))) / 2520;
258  s3 = (210 + a * (462 + a * (707 + 932 * a))) / 2520;
259  s4 = (252 + a * (672 + 1182 * a) + c * (294 + a * (889 + 1740 * a))) / 5040;
260  s5 = (84 + 264 * a + c * (175 + 606 * a)) / 2520;
261  s6 = (120 + c * (346 + 127 * c)) / 5040;
262  ch += t * (1 + 0.5 * t * s1 - b * c * (s1 - b * (s2 - b * (s3 - b * (s4 - b * (s5 - b * s6))))));
263  if (fabs(q / ch - 1) > e)
264  goto l4;
265 
266  return ch;
267 }
268 
269 
270 double RandomTools::pNorm(double x, double mu, double sigma)
271 {
272  return RandomTools::pNorm((x - mu) / sigma);
273 }
274 
275 
276 double RandomTools::pNorm(double x)
277 {
278  const static double a[5] = {
279  2.2352520354606839287,
280  161.02823106855587881,
281  1067.6894854603709582,
282  18154.981253343561249,
283  0.065682337918207449113
284  };
285  const static double b[4] = {
286  47.20258190468824187,
287  976.09855173777669322,
288  10260.932208618978205,
289  45507.789335026729956
290  };
291  const static double c[9] = {
292  0.39894151208813466764,
293  8.8831497943883759412,
294  93.506656132177855979,
295  597.27027639480026226,
296  2494.5375852903726711,
297  6848.1904505362823326,
298  11602.651437647350124,
299  9842.7148383839780218,
300  1.0765576773720192317e-8
301  };
302  const static double d[8] = {
303  22.266688044328115691,
304  235.38790178262499861,
305  1519.377599407554805,
306  6485.558298266760755,
307  18615.571640885098091,
308  34900.952721145977266,
309  38912.003286093271411,
310  19685.429676859990727
311  };
312  const static double p[6] = {
313  0.21589853405795699,
314  0.1274011611602473639,
315  0.022235277870649807,
316  0.001421619193227893466,
317  2.9112874951168792e-5,
318  0.02307344176494017303
319  };
320  const static double q[5] = {
321  1.28426009614491121,
322  0.468238212480865118,
323  0.0659881378689285515,
324  0.00378239633202758244,
325  7.29751555083966205e-5
326  };
327 
328  double xden, xnum, temp, del, eps, xsq, y, cum;
329  int i;
330 
331  eps = 1e-20;
332 
333  y = fabs(x);
334  if (y <= 0.67448975) /* qnorm(3/4) = .6744.... -- earlier had 0.66291 */
335  {
336  if (y > eps)
337  {
338  xsq = x * x;
339  xnum = a[4] * xsq;
340  xden = xsq;
341  for (i = 0; i < 3; ++i)
342  {
343  xnum = (xnum + a[i]) * xsq;
344  xden = (xden + b[i]) * xsq;
345  }
346  }
347  else
348  xnum = xden = 0.0;
349 
350  temp = x * (xnum + a[3]) / (xden + b[3]);
351  cum = 0.5 + temp;
352  }
353  else if (y <= sqrt(32))
354  {
355  /* Evaluate pnorm for 0.674.. = qnorm(3/4) < |x| <= sqrt(32) ~= 5.657 */
356 
357  xnum = c[8] * y;
358  xden = y;
359  for (i = 0; i < 7; ++i)
360  {
361  xnum = (xnum + c[i]) * y;
362  xden = (xden + d[i]) * y;
363  }
364  temp = (xnum + c[7]) / (xden + d[7]);
365 
366  xsq = trunc(y * 16) / 16;
367  del = (y - xsq) * (y + xsq);
368  cum = exp(-xsq * xsq * 0.5) * exp(-del * 0.5) * temp;
369 
370  if (x > 0.)
371  cum = 1 - cum;
372  }
373  else if (-37.5193 < x && x < 8.2924)
374  {
375  xsq = 1.0 / (x * x);
376  xnum = p[5] * xsq;
377  xden = xsq;
378  for (i = 0; i < 4; ++i)
379  {
380  xnum = (xnum + p[i]) * xsq;
381  xden = (xden + q[i]) * xsq;
382  }
383  temp = xsq * (xnum + p[4]) / (xden + q[4]);
384  temp = (1 / sqrt(2 * M_PI) - temp) / y;
385 
386  xsq = trunc(x * 16) / 16;
387  del = (x - xsq) * (x + xsq);
388 
389  cum = exp(-xsq * xsq * 0.5) * exp(-del * 0.5) * temp;
390 
391  if (x > 0.)
392  cum = 1. - cum;
393  }
394  else /* no log_p , large x such that probs are 0 or 1 */
395  {
396  if (x > 0)
397  cum = 1.;
398  else
399  cum = 0.;
400  }
401 
402  return cum;
403 }
404 
405 double RandomTools::lnBeta(double alpha, double beta)
406 {
407  return lnGamma(alpha) + lnGamma(beta) - lnGamma(alpha + beta);
408 }
409 
410 double RandomTools::randBeta(double alpha, double beta)
411 {
412  return RandomTools::qBeta(giveRandomNumberBetweenZeroAndEntry(1.0), alpha, beta);
413 }
414 
415 
416 double RandomTools::qBeta(double prob, double alpha, double beta)
417 {
418  double p = alpha;
419  double q = beta;
420  /* This calculates the Quantile of the beta distribution
421 
422  Cran, G. W., K. J. Martin and G. E. Thomas (1977).
423  Remark AS R19 and Algorithm AS 109, Applied Statistics, 26(1), 111-114.
424  Remark AS R83 (v.39, 309-310) and correction (v.40(1) p.236).
425 
426  My own implementation of the algorithm did not bracket the variable well.
427  This version is Adpated from the pbeta and qbeta routines from
428  "R : A Computer Language for Statistical Data Analysis". It fails for
429  extreme values of p and q as well, although it seems better than my
430  previous version.
431  Ziheng Yang, May 2001
432  */
433  double fpu = 3e-308, acu_min = 1e-300, lower = fpu, upper = 1 - 2.22e-16;
434  /* acu_min>= fpu: Minimal value for accuracy 'acu' which will depend on (a,p); */
435  int swap_tail, i_pb, i_inn, niterations = 2000;
436  double a, adj, g, h, pp, prev = 0, qq, r, s, t, tx = 0, w, y, yprev;
437  double acu, xinbta;
438 
439  if (prob < 0 || prob > 1)
440  throw Exception("RandomTools::qBeta. Prob muwt be between 0 and 1.");
441  if (p < 0 || q < 0)
442  throw Exception("RandomTools::qBeta. Alpha and beta should be positive numbers.");
443 
444  /* define accuracy and initialize */
445  xinbta = prob;
446 
447  if (prob == 0 || prob == 1)
448  return prob;
449 
450  double lnbeta = lnBeta(p, q);
451 
452  /* change tail if necessary; afterwards 0 < a <= 1/2 */
453  if (prob <= 0.5)
454  {
455  a = prob; pp = p; qq = q; swap_tail = 0;
456  }
457  else
458  {
459  a = 1. - prob; pp = q; qq = p; swap_tail = 1;
460  }
461 
462  /* calculate the initial approximation */
463  r = sqrt(-log(a * a));
464  y = r - (2.30753 + 0.27061 * r) / (1. + (0.99229 + 0.04481 * r) * r);
465 
466  if (pp > 1. && qq > 1.)
467  {
468  r = (y * y - 3.) / 6.;
469  s = 1. / (pp * 2. - 1.);
470  t = 1. / (qq * 2. - 1.);
471  h = 2. / (s + t);
472  w = y * sqrt(h + r) / h - (t - s) * (r + 5. / 6. - 2. / (3. * h));
473  xinbta = pp / (pp + qq * exp(w + w));
474  }
475  else
476  {
477  r = qq * 2.;
478  t = 1. / (9. * qq);
479  t = r * pow(1. - t + y * sqrt(t), 3.);
480  if (t <= 0.)
481  xinbta = 1. - exp((log((1. - a) * qq) + lnbeta) / qq);
482  else
483  {
484  t = (4. * pp + r - 2.) / t;
485  if (t <= 1.)
486  xinbta = exp((log(a * pp) + lnbeta) / pp);
487  else
488  xinbta = 1. - 2. / (t + 1.);
489  }
490  }
491 
492  /* solve for x by a modified newton-raphson method, using CDFBeta */
493  r = 1. - pp;
494  t = 1. - qq;
495  yprev = 0.;
496  adj = 1.;
497 
498 
499  /* Changes made by Ziheng to fix a bug in qbeta()
500  qbeta(0.25, 0.143891, 0.05) = 3e-308 wrong (correct value is 0.457227)
501  */
502  if (xinbta <= lower || xinbta >= upper)
503  xinbta = (a + .5) / 2;
504 
505  /* Desired accuracy should depend on (a,p)
506  * This is from Remark .. on AS 109, adapted.
507  * However, it's not clear if this is "optimal" for IEEE double prec.
508  * acu = fmax2(acu_min, pow(10., -25. - 5./(pp * pp) - 1./(a * a)));
509  * NEW: 'acu' accuracy NOT for squared adjustment, but simple;
510  * ---- i.e., "new acu" = sqrt(old acu)
511  */
512  acu = pow(10., -13. - 2.5 / (pp * pp) - 0.5 / (a * a));
513  acu = max(acu, acu_min);
514 
515  for (i_pb = 0; i_pb < niterations; i_pb++)
516  {
517  y = pBeta(xinbta, pp, qq);
518  y = (y - a) *
519  exp(lnbeta + r * log(xinbta) + t * log(1. - xinbta));
520  if (y * yprev <= 0)
521  prev = max(fabs(adj), fpu);
522  for (i_inn = 0, g = 1; i_inn < niterations; i_inn++)
523  {
524  adj = g * y;
525  if (fabs(adj) < prev)
526  {
527  tx = xinbta - adj; /* trial new x */
528  if (tx >= 0. && tx <= 1.)
529  {
530  if (prev <= acu || fabs(y) <= acu)
531  goto L_converged;
532  if (tx != 0. && tx != 1.)
533  break;
534  }
535  }
536  g /= 3.;
537  }
538  if (fabs(tx - xinbta) < fpu)
539  goto L_converged;
540  xinbta = tx;
541  yprev = y;
542  }
543 
544 L_converged:
545  return swap_tail ? 1. - xinbta : xinbta;
546 }
547 
548 
549 double RandomTools::incompleteBeta(double x, double alpha, double beta)
550 {
551  double t;
552  double xc;
553  double w;
554  double y;
555  int flag;
556  double big;
557  double biginv;
558  double maxgam;
559  double minlog;
560  double maxlog;
561 
562  big = 4.503599627370496e15;
563  biginv = 2.22044604925031308085e-16;
564  maxgam = 171.624376956302725;
565  minlog = log(NumConstants::VERY_TINY());
566  maxlog = log(NumConstants::VERY_BIG());
567 
568  if ((alpha <= 0) || (beta <= 0))
569  throw Exception("RandomTools::incompleteBeta not valid with non-positive parameters");
570 
571  if ((x < 0) || (x > 1))
572  throw Exception("RandomTools::incompleteBeta out of bounds limit");
573 
574  if (x == 0)
575  return 0;
576 
577  if (x == 1)
578  return 1;
579 
580  flag = 0;
581  if ((beta * x <= 1.0) && (x <= 0.95))
582  {
583  return incompletebetaps(alpha, beta, x, maxgam);
584  }
585  w = 1.0 - x;
586 
587  if (x > alpha / (alpha + beta))
588  {
589  flag = 1;
590  t = alpha;
591  alpha = beta;
592  beta = t;
593  xc = x;
594  x = w;
595  }
596  else
597  {
598  xc = w;
599  }
600  if (flag == 1 && (beta * x <= 1.0) && (x <= 0.95) )
601  {
602  t = incompletebetaps(alpha, beta, x, maxgam);
603  if (t <= NumConstants::VERY_TINY())
604  return 1.0 - NumConstants::VERY_TINY();
605  else
606  return 1.0 - t;
607  }
608 
609  y = x * (alpha + beta - 2.0) - (alpha - 1.0);
610  if (y < 0.0)
611  {
612  w = incompletebetafe(alpha, beta, x, big, biginv);
613  }
614  else
615  {
616  w = incompletebetafe2(alpha, beta, x, big, biginv) / xc;
617  }
618  y = alpha * log(x);
619  t = beta * log(xc);
620  if ( (alpha + beta < maxgam) && (fabs(y) < maxlog) && (fabs(t) < maxlog) )
621  {
622  t = pow(xc, beta);
623  t = t * pow(x, alpha);
624  t = t / alpha;
625  t = t * w;
626  t = t * exp(lnGamma(alpha + beta) - (lnGamma(alpha) + lnGamma(beta)));
627  if (flag == 1)
628  {
629  if (t < NumConstants::VERY_TINY())
630  return 1.0 - NumConstants::VERY_TINY();
631  else
632  return 1.0 - t;
633  }
634  else
635  return t;
636  }
637  y = y + t + lnGamma(alpha + beta) - lnGamma(alpha) - lnGamma(beta);
638  y = y + log(w / alpha);
639  if (y < minlog)
640  {
641  t = 0.0;
642  }
643  else
644  {
645  t = exp(y);
646  }
647  if (flag == 1)
648  {
649  if (t < NumConstants::VERY_TINY())
650  t = 1.0 - NumConstants::VERY_TINY();
651  else
652  t = 1.0 - t;
653  }
654  return t;
655 }
656 
657 
658 /**********************************************/
659 
661  double b,
662  double x,
663  double big,
664  double biginv)
665 {
666  double result;
667  double xk;
668  double pk;
669  double pkm1;
670  double pkm2;
671  double qk;
672  double qkm1;
673  double qkm2;
674  double k1;
675  double k2;
676  double k3;
677  double k4;
678  double k5;
679  double k6;
680  double k7;
681  double k8;
682  double r;
683  double t;
684  double ans;
685  double thresh;
686  int n;
687 
688  k1 = a;
689  k2 = a + b;
690  k3 = a;
691  k4 = a + 1.0;
692  k5 = 1.0;
693  k6 = b - 1.0;
694  k7 = k4;
695  k8 = a + 2.0;
696  pkm2 = 0.0;
697  qkm2 = 1.0;
698  pkm1 = 1.0;
699  qkm1 = 1.0;
700  ans = 1.0;
701  r = 1.0;
702  n = 0;
703  thresh = 3.0 * NumConstants::VERY_TINY();
704  do
705  {
706  xk = -x * k1 * k2 / (k3 * k4);
707  pk = pkm1 + pkm2 * xk;
708  qk = qkm1 + qkm2 * xk;
709  pkm2 = pkm1;
710  pkm1 = pk;
711  qkm2 = qkm1;
712  qkm1 = qk;
713  xk = x * k5 * k6 / (k7 * k8);
714  pk = pkm1 + pkm2 * xk;
715  qk = qkm1 + qkm2 * xk;
716  pkm2 = pkm1;
717  pkm1 = pk;
718  qkm2 = qkm1;
719  qkm1 = qk;
720  if (qk != 0)
721  {
722  r = pk / qk;
723  }
724  if (r != 0)
725  {
726  t = fabs((ans - r) / r);
727  ans = r;
728  }
729  else
730  {
731  t = 1.0;
732  }
733  if (t < thresh)
734  {
735  break;
736  }
737  k1 = k1 + 1.0;
738  k2 = k2 + 1.0;
739  k3 = k3 + 2.0;
740  k4 = k4 + 2.0;
741  k5 = k5 + 1.0;
742  k6 = k6 - 1.0;
743  k7 = k7 + 2.0;
744  k8 = k8 + 2.0;
745  if (fabs(qk) + fabs(pk) > big)
746  {
747  pkm2 = pkm2 * biginv;
748  pkm1 = pkm1 * biginv;
749  qkm2 = qkm2 * biginv;
750  qkm1 = qkm1 * biginv;
751  }
752  if ((fabs(qk) < biginv) || (fabs(pk) < biginv))
753  {
754  pkm2 = pkm2 * big;
755  pkm1 = pkm1 * big;
756  qkm2 = qkm2 * big;
757  qkm1 = qkm1 * big;
758  }
759  n = n + 1;
760  }
761  while (n != 300);
762  result = ans;
763  return result;
764 }
765 
766 // Copyright 1984, 1995, 2000 by Stephen L. Moshier
767 // SPDX-FileCopyrightText: The Bio++ Development Group
768 //
769 // SPDX-License-Identifier: CECILL-2.1
770 
772  double b,
773  double x,
774  double big,
775  double biginv)
776 {
777  double result;
778  double xk;
779  double pk;
780  double pkm1;
781  double pkm2;
782  double qk;
783  double qkm1;
784  double qkm2;
785  double k1;
786  double k2;
787  double k3;
788  double k4;
789  double k5;
790  double k6;
791  double k7;
792  double k8;
793  double r;
794  double t;
795  double ans;
796  double z;
797  double thresh;
798  int n;
799 
800  k1 = a;
801  k2 = b - 1.0;
802  k3 = a;
803  k4 = a + 1.0;
804  k5 = 1.0;
805  k6 = a + b;
806  k7 = a + 1.0;
807  k8 = a + 2.0;
808  pkm2 = 0.0;
809  qkm2 = 1.0;
810  pkm1 = 1.0;
811  qkm1 = 1.0;
812  z = x / (1.0 - x);
813  ans = 1.0;
814  r = 1.0;
815  n = 0;
816  thresh = 3.0 * NumConstants::VERY_TINY();
817  do
818  {
819  xk = -z * k1 * k2 / (k3 * k4);
820  pk = pkm1 + pkm2 * xk;
821  qk = qkm1 + qkm2 * xk;
822  pkm2 = pkm1;
823  pkm1 = pk;
824  qkm2 = qkm1;
825  qkm1 = qk;
826  xk = z * k5 * k6 / (k7 * k8);
827  pk = pkm1 + pkm2 * xk;
828  qk = qkm1 + qkm2 * xk;
829  pkm2 = pkm1;
830  pkm1 = pk;
831  qkm2 = qkm1;
832  qkm1 = qk;
833  if (qk != 0)
834  {
835  r = pk / qk;
836  }
837  if (r != 0)
838  {
839  t = fabs((ans - r) / r);
840  ans = r;
841  }
842  else
843  {
844  t = 1.0;
845  }
846  if (t < thresh)
847  {
848  break;
849  }
850  k1 = k1 + 1.0;
851  k2 = k2 - 1.0;
852  k3 = k3 + 2.0;
853  k4 = k4 + 2.0;
854  k5 = k5 + 1.0;
855  k6 = k6 + 1.0;
856  k7 = k7 + 2.0;
857  k8 = k8 + 2.0;
858  if (fabs(qk) + fabs(pk) > big)
859  {
860  pkm2 = pkm2 * biginv;
861  pkm1 = pkm1 * biginv;
862  qkm2 = qkm2 * biginv;
863  qkm1 = qkm1 * biginv;
864  }
865  if ((fabs(qk) < biginv) || (fabs(pk) < biginv))
866  {
867  pkm2 = pkm2 * big;
868  pkm1 = pkm1 * big;
869  qkm2 = qkm2 * big;
870  qkm1 = qkm1 * big;
871  }
872  n = n + 1;
873  }
874  while (n != 300);
875  result = ans;
876  return result;
877 }
878 
879 
880 /*************************************************************************
881  Power series for incomplete beta integral.
882  Use when b*x is small and x not too close to 1.
883 
884  Cephes Math Library, Release 2.8: June, 2000
885  Copyright 1984, 1995, 2000 by Stephen L. Moshier
886 *************************************************************************/
887 double RandomTools::incompletebetaps(double a, double b, double x, double maxgam)
888 {
889  double result;
890  double s;
891  double t;
892  double u;
893  double v;
894  double n;
895  double t1;
896  double z;
897  double ai;
898 
899  ai = 1.0 / a;
900  u = (1.0 - b) * x;
901  v = u / (a + 1.0);
902  t1 = v;
903  t = u;
904  n = 2.0;
905  s = 0.0;
906  z = NumConstants::VERY_TINY() * ai;
907  while (fabs(v) > z)
908  {
909  u = (n - b) * x / n;
910  t = t * u;
911  v = t / (a + n);
912  s = s + v;
913  n = n + 1.0;
914  }
915  s = s + t1;
916  s = s + ai;
917  u = a * log(x);
918  if ((a + b < maxgam) && (fabs(u) < log(NumConstants::VERY_BIG())))
919  {
920  t = exp(lnGamma(a + b) - (lnGamma(a) + lnGamma(b)));
921  s = s * t * pow(x, a);
922  }
923  else
924  {
925  t = lnGamma(a + b) - lnGamma(a) - lnGamma(b) + u + log(s);
926  if (t < log(NumConstants::VERY_TINY()))
927  {
928  s = 0.0;
929  }
930  else
931  {
932  s = exp(t);
933  }
934  }
935  result = s;
936  return result;
937 }
938 
939 /**************************************************************************/
static double pNorm(double z)
Normal cumulative function.
static double incompletebetafe2(double a, double b, double x, double big, double biginv)
static double randBeta(double alpha, double beta)
static T sum(const std::vector< T > &v1)
Definition: VectorTools.h:587
STL namespace.
static double VERY_TINY()
Definition: NumConstants.h:47
static std::random_device RANDOM_DEVICE
Definition: RandomTools.h:60
static double DblGammaGreaterThanOne(double dblAlpha)
Definition: RandomTools.cpp:43
static double qBeta(double prob, double alpha, double beta)
The Beta quantile function.
static double incompleteGamma(double x, double alpha, double ln_gamma_alpha)
Returns the incomplete gamma ratio I(x,alpha).
static double qNorm(double prob)
Normal quantile function.
static double giveRandomNumberBetweenZeroAndEntry(double entry)
Get a double random value (between 0 and specified range).
Definition: RandomTools.h:78
static double VERY_BIG()
Definition: NumConstants.h:48
static double incompletebetafe(double a, double b, double x, double big, double biginv)
functions for the computation of incompleteBeta
Exception base class. Overload exception constructor (to control the exceptions mechanism). Destructor is already virtual (from std::exception)
Definition: Exceptions.h:20
static std::mt19937 DEFAULT_GENERATOR
Definition: RandomTools.h:61
static double incompletebetaps(double a, double b, double x, double maxgam)
static std::vector< size_t > randMultinomial(size_t n, const std::vector< double > &probs)
Get a random state from a set of probabilities/scores.
Definition: RandomTools.cpp:13
static double DblGammaLessThanOne(double dblAlpha)
Definition: RandomTools.cpp:87
static double qChisq(double prob, double v)
quantile function.
static double incompleteBeta(double x, double alpha, double beta)
Returns the regularized incomplete beta function .
static double lnBeta(double alpha, double beta)
Computes given and .