bpp-core3  3.0.0
RandomTools.cpp
Go to the documentation of this file.
1 //
2 // File: RandomTools.cpp
3 // Authors:
4 // Julien Dutheil
5 // Last modified: Friday Septembre 24 2004
6 //
7 
8 /*
9  Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
10 
11  This software is a computer program whose purpose is to provide classes
12  for numerical calculus.
13 
14  This software is governed by the CeCILL license under French law and
15  abiding by the rules of distribution of free software. You can use,
16  modify and/ or redistribute the software under the terms of the CeCILL
17  license as circulated by CEA, CNRS and INRIA at the following URL
18  "http://www.cecill.info".
19 
20  As a counterpart to the access to the source code and rights to copy,
21  modify and redistribute granted by the license, users are provided only
22  with a limited warranty and the software's author, the holder of the
23  economic rights, and the successive licensors have only limited
24  liability.
25 
26  In this respect, the user's attention is drawn to the risks associated
27  with loading, using, modifying and/or developing or reproducing the
28  software by the user in light of its specific status of free software,
29  that may mean that it is complicated to manipulate, and that also
30  therefore means that it is reserved for developers and experienced
31  professionals having in-depth computer knowledge. Users are therefore
32  encouraged to load and test the software's suitability as regards their
33  requirements in conditions enabling the security of their systems and/or
34  data to be ensured and, more generally, to use and operate it in the
35  same conditions as regards security.
36 
37  The fact that you are presently reading this means that you have had
38  knowledge of the CeCILL license and that you accept its terms.
39 */
40 
41 #include <iostream>
42 
43 #include "../NumConstants.h"
44 #include "../VectorTools.h"
45 #include "RandomTools.h"
46 #include "Uniform01K.h"
47 
48 using namespace bpp;
49 using namespace std;
50 
52 
53 // Initiate random seed :
54 // RandomTools::RandInt RandomTools::r = time(NULL) ;
55 
56 void RandomTools::setSeed(long seed)
57 {
58  DEFAULT_GENERATOR->setSeed(seed);
59 }
60 
61 // Method to get a double random value (between 0 and specified range)
62 // Note : the number you get is between 0 and entry not including entry !
64 {
65  // double tm = r.drawFloatNumber();
66  double tm = generator.drawNumber();
67  return tm * entry;
68 }
69 
70 // Method to get a boolean random value
71 bool RandomTools::flipCoin(const RandomFactory& generator)
72 {
73  return (RandomTools::giveRandomNumberBetweenZeroAndEntry(1.0, generator) - 0.5) > 0;
74 }
75 
76 double RandomTools::randGaussian(double mean, double variance, const RandomFactory& generator)
77 {
78  return RandomTools::qNorm(generator.drawNumber(), mean, sqrt(variance));
79 }
80 
81 double RandomTools::randGamma(double dblAlpha, const RandomFactory& generator)
82 {
83  assert(dblAlpha > 0.0);
84  if (dblAlpha < 1.0)
85  return RandomTools::DblGammaLessThanOne(dblAlpha, generator);
86  else if (dblAlpha > 1.0)
87  return RandomTools::DblGammaGreaterThanOne(dblAlpha, generator);
88  return -log(RandomTools::giveRandomNumberBetweenZeroAndEntry(1.0, generator));
89 }
90 
91 double RandomTools::randGamma(double alpha, double beta, const RandomFactory& generator)
92 {
93  double x = RandomTools::randGamma(alpha, generator) / beta;
94  return x;
95 }
96 
97 double RandomTools::randExponential(double mean, const RandomFactory& generator)
98 {
99  return -mean* log(RandomTools::giveRandomNumberBetweenZeroAndEntry(1, generator));
100 }
101 
102 std::vector<size_t> RandomTools::randMultinomial(size_t n, const std::vector<double>& probs)
103 {
104  double s = VectorTools::sum(probs);
105  double r;
106  double cumprob;
107  vector<size_t> sample(n);
108  for (unsigned int i = 0; i < n; i++)
109  {
111  cumprob = 0;
112  bool test = true;
113  for (unsigned int j = 0; test& (j < probs.size()); j++)
114  {
115  cumprob += probs[j] / s;
116  if (r <= cumprob)
117  {
118  sample[i] = j;
119  test = false;
120  }
121  }
122  // This test should never be true if probs sum to one:
123  if (test)
124  sample[i] = probs.size();
125  }
126  return sample;
127 }
128 
129 // ------------------------------------------------------------------------------
130 
131 
132 double RandomTools::DblGammaGreaterThanOne(double dblAlpha, const RandomFactory& generator)
133 {
134  // Code adopted from David Heckerman
135  // -----------------------------------------------------------
136  // DblGammaGreaterThanOne(dblAlpha)
137  //
138  // routine to generate a gamma random variable with unit scale and
139  // alpha > 1
140  // reference: Ripley, Stochastic Simulation, p.90
141  // Chang and Feast, Appl.Stat. (28) p.290
142  // -----------------------------------------------------------
143  double rgdbl[6];
144 
145  rgdbl[1] = dblAlpha - 1.0;
146  rgdbl[2] = (dblAlpha - (1.0 / (6.0 * dblAlpha))) / rgdbl[1];
147  rgdbl[3] = 2.0 / rgdbl[1];
148  rgdbl[4] = rgdbl[3] + 2.0;
149  rgdbl[5] = 1.0 / sqrt(dblAlpha);
150 
151  for ( ; ;)
152  {
153  double dblRand1;
154  double dblRand2;
155  do
156  {
157  dblRand1 = RandomTools::giveRandomNumberBetweenZeroAndEntry(1.0, generator);
158  dblRand2 = RandomTools::giveRandomNumberBetweenZeroAndEntry(1.0, generator);
159  if (dblAlpha > 2.5)
160  dblRand1 = dblRand2 + rgdbl[5] * (1.0 - 1.86 * dblRand1);
161  }
162  while (!(0.0 < dblRand1 && dblRand1 < 1.0));
163 
164  double dblTemp = rgdbl[2] * dblRand2 / dblRand1;
165 
166  if (rgdbl[3] * dblRand1 + dblTemp + 1.0 / dblTemp <= rgdbl[4] ||
167  rgdbl[3] * log(dblRand1) + dblTemp - log(dblTemp) < 1.0)
168  {
169  return dblTemp * rgdbl[1];
170  }
171  }
172  assert(false);
173  return 0.0;
174 }
175 
176 double RandomTools::DblGammaLessThanOne(double dblAlpha, const RandomFactory& generator)
177 {
178  // routine to generate a gamma random variable with
179  // unit scale and alpha < 1
180  // reference: Ripley, Stochastic Simulation, p.88
181  double dblTemp;
182  const double dblexp = exp(1.0);
183  for ( ; ;)
184  {
185  double dblRand0 = giveRandomNumberBetweenZeroAndEntry(1.0, generator);
186  double dblRand1 = giveRandomNumberBetweenZeroAndEntry(1.0, generator);
187  if (dblRand0 <= (dblexp / (dblAlpha + dblexp)))
188  {
189  dblTemp = pow(((dblAlpha + dblexp) * dblRand0) /
190  dblexp, 1.0 / dblAlpha);
191  if (dblRand1 <= exp(-1.0 * dblTemp))
192  return dblTemp;
193  }
194  else
195  {
196  dblTemp = -1.0 * log((dblAlpha + dblexp) * (1.0 - dblRand0) / (dblAlpha * dblexp));
197  if (dblRand1 <= pow(dblTemp, dblAlpha - 1.0))
198  return dblTemp;
199  }
200  }
201  assert(false);
202  return 0.0;
203 }
204 
205 /******************************************************************************/
206 
207 // From Yang's PAML package:
208 
209 /******************************************************************************/
210 
211 double RandomTools::qNorm(double prob)
212 {
213  double a0 = -.322232431088, a1 = -1, a2 = -.342242088547, a3 = -.0204231210245;
214  double a4 = -.453642210148e-4, b0 = .0993484626060, b1 = .588581570495;
215  double b2 = .531103462366, b3 = .103537752850, b4 = .0038560700634;
216  double y, z = 0, p = prob, p1;
217 
218  p1 = (p < 0.5 ? p : 1 - p);
219  if (p1 < 1e-20)
220  return -9999;
221 
222  y = sqrt (log(1 / (p1 * p1)));
223  z = y + ((((y * a4 + a3) * y + a2) * y + a1) * y + a0) / ((((y * b4 + b3) * y + b2) * y + b1) * y + b0);
224  return p < 0.5 ? -z : z;
225 }
226 
227 double RandomTools::qNorm(double prob, double mu, double sigma)
228 {
229  return RandomTools::qNorm(prob) * sigma + mu;
230 }
231 
232 double RandomTools::incompleteGamma (double x, double alpha, double ln_gamma_alpha)
233 {
234  size_t i;
235  double p = alpha, g = ln_gamma_alpha;
236  double accurate = 1e-8, overflow = 1e30;
237  double factor, gin = 0, rn = 0, a = 0, b = 0, an = 0, dif = 0, term = 0;
238  vector<double> pn(6);
239 
240  if (x == 0)
241  return 0;
242  if (x < 0 || p <= 0)
243  return -1;
244 
245  factor = exp(p * log(x) - x - g);
246  if (x > 1 && x >= p)
247  goto l30;
248  /* (1) series expansion */
249  gin = 1; term = 1; rn = p;
250 l20:
251  rn++;
252  term *= x / rn; gin += term;
253 
254  if (term > accurate)
255  goto l20;
256  gin *= factor / p;
257  goto l50;
258 l30:
259  /* (2) continued fraction */
260  a = 1 - p; b = a + x + 1; term = 0;
261  pn[0] = 1; pn[1] = x; pn[2] = x + 1; pn[3] = x * b;
262  gin = pn[2] / pn[3];
263 l32:
264  a++; b += 2; term++; an = a * term;
265  for (i = 0; i < 2; i++)
266  {
267  pn[i + 4] = b * pn[i + 2] - an * pn[i];
268  }
269  if (pn[5] == 0)
270  goto l35;
271  rn = pn[4] / pn[5]; dif = fabs(gin - rn);
272  if (dif > accurate)
273  goto l34;
274  if (dif <= accurate * rn)
275  goto l42;
276 l34:
277  gin = rn;
278 l35:
279  for (i = 0; i < 4; i++)
280  {
281  pn[i] = pn[i + 2];
282  }
283  if (fabs(pn[4]) < overflow)
284  goto l32;
285  for (i = 0; i < 4; i++)
286  {
287  pn[i] /= overflow;
288  }
289  goto l32;
290 l42:
291  gin = 1 - factor * gin;
292 
293 l50:
294 
295  return gin;
296 }
297 
298 
299 double RandomTools::qChisq(double prob, double v)
300 {
301  double e = .5e-6, aa = .6931471805, p = prob, g;
302  double xx, c, ch, a = 0, q = 0, p1 = 0, p2 = 0, t = 0, x = 0, b = 0, s1, s2, s3, s4, s5, s6;
303 
304  if (p < .000002 || p > .999998 || v <= 0)
305  return -1;
306 
307  g = lnGamma (v / 2);
308  xx = v / 2; c = xx - 1;
309  if (v >= -1.24 * log(p))
310  goto l1;
311 
312  ch = pow((p * xx * exp(g + xx * aa)), 1 / xx);
313  if (ch - e < 0)
314  return ch;
315  goto l4;
316 l1:
317  if (v > .32)
318  goto l3;
319  ch = 0.4; a = log(1 - p);
320 l2:
321  q = ch; p1 = 1 + ch * (4.67 + ch); p2 = ch * (6.73 + ch * (6.66 + ch));
322  t = -0.5 + (4.67 + 2 * ch) / p1 - (6.73 + ch * (13.32 + 3 * ch)) / p2;
323  ch -= (1 - exp(a + g + .5 * ch + c * aa) * p2 / p1) / t;
324  if (fabs(q / ch - 1) - .01 <= 0)
325  goto l4;
326  else
327  goto l2;
328 
329 l3:
330  x = qNorm (p);
331  p1 = 0.222222 / v; ch = v * pow((x * sqrt(p1) + 1 - p1), 3.0);
332  if (ch > 2.2 * v + 6)
333  ch = -2 * (log(1 - p) - c * log(.5 * ch) + g);
334 l4:
335  q = ch; p1 = .5 * ch;
336  if ((t = incompleteGamma (p1, xx, g)) < 0)
337  {
338  std::cerr << "err IncompleteGamma" << std::endl;
339  return -1;
340  }
341  p2 = p - t;
342  t = p2 * exp(xx * aa + g + p1 - c * log(ch));
343  b = t / ch; a = 0.5 * t - b * c;
344 
345  s1 = (210 + a * (140 + a * (105 + a * (84 + a * (70 + 60 * a))))) / 420;
346  s2 = (420 + a * (735 + a * (966 + a * (1141 + 1278 * a)))) / 2520;
347  s3 = (210 + a * (462 + a * (707 + 932 * a))) / 2520;
348  s4 = (252 + a * (672 + 1182 * a) + c * (294 + a * (889 + 1740 * a))) / 5040;
349  s5 = (84 + 264 * a + c * (175 + 606 * a)) / 2520;
350  s6 = (120 + c * (346 + 127 * c)) / 5040;
351  ch += t * (1 + 0.5 * t * s1 - b * c * (s1 - b * (s2 - b * (s3 - b * (s4 - b * (s5 - b * s6))))));
352  if (fabs(q / ch - 1) > e)
353  goto l4;
354 
355  return ch;
356 }
357 
358 
359 double RandomTools::pNorm(double x, double mu, double sigma)
360 {
361  return RandomTools::pNorm((x - mu) / sigma);
362 }
363 
364 
365 double RandomTools::pNorm(double x)
366 {
367  const static double a[5] = {
368  2.2352520354606839287,
369  161.02823106855587881,
370  1067.6894854603709582,
371  18154.981253343561249,
372  0.065682337918207449113
373  };
374  const static double b[4] = {
375  47.20258190468824187,
376  976.09855173777669322,
377  10260.932208618978205,
378  45507.789335026729956
379  };
380  const static double c[9] = {
381  0.39894151208813466764,
382  8.8831497943883759412,
383  93.506656132177855979,
384  597.27027639480026226,
385  2494.5375852903726711,
386  6848.1904505362823326,
387  11602.651437647350124,
388  9842.7148383839780218,
389  1.0765576773720192317e-8
390  };
391  const static double d[8] = {
392  22.266688044328115691,
393  235.38790178262499861,
394  1519.377599407554805,
395  6485.558298266760755,
396  18615.571640885098091,
397  34900.952721145977266,
398  38912.003286093271411,
399  19685.429676859990727
400  };
401  const static double p[6] = {
402  0.21589853405795699,
403  0.1274011611602473639,
404  0.022235277870649807,
405  0.001421619193227893466,
406  2.9112874951168792e-5,
407  0.02307344176494017303
408  };
409  const static double q[5] = {
410  1.28426009614491121,
411  0.468238212480865118,
412  0.0659881378689285515,
413  0.00378239633202758244,
414  7.29751555083966205e-5
415  };
416 
417  double xden, xnum, temp, del, eps, xsq, y, cum;
418  int i;
419 
420  eps = 1e-20;
421 
422  y = fabs(x);
423  if (y <= 0.67448975) /* qnorm(3/4) = .6744.... -- earlier had 0.66291 */
424  {
425  if (y > eps)
426  {
427  xsq = x * x;
428  xnum = a[4] * xsq;
429  xden = xsq;
430  for (i = 0; i < 3; ++i)
431  {
432  xnum = (xnum + a[i]) * xsq;
433  xden = (xden + b[i]) * xsq;
434  }
435  }
436  else
437  xnum = xden = 0.0;
438 
439  temp = x * (xnum + a[3]) / (xden + b[3]);
440  cum = 0.5 + temp;
441  }
442  else if (y <= sqrt(32))
443  {
444  /* Evaluate pnorm for 0.674.. = qnorm(3/4) < |x| <= sqrt(32) ~= 5.657 */
445 
446  xnum = c[8] * y;
447  xden = y;
448  for (i = 0; i < 7; ++i)
449  {
450  xnum = (xnum + c[i]) * y;
451  xden = (xden + d[i]) * y;
452  }
453  temp = (xnum + c[7]) / (xden + d[7]);
454 
455  xsq = trunc(y * 16) / 16;
456  del = (y - xsq) * (y + xsq);
457  cum = exp(-xsq * xsq * 0.5) * exp(-del * 0.5) * temp;
458 
459  if (x > 0.)
460  cum = 1 - cum;
461  }
462  else if (-37.5193 < x && x < 8.2924)
463  {
464  xsq = 1.0 / (x * x);
465  xnum = p[5] * xsq;
466  xden = xsq;
467  for (i = 0; i < 4; ++i)
468  {
469  xnum = (xnum + p[i]) * xsq;
470  xden = (xden + q[i]) * xsq;
471  }
472  temp = xsq * (xnum + p[4]) / (xden + q[4]);
473  temp = (1 / sqrt(2 * M_PI) - temp) / y;
474 
475  xsq = trunc(x * 16) / 16;
476  del = (x - xsq) * (x + xsq);
477 
478  cum = exp(-xsq * xsq * 0.5) * exp(-del * 0.5) * temp;
479 
480  if (x > 0.)
481  cum = 1. - cum;
482  }
483  else /* no log_p , large x such that probs are 0 or 1 */
484  {
485  if (x > 0)
486  cum = 1.;
487  else
488  cum = 0.;
489  }
490 
491  return cum;
492 }
493 
494 double RandomTools::lnBeta(double alpha, double beta)
495 {
496  return lnGamma(alpha) + lnGamma(beta) - lnGamma(alpha + beta);
497 }
498 
499 double RandomTools::randBeta(double alpha, double beta, const RandomFactory& generator)
500 {
501  return RandomTools::qBeta(generator.drawNumber(), alpha, beta);
502 }
503 
504 
505 double RandomTools::qBeta(double prob, double alpha, double beta)
506 {
507  double lower = NumConstants::VERY_TINY();
508  double upper = 1 - NumConstants::VERY_TINY();
509  double const1 = 2.30753;
510  double const2 = 0.27061;
511  double const3 = 0.99229;
512  double const4 = 0.04481;
513 
514 
515  int swap_tail, i_pb, i_inn;
516  double a, adj, logbeta, g, h, pp, prev, qq, r, s, t, tx, w, y, yprev;
517  double acu;
518  volatile double xinbta;
519 
520  if (alpha <= 0. || beta < 0.)
521  throw ("RandomTools::qBeta with non positive parameters");
522 
523  if (prob < 0. || prob > 1.)
524  throw ("RandomTools::qBeta with bad probability");
525 
526  /* initialize */
527  logbeta = lnBeta(alpha, beta);
528 
529  /* change tail if necessary; afterwards 0 < a <= 1/2 */
530  if (prob <= 0.5)
531  {
532  a = prob; pp = alpha; qq = beta; swap_tail = 0;
533  }
534  else /* change tail, swap alpha <-> beta :*/
535  {
536  a = 1 - prob;
537  pp = beta; qq = alpha; swap_tail = 1;
538  }
539 
540  /* calculate the initial approximation */
541 
542  /* y := {fast approximation of} qnorm(1 - a) :*/
543  r = sqrt(-2 * log(a));
544  y = r - (const1 + const2 * r) / (1. + (const3 + const4 * r) * r);
545  if (pp > 1 && qq > 1)
546  {
547  r = (y * y - 3.) / 6.;
548  s = 1. / (pp + pp - 1.);
549  t = 1. / (qq + qq - 1.);
550  h = 2. / (s + t);
551  w = y * sqrt(h + r) / h - (t - s) * (r + 5. / 6. - 2. / (3. * h));
552  xinbta = pp / (pp + qq * exp(w + w));
553  }
554  else
555  {
556  r = qq + qq;
557  t = 1. / (9. * qq);
558  t = r * pow(1. - t + y * sqrt(t), 3.0);
559  if (t <= 0.)
560  xinbta = 1. - exp((log1p(-a) + log(qq) + logbeta) / qq);
561  else
562  {
563  t = (4. * pp + r - 2.) / t;
564  if (t <= 1.)
565  xinbta = exp((log(a * pp) + logbeta) / pp);
566  else
567  xinbta = 1. - 2. / (t + 1.);
568  }
569  }
570 
571  /* solve for x by a modified newton-raphson method, */
572  /* using the function pbeta_raw */
573 
574  r = 1 - pp;
575  t = 1 - qq;
576  yprev = 0.;
577  adj = 1;
578  /* Sometimes the approximation is negative! */
579  if (xinbta < lower)
580  xinbta = 0.5;
581  else if (xinbta > upper)
582  xinbta = 0.5;
583 
584  /* Desired accuracy should depend on (a,p)
585  * This is from Remark .. on AS 109, adapted.
586  * However, it's not clear if this is "optimal" for IEEE double prec.
587 
588  * acu = fmax2(lower, pow(10., -25. - 5./(pp * pp) - 1./(a * a)));
589 
590  * NEW: 'acu' accuracy NOT for squared adjustment, but simple;
591  * ---- i.e., "new acu" = sqrt(old acu)
592 
593  */
594  double po = pow(10., -13 - 2.5 / (pp * pp) - 0.5 / (a * a));
595  acu = (lower > po) ? lower : po;
596 
597  tx = prev = 0.; /* keep -Wall happy */
598 
599  for (i_pb = 0; i_pb < 1000; i_pb++)
600  {
601  y = incompleteBeta(xinbta, pp, qq);
602 // #ifdef IEEE_754
603 // if(!R_FINITE(y))
604 // #else
605 // if (errno)
606 // #endif
607 // ML_ERR_return_NAN;
608 
609  y = (y - a) *
610  exp(logbeta + r * log(xinbta) + t * log1p(-xinbta));
611  if (y * yprev <= 0.)
612  prev = (fabs(adj) > lower) ? fabs(adj) : lower;
613  g = 1;
614  for (i_inn = 0; i_inn < 1000; i_inn++)
615  {
616  adj = g * y;
617  if (fabs(adj) < prev)
618  {
619  tx = xinbta - adj; /* trial new x */
620  if (tx >= 0. && tx <= 1)
621  {
622  if ((prev <= acu) || (fabs(y) <= acu))
623  return swap_tail ? 1 - xinbta : xinbta;
624  if (tx != 0. && tx != 1)
625  break;
626  }
627  }
628  g /= 3;
629  }
630  if (fabs(tx - xinbta) < 1e-15 * xinbta)
631  return swap_tail ? 1 - xinbta : xinbta;
632 
633  xinbta = tx;
634  yprev = y;
635  }
636  // throw Exception("Bad precision in RandomTools::qBeta");
637 
638  return swap_tail ? 1 - xinbta : xinbta;
639 }
640 
641 double RandomTools::incompleteBeta(double x, double alpha, double beta)
642 {
643  double t;
644  double xc;
645  double w;
646  double y;
647  int flag;
648  double big;
649  double biginv;
650  double maxgam;
651  double minlog;
652  double maxlog;
653 
654  big = 4.503599627370496e15;
655  biginv = 2.22044604925031308085e-16;
656  maxgam = 171.624376956302725;
657  minlog = log(NumConstants::VERY_TINY());
658  maxlog = log(NumConstants::VERY_BIG());
659 
660  if ((alpha <= 0) || (beta <= 0))
661  throw Exception("RandomTools::incompleteBeta not valid with non-positive parameters");
662 
663  if ((x < 0) || (x > 1))
664  throw Exception("RandomTools::incompleteBeta out of bounds limit");
665 
666  if (x == 0)
667  return 0;
668 
669  if (x == 1)
670  return 1;
671 
672  flag = 0;
673  if ((beta * x <= 1.0) && (x <= 0.95))
674  {
675  return incompletebetaps(alpha, beta, x, maxgam);
676  }
677  w = 1.0 - x;
678 
679  if (x > alpha / (alpha + beta))
680  {
681  flag = 1;
682  t = alpha;
683  alpha = beta;
684  beta = t;
685  xc = x;
686  x = w;
687  }
688  else
689  {
690  xc = w;
691  }
692  if (flag == 1 && (beta * x <= 1.0) && (x <= 0.95) )
693  {
694  t = incompletebetaps(alpha, beta, x, maxgam);
695  if (t <= NumConstants::VERY_TINY())
696  return 1.0 - NumConstants::VERY_TINY();
697  else
698  return 1.0 - t;
699  }
700 
701  y = x * (alpha + beta - 2.0) - (alpha - 1.0);
702  if (y < 0.0)
703  {
704  w = incompletebetafe(alpha, beta, x, big, biginv);
705  }
706  else
707  {
708  w = incompletebetafe2(alpha, beta, x, big, biginv) / xc;
709  }
710  y = alpha * log(x);
711  t = beta * log(xc);
712  if ( (alpha + beta < maxgam) && (fabs(y) < maxlog) && (fabs(t) < maxlog) )
713  {
714  t = pow(xc, beta);
715  t = t * pow(x, alpha);
716  t = t / alpha;
717  t = t * w;
718  t = t * exp(lnGamma(alpha + beta) - (lnGamma(alpha) + lnGamma(beta)));
719  if (flag == 1)
720  {
721  if (t < NumConstants::VERY_TINY())
722  return 1.0 - NumConstants::VERY_TINY();
723  else
724  return 1.0 - t;
725  }
726  else
727  return t;
728  }
729  y = y + t + lnGamma(alpha + beta) - lnGamma(alpha) - lnGamma(beta);
730  y = y + log(w / alpha);
731  if (y < minlog)
732  {
733  t = 0.0;
734  }
735  else
736  {
737  t = exp(y);
738  }
739  if (flag == 1)
740  {
741  if (t < NumConstants::VERY_TINY())
742  t = 1.0 - NumConstants::VERY_TINY();
743  else
744  t = 1.0 - t;
745  }
746  return t;
747 }
748 
749 
750 /**********************************************/
751 
753  double b,
754  double x,
755  double big,
756  double biginv)
757 {
758  double result;
759  double xk;
760  double pk;
761  double pkm1;
762  double pkm2;
763  double qk;
764  double qkm1;
765  double qkm2;
766  double k1;
767  double k2;
768  double k3;
769  double k4;
770  double k5;
771  double k6;
772  double k7;
773  double k8;
774  double r;
775  double t;
776  double ans;
777  double thresh;
778  int n;
779 
780  k1 = a;
781  k2 = a + b;
782  k3 = a;
783  k4 = a + 1.0;
784  k5 = 1.0;
785  k6 = b - 1.0;
786  k7 = k4;
787  k8 = a + 2.0;
788  pkm2 = 0.0;
789  qkm2 = 1.0;
790  pkm1 = 1.0;
791  qkm1 = 1.0;
792  ans = 1.0;
793  r = 1.0;
794  n = 0;
795  thresh = 3.0 * NumConstants::VERY_TINY();
796  do
797  {
798  xk = -x * k1 * k2 / (k3 * k4);
799  pk = pkm1 + pkm2 * xk;
800  qk = qkm1 + qkm2 * xk;
801  pkm2 = pkm1;
802  pkm1 = pk;
803  qkm2 = qkm1;
804  qkm1 = qk;
805  xk = x * k5 * k6 / (k7 * k8);
806  pk = pkm1 + pkm2 * xk;
807  qk = qkm1 + qkm2 * xk;
808  pkm2 = pkm1;
809  pkm1 = pk;
810  qkm2 = qkm1;
811  qkm1 = qk;
812  if (qk != 0)
813  {
814  r = pk / qk;
815  }
816  if (r != 0)
817  {
818  t = fabs((ans - r) / r);
819  ans = r;
820  }
821  else
822  {
823  t = 1.0;
824  }
825  if (t < thresh)
826  {
827  break;
828  }
829  k1 = k1 + 1.0;
830  k2 = k2 + 1.0;
831  k3 = k3 + 2.0;
832  k4 = k4 + 2.0;
833  k5 = k5 + 1.0;
834  k6 = k6 - 1.0;
835  k7 = k7 + 2.0;
836  k8 = k8 + 2.0;
837  if (fabs(qk) + fabs(pk) > big)
838  {
839  pkm2 = pkm2 * biginv;
840  pkm1 = pkm1 * biginv;
841  qkm2 = qkm2 * biginv;
842  qkm1 = qkm1 * biginv;
843  }
844  if ((fabs(qk) < biginv) || (fabs(pk) < biginv))
845  {
846  pkm2 = pkm2 * big;
847  pkm1 = pkm1 * big;
848  qkm2 = qkm2 * big;
849  qkm1 = qkm1 * big;
850  }
851  n = n + 1;
852  }
853  while (n != 300);
854  result = ans;
855  return result;
856 }
857 
858 
859 /*************************************************************************
860  Continued fraction expansion #2
861  for incomplete beta integral
862 
863  Cephes Math Library, Release 2.8: June, 2000
864  Copyright 1984, 1995, 2000 by Stephen L. Moshier
865 *************************************************************************/
867  double b,
868  double x,
869  double big,
870  double biginv)
871 {
872  double result;
873  double xk;
874  double pk;
875  double pkm1;
876  double pkm2;
877  double qk;
878  double qkm1;
879  double qkm2;
880  double k1;
881  double k2;
882  double k3;
883  double k4;
884  double k5;
885  double k6;
886  double k7;
887  double k8;
888  double r;
889  double t;
890  double ans;
891  double z;
892  double thresh;
893  int n;
894 
895  k1 = a;
896  k2 = b - 1.0;
897  k3 = a;
898  k4 = a + 1.0;
899  k5 = 1.0;
900  k6 = a + b;
901  k7 = a + 1.0;
902  k8 = a + 2.0;
903  pkm2 = 0.0;
904  qkm2 = 1.0;
905  pkm1 = 1.0;
906  qkm1 = 1.0;
907  z = x / (1.0 - x);
908  ans = 1.0;
909  r = 1.0;
910  n = 0;
911  thresh = 3.0 * NumConstants::VERY_TINY();
912  do
913  {
914  xk = -z * k1 * k2 / (k3 * k4);
915  pk = pkm1 + pkm2 * xk;
916  qk = qkm1 + qkm2 * xk;
917  pkm2 = pkm1;
918  pkm1 = pk;
919  qkm2 = qkm1;
920  qkm1 = qk;
921  xk = z * k5 * k6 / (k7 * k8);
922  pk = pkm1 + pkm2 * xk;
923  qk = qkm1 + qkm2 * xk;
924  pkm2 = pkm1;
925  pkm1 = pk;
926  qkm2 = qkm1;
927  qkm1 = qk;
928  if (qk != 0)
929  {
930  r = pk / qk;
931  }
932  if (r != 0)
933  {
934  t = fabs((ans - r) / r);
935  ans = r;
936  }
937  else
938  {
939  t = 1.0;
940  }
941  if (t < thresh)
942  {
943  break;
944  }
945  k1 = k1 + 1.0;
946  k2 = k2 - 1.0;
947  k3 = k3 + 2.0;
948  k4 = k4 + 2.0;
949  k5 = k5 + 1.0;
950  k6 = k6 + 1.0;
951  k7 = k7 + 2.0;
952  k8 = k8 + 2.0;
953  if (fabs(qk) + fabs(pk) > big)
954  {
955  pkm2 = pkm2 * biginv;
956  pkm1 = pkm1 * biginv;
957  qkm2 = qkm2 * biginv;
958  qkm1 = qkm1 * biginv;
959  }
960  if ((fabs(qk) < biginv) || (fabs(pk) < biginv))
961  {
962  pkm2 = pkm2 * big;
963  pkm1 = pkm1 * big;
964  qkm2 = qkm2 * big;
965  qkm1 = qkm1 * big;
966  }
967  n = n + 1;
968  }
969  while (n != 300);
970  result = ans;
971  return result;
972 }
973 
974 
975 /*************************************************************************
976  Power series for incomplete beta integral.
977  Use when b*x is small and x not too close to 1.
978 
979  Cephes Math Library, Release 2.8: June, 2000
980  Copyright 1984, 1995, 2000 by Stephen L. Moshier
981 *************************************************************************/
982 double RandomTools::incompletebetaps(double a, double b, double x, double maxgam)
983 {
984  double result;
985  double s;
986  double t;
987  double u;
988  double v;
989  double n;
990  double t1;
991  double z;
992  double ai;
993 
994  ai = 1.0 / a;
995  u = (1.0 - b) * x;
996  v = u / (a + 1.0);
997  t1 = v;
998  t = u;
999  n = 2.0;
1000  s = 0.0;
1001  z = NumConstants::VERY_TINY() * ai;
1002  while (fabs(v) > z)
1003  {
1004  u = (n - b) * x / n;
1005  t = t * u;
1006  v = t / (a + n);
1007  s = s + v;
1008  n = n + 1.0;
1009  }
1010  s = s + t1;
1011  s = s + ai;
1012  u = a * log(x);
1013  if ((a + b < maxgam) && (fabs(u) < log(NumConstants::VERY_BIG())))
1014  {
1015  t = exp(lnGamma(a + b) - (lnGamma(a) + lnGamma(b)));
1016  s = s * t * pow(x, a);
1017  }
1018  else
1019  {
1020  t = lnGamma(a + b) - lnGamma(a) - lnGamma(b) + u + log(s);
1021  if (t < log(NumConstants::VERY_TINY()))
1022  {
1023  s = 0.0;
1024  }
1025  else
1026  {
1027  s = exp(t);
1028  }
1029  }
1030  result = s;
1031  return result;
1032 }
1033 
1034 /**************************************************************************/
Exception base class. Overload exception constructor (to control the exceptions mechanism)....
Definition: Exceptions.h:59
static double VERY_TINY()
Definition: NumConstants.h:83
static double VERY_BIG()
Definition: NumConstants.h:84
This is the interface for the Random Number Generators.
Definition: RandomFactory.h:55
virtual double drawNumber() const =0
Return a random number.
static double DblGammaLessThanOne(double dblAlpha, const RandomFactory &generator)
static double pNorm(double z)
Normal cumulative function.
static double incompleteBeta(double x, double alpha, double beta)
Returns the regularized incomplete beta function .
static double randExponential(double mean, const RandomFactory &generator= *DEFAULT_GENERATOR)
Definition: RandomTools.cpp:97
static double giveRandomNumberBetweenZeroAndEntry(double entry, const RandomFactory &generator= *DEFAULT_GENERATOR)
Get a double random value (between 0 and specified range).
Definition: RandomTools.cpp:63
static double lnBeta(double alpha, double beta)
Computes given and .
static double qChisq(double prob, double v)
quantile function.
static void setSeed(long seed)
Set the default generator seed.
Definition: RandomTools.cpp:56
static std::vector< size_t > randMultinomial(size_t n, const std::vector< double > &probs)
Get a random state from a set of probabilities/scores.
static double randGamma(double dblAlpha, const RandomFactory &generator= *DEFAULT_GENERATOR)
Definition: RandomTools.cpp:81
static double qBeta(double prob, double alpha, double beta)
The Beta quantile function.
static double incompletebetafe(double a, double b, double x, double big, double biginv)
functions for the computation of incompleteBeta
static double DblGammaGreaterThanOne(double dblAlpha, const RandomFactory &generator)
static double randBeta(double alpha, double beta, const RandomFactory &generator= *DEFAULT_GENERATOR)
static bool flipCoin(const RandomFactory &generator= *DEFAULT_GENERATOR)
Get a boolean random value.
Definition: RandomTools.cpp:71
static RandomFactory * DEFAULT_GENERATOR
Definition: RandomTools.h:97
static double incompleteGamma(double x, double alpha, double ln_gamma_alpha)
Returns the incomplete gamma ratio I(x,alpha).
static double incompletebetaps(double a, double b, double x, double maxgam)
static double randGaussian(double mean, double variance, const RandomFactory &generator= *DEFAULT_GENERATOR)
Definition: RandomTools.cpp:76
static double qNorm(double prob)
Normal quantile function.
static double incompletebetafe2(double a, double b, double x, double big, double biginv)
A uniform random number generator.
Definition: Uniform01K.h:61
static T sum(const std::vector< T > &v1)
Definition: VectorTools.h:624