double ranpoiss1(double xm) /* poisson variable conditioned on x>0 */ /** xm should be small here ranpoissx is the driver. Don't call this directly */ { double t, tc, s, y ; int k ; t = exp(-xm) ; tc = 1.0-t ; if (tc==0.0) return 1 ; y = t ; s = tc*DRAND2() ; /* s uniform [0, tc] */ k = 1 ; y *= xm / (double) k ; for (;;) { if (s<y) return (double) k ; s -= y ; ++k ; y *= xm / (double) k ; if (k>=100) { fprintf(stderr,"(ranpoiss1) bug? xm: %12.6f\n", xm) ; return k ; } } }
double samppow(double e, double a, double b) // sample x^e in range (a,b) // uses cdf method since integral is analytic // care taken to prevent underflow { double ztot, rhs, zlog, ee, x ; double y1, y2, u ; ee = e+1.0 ; if (ee<0.0) fatalx("e must be > -1 \n") ; // fixable if integral finite if (b<a) return samppow(e, b, a) ; if (a==b) return a ; u = DRAND2() ; if (u==0.0) u = 0.5 ; // tiny hack y1 = ee*log(b) + log(u) ; if (a==0.0) zlog = y1 ; else { y2 = ee*log(a) + log(1.0-u) ; zlog = addlog(y1, y2) ; } /** ztot = pow(b, ee) - pow(a, ee) ; rhs = ztot*DRAND() + pow(a, ee) ; zlog = log(rhs) ; */ x = exp(zlog/ee) ; return x ; }
double ranexp( void) { /** exponential mean 1 */ double x, t; t = DRAND2(); x = -log(1.0 - t); return x; }
int prob1(double p) // return YES with probability p { double z ; if ((p<0) || (p>1)) fatalx("bad p %12.6f\n", p) ; z = DRAND2() ; if (z<p) return YES ; return NO ; }
double rantruncnorm(double T, int upper) { double u ; if (upper==0) return -rantruncnorm(-T, 1) ; u = DRAND2() ; if (u==0.0) u = 0.5 ; // tiny hack u *= ntail(T) ; if (u==0.0) return MAX(T, 50.0) ; return zprob(u) ; }
double uniform(double lo, double hi) { double x, width ; width = hi - lo ; if (width < 0) return uniform(hi, lo) ; x = DRAND2() * width ; return x + lo ; }
double poidev(double xm) /** NUM REC pp 293 ff (modified) */ { static double sq,alxm,g,oldm=(-1.0); double em,t,y; if (xm < 12.0) { if (xm != oldm) { oldm=xm; g=exp(-xm); } em = -1; t=1.0; do { ++em; t *= DRAND2(); } while (t > g); } else { if (xm != oldm) { oldm=xm; sq=sqrt(2.0*xm); alxm=log(xm); g=xm*alxm-lgamma(xm+1.0); } do { do { y=tan(PI*DRAND2()); em=sq*y+xm; } while (em < 0.0); em=floor(em); t=0.9*(1.0+y*y)*exp(em*alxm-lgamma(em+1.0)-g); } while (DRAND2() > t); } return em; }
static int ranb1 (int n, double p) /** binomial dis. Naive routine */ { int cnt = 0, i ; for (i=0 ; i< n ; i++) { if (DRAND2() <= p) ++ cnt ; } return cnt ; }
void ewens(int *a, int n, double theta) /** implements the Ewens sampler. Categories 1...K */ { int i, k, maxcat=0 ; double t, x ; if (n==0) return ; a[0] = maxcat = 1 ; for (i=1 ; i< n ; i++) { t = theta/ ((double) i + theta) ; x = DRAND2() ; if (x > t) { k = ranmod(i) ; a[i] = a[k] ; } else { ++maxcat ; a[i] = maxcat ; } } }
int randis(double *a, int n) { /* a should be prob dis summing to 1 */ int i ; double t, y ; static int nfirst=0 ; t = DRAND2() ; for (i=0; i<n; i++) { t -= a[i] ; if (t<=0.0) return i ; } if (nfirst==0) { printf("pos t: %15.9f\n",t) ; for (i=0; i<n ; i++) { printf("zzrand %4d %9.3f\n",i, a[i]) ; } } ++nfirst ; fprintf(stderr, "probable bug (randis)\n") ; return n-1 ; }