sre_random.c

来自「这是一个基于HMM 模型的生物多序列比对算法的linux实现版本。hmmer」· C语言 代码 · 共 316 行

C
316
字号
/* sre_random.c *  * Portable random number generator, and sampling routines. * * SRE, Tue Oct  1 15:24:11 2002 [St. Louis] * CVS $Id: sre_random.c,v 1.2 2003/04/14 16:00:16 eddy Exp $ */#include "squidconf.h"#include <stdio.h>#include <stdlib.h>#include <math.h>#include "sre_random.h"static int sre_randseed = 42;	/* default seed for sre_random()   *//* Function: sre_random() *  * Purpose:  Return a uniform deviate x, 0.0 <= x < 1.0. *  *           sre_randseed is a static variable, set *           by sre_srandom(). When it is non-zero,  *           we re-seed. *            *           Implements L'Ecuyer's algorithm for combining output *           of two linear congruential generators, plus a Bays-Durham *           shuffle. This is essentially ran2() from Numerical Recipes, *           sans their nonhelpful Rand/McNally-esque code obfuscation. *            *           Overflow errors are avoided by Schrage's algorithm: *               az % m = a(z%q) - r(z/q) (+m if <0) *           where q=m/a, r=m%a * *           Requires that long int's have at least 32 bits. *           This function uses statics and is NOT THREADSAFE. *            * Reference: Press et al. Numerical Recipes in C, 1992.  * * Reliable and portable, but slow. Benchmarks on wrasse, * using Linux gcc and Linux glibc rand() (see randspeed, in Testsuite): *     sre_random():    0.5 usec/call *     rand():          0.2 usec/call */doublesre_random(void){  static long  rnd1;		/* random number from LCG1 */  static long  rnd2;            /* random number from LCG2 */  static long  rnd;             /* random number we return */  static long  tbl[64];		/* table for Bays/Durham shuffle */  long x,y;  int i;  /* Magic numbers a1,m1, a2,m2 from L'Ecuyer, for 2 LCGs.   * q,r derive from them (q=m/a, r=m%a) and are needed for Schrage's algorithm.   */  long a1 = 40014;		  long m1 = 2147483563;		  long q1 = 53668;  long r1 = 12211;  long a2 = 40692;  long m2 = 2147483399;  long q2 = 52774;  long r2 = 3791;  if (sre_randseed > 0)     {      rnd1 = sre_randseed;      rnd2 = sre_randseed;				/* Fill the table for Bays/Durham */      for (i = 0; i < 64; i++) {	x    = a1*(rnd1%q1);   /* LCG1 in action... */	y    = r1*(rnd1/q1);	rnd1 = x-y;	if (rnd1 < 0) rnd1 += m1;	x    = a2*(rnd2%q2);   /* LCG2 in action... */	y    = r2*(rnd2/q2);	rnd2 = x-y;	if (rnd2 < 0) rnd2 += m2;	tbl[i] = rnd1-rnd2;	if (tbl[i] < 0) tbl[i] += m1;      }      sre_randseed = 0;		/* drop the flag. */    }/* end of initialization*/  x    = a1*(rnd1%q1);   /* LCG1 in action... */  y    = r1*(rnd1/q1);  rnd1 = x-y;  if (rnd1 < 0) rnd1 += m1;  x    = a2*(rnd2%q2);   /* LCG2 in action... */  y    = r2*(rnd2/q2);  rnd2 = x-y;  if (rnd2 < 0) rnd2 += m2;   			/* Choose our random number from the table... */  i   = (int) (((double) rnd / (double) m1) * 64.);  rnd = tbl[i];			/* and replace with a new number by L'Ecuyer. */  tbl[i] = rnd1-rnd2;  if (tbl[i] < 0) tbl[i] += m1;  return ((double) rnd / (double) m1);  }/* Function: sre_srandom() *  * Purpose:  Initialize with a random seed. Seed must be *           >= 0 to work; we silently enforce this. */voidsre_srandom(int seed){  if (seed < 0)  seed = -1 * seed;  if (seed == 0) seed = 42;  sre_randseed = seed;}/* Function: sre_random_positive() * Date:     SRE, Wed Apr 17 13:34:32 2002 [St. Louis] * * Purpose:  Assure 0 < x < 1 (positive uniform deviate) */doublesre_random_positive(void){  double x;  do { x = sre_random(); } while (x == 0.0);  return x;}/* Function: ExponentialRandom() * Date:     SRE, Mon Sep  6 21:24:29 1999 [St. Louis] * * Purpose:  Pick an exponentially distributed random variable *           0 > x >= infinity *            * Args:     (void) * * Returns:  x */doubleExponentialRandom(void){  double x;  do x = sre_random(); while (x == 0.0);  return -log(x);}    /* Function: Gaussrandom() *  * Pick a Gaussian-distributed random variable * with some mean and standard deviation, and * return it. *  * Based on RANLIB.c public domain implementation. * Thanks to the authors, Barry W. Brown and James Lovato, * University of Texas, M.D. Anderson Cancer Center, Houston TX. * Their implementation is from Ahrens and Dieter, "Extensions  * of Forsythe's method for random sampling from the normal * distribution", Math. Comput. 27:927-937 (1973). * * Impenetrability of the code is to be blamed on its FORTRAN/f2c lineage. *  */doubleGaussrandom(double mean, double stddev){  static double a[32] = {    0.0,3.917609E-2,7.841241E-2,0.11777,0.1573107,0.1970991,0.2372021,0.2776904,    0.3186394,0.36013,0.4022501,0.4450965,0.4887764,0.5334097,0.5791322,    0.626099,0.6744898,0.7245144,0.7764218,0.8305109,0.8871466,0.9467818,    1.00999,1.077516,1.150349,1.229859,1.318011,1.417797,1.534121,1.67594,    1.862732,2.153875  };  static double d[31] = {    0.0,0.0,0.0,0.0,0.0,0.2636843,0.2425085,0.2255674,0.2116342,0.1999243,    0.1899108,0.1812252,0.1736014,0.1668419,0.1607967,0.1553497,0.1504094,    0.1459026,0.14177,0.1379632,0.1344418,0.1311722,0.128126,0.1252791,    0.1226109,0.1201036,0.1177417,0.1155119,0.1134023,0.1114027,0.1095039  };  static double t[31] = {    7.673828E-4,2.30687E-3,3.860618E-3,5.438454E-3,7.0507E-3,8.708396E-3,    1.042357E-2,1.220953E-2,1.408125E-2,1.605579E-2,1.81529E-2,2.039573E-2,    2.281177E-2,2.543407E-2,2.830296E-2,3.146822E-2,3.499233E-2,3.895483E-2,    4.345878E-2,4.864035E-2,5.468334E-2,6.184222E-2,7.047983E-2,8.113195E-2,    9.462444E-2,0.1123001,0.136498,0.1716886,0.2276241,0.330498,0.5847031  };  static double h[31] = {    3.920617E-2,3.932705E-2,3.951E-2,3.975703E-2,4.007093E-2,4.045533E-2,    4.091481E-2,4.145507E-2,4.208311E-2,4.280748E-2,4.363863E-2,4.458932E-2,    4.567523E-2,4.691571E-2,4.833487E-2,4.996298E-2,5.183859E-2,5.401138E-2,    5.654656E-2,5.95313E-2,6.308489E-2,6.737503E-2,7.264544E-2,7.926471E-2,    8.781922E-2,9.930398E-2,0.11556,0.1404344,0.1836142,0.2790016,0.7010474  };  static long i;  static double snorm,u,s,ustar,aa,w,y,tt;  u = sre_random();  s = 0.0;  if(u > 0.5) s = 1.0;  u += (u-s);  u = 32.0*u;  i = (long) (u);  if(i == 32) i = 31;  if(i == 0) goto S100;  /*   * START CENTER   */  ustar = u-(double)i;  aa = *(a+i-1);S40:  if(ustar <= *(t+i-1)) goto S60;  w = (ustar-*(t+i-1))**(h+i-1);S50:  /*   * EXIT   (BOTH CASES)   */  y = aa+w;  snorm = y;  if(s == 1.0) snorm = -y;  return (stddev*snorm + mean);S60:  /*   * CENTER CONTINUED   */  u = sre_random();  w = u*(*(a+i)-aa);  tt = (0.5*w+aa)*w;  goto S80;S70:  tt = u;  ustar = sre_random();S80:  if(ustar > tt) goto S50;  u = sre_random();  if(ustar >= u) goto S70;  ustar = sre_random();  goto S40;S100:  /*   * START TAIL   */  i = 6;  aa = *(a+31);  goto S120;S110:  aa += *(d+i-1);  i += 1;S120:  u += u;  if(u < 1.0) goto S110;  u -= 1.0;S140:  w = u**(d+i-1);  tt = (0.5*w+aa)*w;  goto S160;S150:  tt = u;S160:  ustar = sre_random();  if(ustar > tt) goto S50;  u = sre_random();  if(ustar >= u) goto S150;  u = sre_random();  goto S140;}  /* Functions: DChoose(), FChoose() * * Purpose:   Make a random choice from a normalized distribution. *            DChoose() is for double-precision vectors; *            FChoose() is for single-precision float vectors. *            Returns the number of the choice. */intDChoose(double *p, int N){  double roll;                  /* random fraction */  double sum;                   /* integrated prob */  int    i;                     /* counter over the probs */  roll    = sre_random();  sum     = 0.0;  for (i = 0; i < N; i++)    {      sum += p[i];      if (roll < sum) return i;    }  return (int) (sre_random() * N);         /* bulletproof */}intFChoose(float *p, int N){  float roll;                   /* random fraction */  float sum;			/* integrated prob */  int   i;                      /* counter over the probs */  roll    = sre_random();  sum     = 0.0;  for (i = 0; i < N; i++)    {      sum += p[i];      if (roll < sum) return i;    }  return (int) (sre_random() * N);           /* bulletproof */}  

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?