📄 tools.c
字号:
char *p=str;
if(direction) while(*p) { *p=(char)toupper(*p); p++; }
else while(*p) { *p=(char)tolower(*p); p++; }
}
FILE *gfopen(char *filename, char *mode)
{
FILE *fp=(FILE*)fopen(filename, mode);
if(fp==NULL) {
printf("\nerror when opening file %s\n", filename);
exit(-1);
}
return(fp);
}
int appendfile(FILE*fout, char*filename)
{
FILE *fin=gfopen(filename,"r");
int ch;
while((ch=fgetc(fin))!=EOF) fputc(ch,fout);
fclose(fin);
return(0);
}
void error2 (char * message)
{ printf("\nError: %s.\n", message); exit(-1); }
int zero (double x[], int n)
{ int i; FOR (i,n) x[i]=0; return (0);}
double sum (double x[], int n)
{ int i; double t=0; for(i=0; i<n; i++) t += x[i]; return(t); }
int fillxc (double x[], double c, int n)
{ int i; for(i=0; i<n; i++) x[i]=c; return (0); }
int xtoy (double x[], double y[], int n)
{ int i; for (i=0; i<n; y[i]=x[i],i++) ; return(0); }
int abyx (double a, double x[], int n)
{ int i; for (i=0; i<n; x[i]*=a,i++) ; return(0); }
int axtoy(double a, double x[], double y[], int n)
{ int i; for (i=0; i<n; y[i] = a*x[i],i++) ; return(0);}
int axbytoz(double a, double x[], double b, double y[], double z[], int n)
{ int i; FOR (i,n) z[i] = a*x[i]+b*y[i]; return (0); }
int identity (double x[], int n)
{ int i,j; FOR (i,n) { FOR(j,n) x[i*n+j]=0; x[i*n+i]=1; } return (0); }
double distance (double x[], double y[], int n)
{ int i; double t=0;
for (i=0; i<n; i++) t += square(x[i]-y[i]);
return(sqrt(t));
}
double innerp (double x[], double y[], int n)
{ int i; double t=0; FOR (i,n) t += x[i]*y[i]; return(t); }
double norm (double x[], int n)
{ int i; double t=0; FOR (i,n) t+=x[i]*x[i]; return sqrt(t); }
int sort1 (double x[], int n, int rank[], int descending, int space[])
{
/* inefficient bubble sort */
int i,j, it=0, *mark=space;
double t=0;
FOR (i,n) mark[i]=1;
FOR (i,n) {
for (j=0; j<n; j++) if (mark[j]) { t=x[j]; it=j++; break; }
if (descending) {
for ( ; j<n; j++)
if (mark[j] && x[j]>t) { t=x[j]; it=j; }
}
else {
for ( ; j<n; j++)
if (mark[j] && x[j]<t) { t=x[j]; it=j; }
}
mark[it]=0; rank[i]=it;
}
return (0);
}
int f_and_x(double x[], double f[], int n, int fromf, int LastItem)
{
/* This transforms between x and f. x and f can be identical.
If (fromf), f->x
else x->f.
The iterative variable x[] and frequency f[0,1,n-2] are related as:
freq[k] = exp(x[k])/(1+SUM(exp(x[k]))), k=0,1,...,n-2,
x[] and freq[] may be the same vector.
The last element (f[n-1] or x[n-1]=1) is updated only if(LastItem).
*/
int i;
double tot;
if (fromf) { /* f => x */
if((tot=1-sum(f,n-1))<1e-80) error2("f[n-1]==1, not dealt with.");
tot=1/tot;
FOR(i,n-1) x[i]=log(f[i]*tot);
if(LastItem) x[n-1]=0;
}
else { /* x => f */
for(i=0,tot=1; i<n-1; i++) tot+=(f[i]=exp(x[i]));
FOR(i,n-1) f[i]/=tot;
if(LastItem) f[n-1]=1/tot;
}
return(0);
}
#if 0
double rndu (void)
{
/* 32-bit integer assumed */
w_rndu *= 127773;
return ldexp((double)w_rndu, -32);
}
#endif
static unsigned int z_rndu=137;
static unsigned int w_rndu=123456757;
void SetSeed (unsigned int seed)
{
z_rndu=170*(seed%178)+137;
w_rndu = seed*127773;
}
#ifdef FAST_RANDOM_NUMBER
double rndu (void)
{
/* From Ripley (1987, page 46). 32-bit integer assumed */
w_rndu = w_rndu*69069+1;
return ldexp((double)w_rndu, -32);
}
#else
double rndu (void)
{
/* U(0,1): AS 183: Appl. Stat. 31:188-190
Wichmann BA & Hill ID. 1982. An efficient and portable
pseudo-random number generator. Appl. Stat. 31:188-190
x, y, z are any numbers in the range 1-30000. Integer operation up
to 30323 required.
*/
static unsigned int x_rndu=11, y_rndu=23;
double r;
x_rndu = 171*(x_rndu%177) - 2*(x_rndu/177);
y_rndu = 172*(y_rndu%176) - 35*(y_rndu/176);
z_rndu = 170*(z_rndu%178) - 63*(z_rndu/178);
/*
if (x_rndu<0) x_rndu+=30269;
if (y_rndu<0) y_rndu+=30307;
if (z_rndu<0) z_rndu+=30323;
*/
r = x_rndu/30269.0 + y_rndu/30307.0 + z_rndu/30323.0;
return (r-(int)r);
}
#endif
double sample_uniform(double x, double range[2], double finetune)
{
double w[2], xnew;
w[0] = x - (range[1]-range[0])*finetune/2;
w[1] = x + (range[1]-range[0])*finetune/2;
xnew = rnduab(w[0],w[1]);
xnew = reflect(xnew, range[0], range[1]);
return(xnew);
}
double reflect(double x, double a, double b)
{
/* This returns a variable in the range (a,b) by reflecting x back into the range
*/
int rounds=0;
double x0=x;
if(a>=b) {
printf("improper range %f (%f, %f)\n", x0,a,b);
printf("");
}
for ( ; ; rounds) {
if(x>=a && x<=b) return x;
if(x<a) x = a + a - x;
else if(x>b) x = b - (x - b);
if(noisy>2 && ++rounds==2) {
printf("reflecting more than once %f (%f, %f)\n", x0,a,b);
printf("");
}
}
}
void randorder(int order[], int n, int space[])
{
/* This orders 0,1,2,...,n-1 at random
space[n]
*/
int i,k, *item=space;
FOR(i,n) item[i]=i;
FOR(i,n) {
k=(int)((n-i)*rndu());
order[i]=item[i+k]; item[i+k]=item[i];
}
}
double rndnorm (void)
{
/* standard normal variate, using the -Muller method (1958), improved by
Marsaglia and Bray (1964). The method generates a pair of random
variates, and only one used.
See N. L. Johnson et al. (1994), Continuous univariate distributions,
vol 1. p.153.
*/
double u1,u2, sumsquare=0;
for (; ;) {
u1=2*rndu()-1;
u2=2*rndu()-1;
sumsquare=u1*u1+u2*u2;
if (sumsquare>=0 && sumsquare<=1) break;
}
return (u1*sqrt(-2*log(sumsquare)/sumsquare));
}
int rndpoisson (double m)
{
/* m is the rate parameter of the poisson
Numerical Recipes in C, 2nd ed. pp. 293-295
*/
static double sq, alm, g, oldm=-1;
double em, t, y;
/* search from the origin
if (m<5) {
if (m!=oldm) { oldm=m; g=exp(-m); }
y=rndu(); sq=alm=g;
for (em=0; ; ) {
if (y<sq) break;
sq+= (alm*=m/ ++em);
}
}
*/
if (m<12) {
if (m!=oldm) { oldm=m; g=exp(-m); }
em=-1; t=1;
for (; ;) {
em++; t*=rndu();
if (t<=g) break;
}
}
else {
if (m!=oldm) {
oldm=m; sq=sqrt(2*m); alm=log(m);
g=m*alm-LnGamma(m+1);
}
do {
do {
y=tan(3.141592654*rndu());
em=sq*y+m;
} while (em<0);
em=floor(em);
t=0.9*(1+y*y)*exp(em*alm-LnGamma(em+1)-g);
} while (rndu()>t);
}
return ((int) em);
}
double rndgamma1 (double s);
double rndgamma2 (double s);
double rndgamma (double s)
{
/* random standard gamma (Mean=Var=s, with shape par=s, scale par=1)
r^(s-1)*exp(-r)
J. Dagpunar (1988) Principles of random variate generation,
Clarendon Press, Oxford
calling rndgamma1() if s<1 or
rndgamma2() if s>1 or
exponential if s=1
*/
double r=0;
if (s<=0) puts ("jgl gamma..");
else if (s<1) r=rndgamma1 (s);
else if (s>1) r=rndgamma2 (s);
else r=-log(rndu());
return (r);
}
double rndgamma1 (double s)
{
/* random standard gamma for s<1
switching method
*/
double r, x=0,small=1e-37,w;
static double a,p,uf,ss=10,d;
if (s!=ss) {
a=1-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-r)/(1-p)), w=a*log(x)-d;
else if (r>uf) x=a*pow(r/p,1/s), w=x;
else return (0);
r=rndu ();
if (1-r<=w && r>0)
if (r*(w+1)>=1 || -log(r)<=w) continue;
break;
}
return (x);
}
double rndgamma2 (double s)
{
/* random standard gamma for s>1
Best's (1978) t distribution method
*/
double r,d,f,g,x;
static double b,h,ss=0;
if (s!=ss) {
b=s-1;
h=sqrt(3*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) continue;
r=rndu();
d=64*r*r*g*g*g;
if (d*x < x-2*f*f || log(d) < 2*(b*log(x/b)-f)) break;
}
return (x);
}
int rndNegBinomial (double shape, double mean)
{
/* mean=mean, var=mean^2/shape+m
*/
return (rndpoisson(rndgamma(shape)/shape*mean));
}
int SampleCat (double P[], int ncat, double space[])
{
/* sample from ncat categories, based on probability P[]
*/
int i;
double *p=space, r;
FOR (i,ncat) p[i]=P[i];
for (i=1; i<ncat; i++) p[i]+=p[i-1];
if (fabs(p[ncat-1]-1) > 1e-5) puts ("Sum P != 1.."), exit (-1);
r=rndu();
FOR (i, ncat) if (r<p[i]) break;
return (i);
}
int MultiNomial (int n, int ncat, double prob[], int nobs[], double space[])
{
/* sample n times from a mutinomial distribution M(ncat, prob[])
prob[] is considered cumulative prob if (space==NULL)
ncrude is the number or crude categories, and lcrude marks the
starting category for each crude category. These are used
to speed up the process when ncat is large.
*/
int i, j, crude=(ncat>20), ncrude, lcrude[200];
double r, *pcdf=(space==NULL?prob:space), small=1e-6;
ncrude=max2(5,ncat/20); ncrude=min2(200,ncrude);
FOR(i,ncat) nobs[i]=0;
if (space) {
xtoy(prob, pcdf, ncat);
for(i=1; i<ncat; i++) pcdf[i]+=pcdf[i-1];
}
if (fabs(pcdf[ncat-1]-1) > small) error2("sum P!=1 in MultiNomial");
if (crude) {
for(j=1,lcrude[0]=i=0; j<ncrude; j++) {
while (pcdf[i]<(double)j/ncrude) i++;
lcrude[j]=i-1;
}
}
FOR(i,n) {
r=rndu();
j=0;
if (crude) {
for (; j<ncrude; j++) if (r<(j+1.)/ncrude) break;
j=lcrude[j];
}
for (; j<ncat-1; j++) if (r<pcdf[j]) break;
nobs[j] ++;
}
return (0);
}
/* functions concerning the CDF and percentage points of the gamma and
Chi2 distribution
*/
double PointNormal (double prob)
{
/* returns z so that Prob{x<z}=prob where x ~ N(0,1) and (1e-12)<prob<1-(1e-12)
returns (-9999) if in error
Odeh RE & Evans JO (1974) The percentage points of the normal distribution.
Applied Statistics 22: 96-97 (AS70)
Newer methods:
Wichura MJ (1988) Algorithm AS 241: the percentage points of the
normal distribution. 37: 477-484.
Beasley JD & Springer SG (1977). Algorithm AS 111: the percentage
points of the normal distribution. 26: 118-121.
*/
double a0=-.322232431088, a1=-1, a2=-.342242088547, a3=-.0204231210245;
double a4=-.453642210148e-4, b0=.0993484626060, b1=.588581570495;
double b2=.531103462366, b3=.103537752850, b4=.0038560700634;
double y, z=0, p=prob, p1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -