double rndgamma2 (double s) { double r ,d, f, g, x; static double b, h, ss=0; if (s!=ss) { b = s-1.0; h = sqrt(3.0*s-0.75); ss = s; } for (;;) { r = rndu(); g = r-r*r; f = (r-0.5)*h/sqrt(g); x = b+f; if (x <= 0.0) continue; r = rndu(); d = 64*r*r*g*g*g; if (d*x < x-2.0*f*f || log(d) < 2*(b*log(x/b)-f)) break; } return (x); }
double rndgamma1 (double s) { double r, x=0.0, small=1e-37, w; static double a, p, uf, ss=10.0, d; if (s!=ss) { a = 1.0-s; p = a/(a+s*exp(-a)); uf = p*pow(small/a,s); d = a*log(a); ss = s; } for (;;) { r = rndu(); if (r > p) x = a-log((1.0-r)/(1.0-p)), w=a*log(x)-d; else if (r>uf) x = a*pow(r/p,1/s), w=x; else return (0.0); r = rndu(); if (1.0-r <= w && r > 0.0) if (r*(w+1.0) >= 1.0 || -log(r) <= w) continue; break; } return (x); }
int main(void) { int n=400, noisy=0, i,j; int nr=10, ir, TimeSquare=10, algorithm; /* TimeSquare should be larger for large t */ double t=5, *Q, *pi, *space, s; char timestr[96], *AlgStr[2]={"repeated squaring", "eigensolution"}; if((Q=(double*)malloc(n*n*5*sizeof(double))) ==NULL) error2("oom"); pi=Q+n*n; space=pi+n; for(algorithm=0; algorithm<2; algorithm++) { starttime(); SetSeed(1234567); for (i=0; i<n; i++) pi[i]=rndu(); s=sum(pi,n); for (i=0; i<n; i++) pi[i]/=s; for(ir=0; ir<nr; ir++) { printf("Replicate %d/%d ", ir+1,nr); for (i=0; i<n; i++) for (j=0,Q[i*n+i]=0; j<i; j++) Q[i*n+j]=Q[j*n+i] = square(rndu()); for (i=0; i<n; i++) for (j=0; j<n; j++) Q[i*n+j] *= pi[j]; for(i=0,s=0; i<n; i++) { /* rescaling Q so that average rate is 1 */ Q[i*n+i]=0; Q[i*n+i]=-sum(Q+i*n, n); s-=pi[i]*Q[i*n+i]; } if(noisy) { matout(stdout, pi, 1, n); matout(stdout, Q, n, n); } if(algorithm==0) matexp(Q, 1, n, TimeSquare, space); else PMatQRev(Q, pi, 1, n, space); printf("%s, time: %s\n", AlgStr[algorithm], printtime(timestr)); if(noisy) matout(stdout, Q, n, n); } } return (0); }
double rndgamma (double s) { double r=0.0; if (s <= 0.0) return 0; else if (s < 1.0) r = rndgamma1 (s); else if (s > 1.0) r = rndgamma2 (s); else r =- log(rndu()); return (r); }
int GetTreeI (int itree, int ns, int rooted) { /* get the i_th tree. Trees are ordered according to the algorithm of adding species. returns a random tree if itree==-1, in which case ns can be large */ int i, M[NS-2], nM=ns-3+rooted, Ib[NS-2]; for (i=0; i<nM-1; i++) M[i]=2*i+5; for (i=0,M[nM-1]=1; i<nM-2; i++) M[nM-1-i-2]*=M[nM-1-i-1]; if (itree==-1) for (i=0; i<nM; i++) Ib[i]=(int)((2*i+3)*rndu()); else for (i=0; i<nM; i++) {Ib[i]=itree/M[i]; itree%=M[i]; } /* if (noisy>3) { FOR (i, nM) printf ("%5d ", M[i]); FPN (F0); FOR (i, nM) printf ("%5d ", Ib[i]); FPN (F0); } */ MakeTreeIb (ns, Ib, rooted); return (0); }