Annotation of capa/capa51/pProj/ranlib.c, revision 1.1.1.1

1.1       albertel    1: 
                      2: #include "ranlib.h"
                      3: #include <stdio.h>
                      4: #include <math.h>
                      5: #include <stdlib.h>
                      6: #define abs(x) ((x) >= 0 ? (x) : -(x))
                      7: #define min(a,b) ((a) <= (b) ? (a) : (b))
                      8: #define max(a,b) ((a) >= (b) ? (a) : (b))
                      9: 
                     10: /*
                     11: **********************************************************************
                     12:      float genbet(float aa,float bb)
                     13:                GeNerate BETa random deviate
                     14:                               Function
                     15:      Returns a single random deviate from the beta distribution with
                     16:      parameters A and B.  The density of the beta is
                     17:                x^(a-1) * (1-x)^(b-1) / B(a,b) for 0 < x < 1
                     18:                               Arguments
                     19:      aa --> First parameter of the beta distribution
                     20:        
                     21:      bb --> Second parameter of the beta distribution
                     22:        
                     23:                               Method
                     24:      R. C. H. Cheng
                     25:      Generating Beta Variatew with Nonintegral Shape Parameters
                     26:      Communications of the ACM, 21:317-322  (1978)
                     27:      (Algorithms BB and BC)
                     28: **********************************************************************
                     29: */
                     30: float genbet(float aa,float bb)
                     31: {
                     32: #define expmax 89.0
                     33: #define infnty 1.0E38
                     34: static float olda = -1.0;
                     35: static float oldb = -1.0;
                     36: static float genbet,a,alpha,b,beta,delta,gamma,k1,k2,r,s,t,u1,u2,v,w,y,z;
                     37: static long qsame;
                     38: 
                     39:     qsame = olda == aa && oldb == bb;
                     40:     if(qsame) goto S20;
                     41:     if(!(aa <= 0.0 || bb <= 0.0)) goto S10;
                     42:     puts(" AA or BB <= 0 in GENBET - Abort!");
                     43:     printf(" AA: %16.6E BB %16.6E\n",aa,bb);
                     44:     exit(1);
                     45: S10:
                     46:     olda = aa;
                     47:     oldb = bb;
                     48: S20:
                     49:     if(!(min(aa,bb) > 1.0)) goto S100;
                     50: /*
                     51:      Alborithm BB
                     52:      Initialize
                     53: */
                     54:     if(qsame) goto S30;
                     55:     a = min(aa,bb);
                     56:     b = max(aa,bb);
                     57:     alpha = a+b;
                     58:     beta = sqrt((alpha-2.0)/(2.0*a*b-alpha));
                     59:     gamma = a+1.0/beta;
                     60: S30:
                     61: S40:
                     62:     u1 = ranf();
                     63: /*
                     64:      Step 1
                     65: */
                     66:     u2 = ranf();
                     67:     v = beta*log(u1/(1.0-u1));
                     68:     if(!(v > expmax)) goto S50;
                     69:     w = infnty;
                     70:     goto S60;
                     71: S50:
                     72:     w = a*exp(v);
                     73: S60:
                     74:     z = pow(u1,2.0)*u2;
                     75:     r = gamma*v-1.3862944;
                     76:     s = a+r-w;
                     77: /*
                     78:      Step 2
                     79: */
                     80:     if(s+2.609438 >= 5.0*z) goto S70;
                     81: /*
                     82:      Step 3
                     83: */
                     84:     t = log(z);
                     85:     if(s > t) goto S70;
                     86: /*
                     87:      Step 4
                     88: */
                     89:     if(r+alpha*log(alpha/(b+w)) < t) goto S40;
                     90: S70:
                     91: /*
                     92:      Step 5
                     93: */
                     94:     if(!(aa == a)) goto S80;
                     95:     genbet = w/(b+w);
                     96:     goto S90;
                     97: S80:
                     98:     genbet = b/(b+w);
                     99: S90:
                    100:     goto S230;
                    101: S100:
                    102: /*
                    103:      Algorithm BC
                    104:      Initialize
                    105: */
                    106:     if(qsame) goto S110;
                    107:     a = max(aa,bb);
                    108:     b = min(aa,bb);
                    109:     alpha = a+b;
                    110:     beta = 1.0/b;
                    111:     delta = 1.0+a-b;
                    112:     k1 = delta*(1.38889E-2+4.16667E-2*b)/(a*beta-0.777778);
                    113:     k2 = 0.25+(0.5+0.25/delta)*b;
                    114: S110:
                    115: S120:
                    116:     u1 = ranf();
                    117: /*
                    118:      Step 1
                    119: */
                    120:     u2 = ranf();
                    121:     if(u1 >= 0.5) goto S130;
                    122: /*
                    123:      Step 2
                    124: */
                    125:     y = u1*u2;
                    126:     z = u1*y;
                    127:     if(0.25*u2+z-y >= k1) goto S120;
                    128:     goto S170;
                    129: S130:
                    130: /*
                    131:      Step 3
                    132: */
                    133:     z = pow(u1,2.0)*u2;
                    134:     if(!(z <= 0.25)) goto S160;
                    135:     v = beta*log(u1/(1.0-u1));
                    136:     if(!(v > expmax)) goto S140;
                    137:     w = infnty;
                    138:     goto S150;
                    139: S140:
                    140:     w = a*exp(v);
                    141: S150:
                    142:     goto S200;
                    143: S160:
                    144:     if(z >= k2) goto S120;
                    145: S170:
                    146: /*
                    147:      Step 4
                    148:      Step 5
                    149: */
                    150:     v = beta*log(u1/(1.0-u1));
                    151:     if(!(v > expmax)) goto S180;
                    152:     w = infnty;
                    153:     goto S190;
                    154: S180:
                    155:     w = a*exp(v);
                    156: S190:
                    157:     if(alpha*(log(alpha/(b+w))+v)-1.3862944 < log(z)) goto S120;
                    158: S200:
                    159: /*
                    160:      Step 6
                    161: */
                    162:     if(!(a == aa)) goto S210;
                    163:     genbet = w/(b+w);
                    164:     goto S220;
                    165: S210:
                    166:     genbet = b/(b+w);
                    167: S230:
                    168: S220:
                    169:     return genbet;
                    170: #undef expmax
                    171: #undef infnty
                    172: }
                    173: float genchi(float df)
                    174: /*
                    175: **********************************************************************
                    176:      float genchi(float df)
                    177:                 Generate random value of CHIsquare variable
                    178:                               Function
                    179:      Generates random deviate from the distribution of a chisquare
                    180:      with DF degrees of freedom random variable.
                    181:                               Arguments
                    182:      df --> Degrees of freedom of the chisquare
                    183:             (Must be positive)
                    184:        
                    185:                               Method
                    186:      Uses relation between chisquare and gamma.
                    187: **********************************************************************
                    188: */
                    189: {
                    190: static float genchi;
                    191: 
                    192:     if(!(df <= 0.0)) goto S10;
                    193:     puts("DF <= 0 in GENCHI - ABORT");
                    194:     printf("Value of DF: %16.6E\n",df);
                    195:     exit(1);
                    196: S10:
                    197:     genchi = 2.0*gengam(1.0,df/2.0);
                    198:     return genchi;
                    199: }
                    200: float genexp(float av)
                    201: /*
                    202: **********************************************************************
                    203:      float genexp(float av)
                    204:                     GENerate EXPonential random deviate
                    205:                               Function
                    206:      Generates a single random deviate from an exponential
                    207:      distribution with mean AV.
                    208:                               Arguments
                    209:      av --> The mean of the exponential distribution from which
                    210:             a random deviate is to be generated.
                    211:                               Method
                    212:      Renames SEXPO from TOMS as slightly modified by BWB to use RANF
                    213:      instead of SUNIF.
                    214:      For details see:
                    215:                Ahrens, J.H. and Dieter, U.
                    216:                Computer Methods for Sampling From the
                    217:                Exponential and Normal Distributions.
                    218:                Comm. ACM, 15,10 (Oct. 1972), 873 - 882.
                    219: **********************************************************************
                    220: */
                    221: {
                    222: static float genexp;
                    223: 
                    224:     genexp = sexpo()*av;
                    225:     return genexp;
                    226: }
                    227: float genf(float dfn,float dfd)
                    228: /*
                    229: **********************************************************************
                    230:      float genf(float dfn,float dfd)
                    231:                 GENerate random deviate from the F distribution
                    232:                               Function
                    233:      Generates a random deviate from the F (variance ratio)
                    234:      distribution with DFN degrees of freedom in the numerator
                    235:      and DFD degrees of freedom in the denominator.
                    236:                               Arguments
                    237:      dfn --> Numerator degrees of freedom
                    238:              (Must be positive)
                    239:      dfd --> Denominator degrees of freedom
                    240:              (Must be positive)
                    241:                               Method
                    242:      Directly generates ratio of chisquare variates
                    243: **********************************************************************
                    244: */
                    245: {
                    246: static float genf,xden,xnum;
                    247: 
                    248:     if(!(dfn <= 0.0 || dfd <= 0.0)) goto S10;
                    249:     puts("Degrees of freedom nonpositive in GENF - abort!");
                    250:     printf("DFN value: %16.6EDFD value: %16.6E\n",dfn,dfd);
                    251:     exit(1);
                    252: S10:
                    253:     xnum = genchi(dfn)/dfn;
                    254: /*
                    255:       GENF = ( GENCHI( DFN ) / DFN ) / ( GENCHI( DFD ) / DFD )
                    256: */
                    257:     xden = genchi(dfd)/dfd;
                    258:     if(!(xden <= 9.999999999998E-39*xnum)) goto S20;
                    259:     puts(" GENF - generated numbers would cause overflow");
                    260:     printf(" Numerator %16.6E Denominator %16.6E\n",xnum,xden);
                    261:     puts(" GENF returning 1.0E38");
                    262:     genf = 1.0E38;
                    263:     goto S30;
                    264: S20:
                    265:     genf = xnum/xden;
                    266: S30:
                    267:     return genf;
                    268: }
                    269: float gengam(float a,float r)
                    270: /*
                    271: **********************************************************************
                    272:      float gengam(float a,float r)
                    273:            GENerates random deviates from GAMma distribution
                    274:                               Function
                    275:      Generates random deviates from the gamma distribution whose
                    276:      density is
                    277:           (A**R)/Gamma(R) * X**(R-1) * Exp(-A*X)
                    278:                               Arguments
                    279:      a --> Location parameter of Gamma distribution
                    280:      r --> Shape parameter of Gamma distribution
                    281:                               Method
                    282:      Renames SGAMMA from TOMS as slightly modified by BWB to use RANF
                    283:      instead of SUNIF.
                    284:      For details see:
                    285:                (Case R >= 1.0)
                    286:                Ahrens, J.H. and Dieter, U.
                    287:                Generating Gamma Variates by a
                    288:                Modified Rejection Technique.
                    289:                Comm. ACM, 25,1 (Jan. 1982), 47 - 54.
                    290:      Algorithm GD
                    291:                (Case 0.0 <= R <= 1.0)
                    292:                Ahrens, J.H. and Dieter, U.
                    293:                Computer Methods for Sampling from Gamma,
                    294:                Beta, Poisson and Binomial Distributions.
                    295:                Computing, 12 (1974), 223-246/
                    296:      Adapted algorithm GS.
                    297: **********************************************************************
                    298: */
                    299: {
                    300: static float gengam;
                    301: 
                    302:     gengam = sgamma(r);
                    303:     gengam /= a;
                    304:     return gengam;
                    305: }
                    306: void genmn(float *parm,float *x,float *work)
                    307: /*
                    308: **********************************************************************
                    309:      void genmn(float *parm,float *x,float *work)
                    310:               GENerate Multivariate Normal random deviate
                    311:                               Arguments
                    312:      parm --> Parameters needed to generate multivariate normal
                    313:                deviates (MEANV and Cholesky decomposition of
                    314:                COVM). Set by a previous call to SETGMN.
                    315:                1 : 1                - size of deviate, P
                    316:                2 : P + 1            - mean vector
                    317:                P+2 : P*(P+3)/2 + 1  - upper half of cholesky
                    318:                                        decomposition of cov matrix
                    319:      x    <-- Vector deviate generated.
                    320:      work <--> Scratch array
                    321:                               Method
                    322:      1) Generate P independent standard normal deviates - Ei ~ N(0,1)
                    323:      2) Using Cholesky decomposition find A s.t. trans(A)*A = COVM
                    324:      3) trans(A)E + MEANV ~ N(MEANV,COVM)
                    325: **********************************************************************
                    326: */
                    327: {
                    328: static long i,icount,j,p,D1,D2,D3,D4;
                    329: static float ae;
                    330: 
                    331:     p = (long) (*parm);
                    332: /*
                    333:      Generate P independent normal deviates - WORK ~ N(0,1)
                    334: */
                    335:     for(i=1; i<=p; i++) *(work+i-1) = snorm();
                    336:     for(i=1,D3=1,D4=(p-i+D3)/D3; D4>0; D4--,i+=D3) {
                    337: /*
                    338:      PARM (P+2 : P*(P+3)/2 + 1) contains A, the Cholesky
                    339:       decomposition of the desired covariance matrix.
                    340:           trans(A)(1,1) = PARM(P+2)
                    341:           trans(A)(2,1) = PARM(P+3)
                    342:           trans(A)(2,2) = PARM(P+2+P)
                    343:           trans(A)(3,1) = PARM(P+4)
                    344:           trans(A)(3,2) = PARM(P+3+P)
                    345:           trans(A)(3,3) = PARM(P+2-1+2P)  ...
                    346:      trans(A)*WORK + MEANV ~ N(MEANV,COVM)
                    347: */
                    348:         icount = 0;
                    349:         ae = 0.0;
                    350:         for(j=1,D1=1,D2=(i-j+D1)/D1; D2>0; D2--,j+=D1) {
                    351:             icount += (j-1);
                    352:             ae += (*(parm+i+(j-1)*p-icount+p)**(work+j-1));
                    353:         }
                    354:         *(x+i-1) = ae+*(parm+i);
                    355:     }
                    356: }
                    357: float gennch(float df,float xnonc)
                    358: /*
                    359: **********************************************************************
                    360:      float gennch(float df,float xnonc)
                    361:            Generate random value of Noncentral CHIsquare variable
                    362:                               Function
                    363:      Generates random deviate  from the  distribution  of a  noncentral
                    364:      chisquare with DF degrees  of freedom and noncentrality  parameter
                    365:      xnonc.
                    366:                               Arguments
                    367:      df --> Degrees of freedom of the chisquare
                    368:             (Must be > 1.0)
                    369:      xnonc --> Noncentrality parameter of the chisquare
                    370:                (Must be >= 0.0)
                    371:                               Method
                    372:      Uses fact that  noncentral chisquare  is  the  sum of a  chisquare
                    373:      deviate with DF-1  degrees of freedom plus the  square of a normal
                    374:      deviate with mean XNONC and standard deviation 1.
                    375: **********************************************************************
                    376: */
                    377: {
                    378: static float gennch;
                    379: 
                    380:     if(!(df <= 1.0 || xnonc < 0.0)) goto S10;
                    381:     puts("DF <= 1 or XNONC < 0 in GENNCH - ABORT");
                    382:     printf("Value of DF: %16.6E Value of XNONC%16.6E\n",df,xnonc);
                    383:     exit(1);
                    384: S10:
                    385:     gennch = genchi(df-1.0)+pow(gennor(sqrt(xnonc),1.0),2.0);
                    386:     return gennch;
                    387: }
                    388: float gennf(float dfn,float dfd,float xnonc)
                    389: /*
                    390: **********************************************************************
                    391:      float gennf(float dfn,float dfd,float xnonc)
                    392:            GENerate random deviate from the Noncentral F distribution
                    393:                               Function
                    394:      Generates a random deviate from the  noncentral F (variance ratio)
                    395:      distribution with DFN degrees of freedom in the numerator, and DFD
                    396:      degrees of freedom in the denominator, and noncentrality parameter
                    397:      XNONC.
                    398:                               Arguments
                    399:      dfn --> Numerator degrees of freedom
                    400:              (Must be >= 1.0)
                    401:      dfd --> Denominator degrees of freedom
                    402:              (Must be positive)
                    403:      xnonc --> Noncentrality parameter
                    404:                (Must be nonnegative)
                    405:                               Method
                    406:      Directly generates ratio of noncentral numerator chisquare variate
                    407:      to central denominator chisquare variate.
                    408: **********************************************************************
                    409: */
                    410: {
                    411: static float gennf,xden,xnum;
                    412: static long qcond;
                    413: 
                    414:     qcond = dfn <= 1.0 || dfd <= 0.0 || xnonc < 0.0;
                    415:     if(!qcond) goto S10;
                    416:     puts("In GENNF - Either (1) Numerator DF <= 1.0 or");
                    417:     puts("(2) Denominator DF < 0.0 or ");
                    418:     puts("(3) Noncentrality parameter < 0.0");
                    419:     printf("DFN value: %16.6EDFD value: %16.6EXNONC value: \n%16.6E\n",dfn,dfd,
                    420:       xnonc);
                    421:     exit(1);
                    422: S10:
                    423:     xnum = gennch(dfn,xnonc)/dfn;
                    424: /*
                    425:       GENNF = ( GENNCH( DFN, XNONC ) / DFN ) / ( GENCHI( DFD ) / DFD )
                    426: */
                    427:     xden = genchi(dfd)/dfd;
                    428:     if(!(xden <= 9.999999999998E-39*xnum)) goto S20;
                    429:     puts(" GENNF - generated numbers would cause overflow");
                    430:     printf(" Numerator %16.6E Denominator %16.6E\n",xnum,xden);
                    431:     puts(" GENNF returning 1.0E38");
                    432:     gennf = 1.0E38;
                    433:     goto S30;
                    434: S20:
                    435:     gennf = xnum/xden;
                    436: S30:
                    437:     return gennf;
                    438: }
                    439: float gennor(float av,float sd)
                    440: /*
                    441: **********************************************************************
                    442:      float gennor(float av,float sd)
                    443:          GENerate random deviate from a NORmal distribution
                    444:                               Function
                    445:      Generates a single random deviate from a normal distribution
                    446:      with mean, AV, and standard deviation, SD.
                    447:                               Arguments
                    448:      av --> Mean of the normal distribution.
                    449:      sd --> Standard deviation of the normal distribution.
                    450:                               Method
                    451:      Renames SNORM from TOMS as slightly modified by BWB to use RANF
                    452:      instead of SUNIF.
                    453:      For details see:
                    454:                Ahrens, J.H. and Dieter, U.
                    455:                Extensions of Forsythe's Method for Random
                    456:                Sampling from the Normal Distribution.
                    457:                Math. Comput., 27,124 (Oct. 1973), 927 - 937.
                    458: **********************************************************************
                    459: */
                    460: {
                    461: static float gennor;
                    462: 
                    463:     gennor = sd*snorm()+av;
                    464:     return gennor;
                    465: }
                    466: void genprm(long *iarray,int larray)
                    467: /*
                    468: **********************************************************************
                    469:     void genprm(long *iarray,int larray)
                    470:                GENerate random PeRMutation of iarray
                    471:                               Arguments
                    472:      iarray <--> On output IARRAY is a random permutation of its
                    473:                  value on input
                    474:      larray <--> Length of IARRAY
                    475: **********************************************************************
                    476: */
                    477: {
                    478: static long i,itmp,iwhich,D1,D2;
                    479: 
                    480:     for(i=1,D1=1,D2=(larray-i+D1)/D1; D2>0; D2--,i+=D1) {
                    481:         iwhich = ignuin(i,larray);
                    482:         itmp = *(iarray+iwhich-1);
                    483:         *(iarray+iwhich-1) = *(iarray+i-1);
                    484:         *(iarray+i-1) = itmp;
                    485:     }
                    486: }
                    487: float genunf(float low,float high)
                    488: /*
                    489: **********************************************************************
                    490:      float genunf(float low,float high)
                    491:                GeNerate Uniform Real between LOW and HIGH
                    492:                               Function
                    493:      Generates a real uniformly distributed between LOW and HIGH.
                    494:                               Arguments
                    495:      low --> Low bound (exclusive) on real value to be generated
                    496:      high --> High bound (exclusive) on real value to be generated
                    497: **********************************************************************
                    498: */
                    499: {
                    500: static float genunf;
                    501: 
                    502:     if(!(low > high)) goto S10;
                    503:     printf("LOW > HIGH in GENUNF: LOW %16.6E HIGH: %16.6E\n",low,high);
                    504:     puts("Abort");
                    505:     exit(1);
                    506: S10:
                    507:     genunf = low+(high-low)*ranf();
                    508:     return genunf;
                    509: }
                    510: void gscgn(long getset,long *g)
                    511: /*
                    512: **********************************************************************
                    513:      void gscgn(long getset,long *g)
                    514:                          Get/Set GeNerator
                    515:      Gets or returns in G the number of the current generator
                    516:                               Arguments
                    517:      getset --> 0 Get
                    518:                 1 Set
                    519:      g <-- Number of the current random number generator (1..32)
                    520: **********************************************************************
                    521: */
                    522: {
                    523: #define numg 32L
                    524: static long curntg = 1;
                    525:     if(getset == 0) *g = curntg;
                    526:     else  {
                    527:         if(*g < 0 || *g > numg) {
                    528:             puts(" Generator number out of range in GSCGN");
                    529:             exit(0);
                    530:         }
                    531:         curntg = *g;
                    532:     }
                    533: #undef numg
                    534: }
                    535: void gsrgs(long getset,long *qvalue)
                    536: /*
                    537: **********************************************************************
                    538:      void gsrgs(long getset,long *qvalue)
                    539:                Get/Set Random Generators Set
                    540:      Gets or sets whether random generators set (initialized).
                    541:      Initially (data statement) state is not set
                    542:      If getset is 1 state is set to qvalue
                    543:      If getset is 0 state returned in qvalue
                    544: **********************************************************************
                    545: */
                    546: {
                    547: static long qinit = 0;
                    548: 
                    549:     if(getset == 0) *qvalue = qinit;
                    550:     else qinit = *qvalue;
                    551: }
                    552: void gssst(long getset,long *qset)
                    553: /*
                    554: **********************************************************************
                    555:      void gssst(long getset,long *qset)
                    556:           Get or Set whether Seed is Set
                    557:      Initialize to Seed not Set
                    558:      If getset is 1 sets state to Seed Set
                    559:      If getset is 0 returns T in qset if Seed Set
                    560:      Else returns F in qset
                    561: **********************************************************************
                    562: */
                    563: {
                    564: static long qstate = 0;
                    565:     if(getset != 0) qstate = 1;
                    566:     else  *qset = qstate;
                    567: }
                    568: long ignbin(long n,float pp)
                    569: /*
                    570: **********************************************************************
                    571:      long ignbin(long n,float pp)
                    572:                     GENerate BINomial random deviate
                    573:                               Function
                    574:      Generates a single random deviate from a binomial
                    575:      distribution whose number of trials is N and whose
                    576:      probability of an event in each trial is P.
                    577:                               Arguments
                    578:      n  --> The number of trials in the binomial distribution
                    579:             from which a random deviate is to be generated.
                    580:      p  --> The probability of an event in each trial of the
                    581:             binomial distribution from which a random deviate
                    582:             is to be generated.
                    583:      ignbin <-- A random deviate yielding the number of events
                    584:                 from N independent trials, each of which has
                    585:                 a probability of event P.
                    586:                               Method
                    587:      This is algorithm BTPE from:
                    588:          Kachitvichyanukul, V. and Schmeiser, B. W.
                    589:          Binomial Random Variate Generation.
                    590:          Communications of the ACM, 31, 2
                    591:          (February, 1988) 216.
                    592: **********************************************************************
                    593:      SUBROUTINE BTPEC(N,PP,ISEED,JX)
                    594:      BINOMIAL RANDOM VARIATE GENERATOR
                    595:      MEAN .LT. 30 -- INVERSE CDF
                    596:        MEAN .GE. 30 -- ALGORITHM BTPE:  ACCEPTANCE-REJECTION VIA
                    597:        FOUR REGION COMPOSITION.  THE FOUR REGIONS ARE A TRIANGLE
                    598:        (SYMMETRIC IN THE CENTER), A PAIR OF PARALLELOGRAMS (ABOVE
                    599:        THE TRIANGLE), AND EXPONENTIAL LEFT AND RIGHT TAILS.
                    600:      BTPE REFERS TO BINOMIAL-TRIANGLE-PARALLELOGRAM-EXPONENTIAL.
                    601:      BTPEC REFERS TO BTPE AND "COMBINED."  THUS BTPE IS THE
                    602:        RESEARCH AND BTPEC IS THE IMPLEMENTATION OF A COMPLETE
                    603:        USABLE ALGORITHM.
                    604:      REFERENCE:  VORATAS KACHITVICHYANUKUL AND BRUCE SCHMEISER,
                    605:        "BINOMIAL RANDOM VARIATE GENERATION,"
                    606:        COMMUNICATIONS OF THE ACM, FORTHCOMING
                    607:      WRITTEN:  SEPTEMBER 1980.
                    608:        LAST REVISED:  MAY 1985, JULY 1987
                    609:      REQUIRED SUBPROGRAM:  RAND() -- A UNIFORM (0,1) RANDOM NUMBER
                    610:                            GENERATOR
                    611:      ARGUMENTS
                    612:        N : NUMBER OF BERNOULLI TRIALS            (INPUT)
                    613:        PP : PROBABILITY OF SUCCESS IN EACH TRIAL (INPUT)
                    614:        ISEED:  RANDOM NUMBER SEED                (INPUT AND OUTPUT)
                    615:        JX:  RANDOMLY GENERATED OBSERVATION       (OUTPUT)
                    616:      VARIABLES
                    617:        PSAVE: VALUE OF PP FROM THE LAST CALL TO BTPEC
                    618:        NSAVE: VALUE OF N FROM THE LAST CALL TO BTPEC
                    619:        XNP:  VALUE OF THE MEAN FROM THE LAST CALL TO BTPEC
                    620:        P: PROBABILITY USED IN THE GENERATION PHASE OF BTPEC
                    621:        FFM: TEMPORARY VARIABLE EQUAL TO XNP + P
                    622:        M:  INTEGER VALUE OF THE CURRENT MODE
                    623:        FM:  FLOATING POINT VALUE OF THE CURRENT MODE
                    624:        XNPQ: TEMPORARY VARIABLE USED IN SETUP AND SQUEEZING STEPS
                    625:        P1:  AREA OF THE TRIANGLE
                    626:        C:  HEIGHT OF THE PARALLELOGRAMS
                    627:        XM:  CENTER OF THE TRIANGLE
                    628:        XL:  LEFT END OF THE TRIANGLE
                    629:        XR:  RIGHT END OF THE TRIANGLE
                    630:        AL:  TEMPORARY VARIABLE
                    631:        XLL:  RATE FOR THE LEFT EXPONENTIAL TAIL
                    632:        XLR:  RATE FOR THE RIGHT EXPONENTIAL TAIL
                    633:        P2:  AREA OF THE PARALLELOGRAMS
                    634:        P3:  AREA OF THE LEFT EXPONENTIAL TAIL
                    635:        P4:  AREA OF THE RIGHT EXPONENTIAL TAIL
                    636:        U:  A U(0,P4) RANDOM VARIATE USED FIRST TO SELECT ONE OF THE
                    637:            FOUR REGIONS AND THEN CONDITIONALLY TO GENERATE A VALUE
                    638:            FROM THE REGION
                    639:        V:  A U(0,1) RANDOM NUMBER USED TO GENERATE THE RANDOM VALUE
                    640:            (REGION 1) OR TRANSFORMED INTO THE VARIATE TO ACCEPT OR
                    641:            REJECT THE CANDIDATE VALUE
                    642:        IX:  INTEGER CANDIDATE VALUE
                    643:        X:  PRELIMINARY CONTINUOUS CANDIDATE VALUE IN REGION 2 LOGIC
                    644:            AND A FLOATING POINT IX IN THE ACCEPT/REJECT LOGIC
                    645:        K:  ABSOLUTE VALUE OF (IX-M)
                    646:        F:  THE HEIGHT OF THE SCALED DENSITY FUNCTION USED IN THE
                    647:            ACCEPT/REJECT DECISION WHEN BOTH M AND IX ARE SMALL
                    648:            ALSO USED IN THE INVERSE TRANSFORMATION
                    649:        R: THE RATIO P/Q
                    650:        G: CONSTANT USED IN CALCULATION OF PROBABILITY
                    651:        MP:  MODE PLUS ONE, THE LOWER INDEX FOR EXPLICIT CALCULATION
                    652:             OF F WHEN IX IS GREATER THAN M
                    653:        IX1:  CANDIDATE VALUE PLUS ONE, THE LOWER INDEX FOR EXPLICIT
                    654:              CALCULATION OF F WHEN IX IS LESS THAN M
                    655:        I:  INDEX FOR EXPLICIT CALCULATION OF F FOR BTPE
                    656:        AMAXP: MAXIMUM ERROR OF THE LOGARITHM OF NORMAL BOUND
                    657:        YNORM: LOGARITHM OF NORMAL BOUND
                    658:        ALV:  NATURAL LOGARITHM OF THE ACCEPT/REJECT VARIATE V
                    659:        X1,F1,Z,W,Z2,X2,F2, AND W2 ARE TEMPORARY VARIABLES TO BE
                    660:        USED IN THE FINAL ACCEPT/REJECT TEST
                    661:        QN: PROBABILITY OF NO SUCCESS IN N TRIALS
                    662:      REMARK
                    663:        IX AND JX COULD LOGICALLY BE THE SAME VARIABLE, WHICH WOULD
                    664:        SAVE A MEMORY POSITION AND A LINE OF CODE.  HOWEVER, SOME
                    665:        COMPILERS (E.G.,CDC MNF) OPTIMIZE BETTER WHEN THE ARGUMENTS
                    666:        ARE NOT INVOLVED.
                    667:      ISEED NEEDS TO BE DOUBLE PRECISION IF THE IMSL ROUTINE
                    668:      GGUBFS IS USED TO GENERATE UNIFORM RANDOM NUMBER, OTHERWISE
                    669:      TYPE OF ISEED SHOULD BE DICTATED BY THE UNIFORM GENERATOR
                    670: **********************************************************************
                    671: *****DETERMINE APPROPRIATE ALGORITHM AND WHETHER SETUP IS NECESSARY
                    672: */
                    673: {
                    674: static float psave = -1.0;
                    675: static long nsave = -1;
                    676: static long ignbin,i,ix,ix1,k,m,mp,T1;
                    677: static float al,alv,amaxp,c,f,f1,f2,ffm,fm,g,p,p1,p2,p3,p4,q,qn,r,u,v,w,w2,x,x1,
                    678:     x2,xl,xll,xlr,xm,xnp,xnpq,xr,ynorm,z,z2;
                    679: 
                    680:     if(pp != psave) goto S10;
                    681:     if(n != nsave) goto S20;
                    682:     if(xnp < 30.0) goto S150;
                    683:     goto S30;
                    684: S10:
                    685: /*
                    686: *****SETUP, PERFORM ONLY WHEN PARAMETERS CHANGE
                    687: */
                    688:     psave = pp;
                    689:     p = min(psave,1.0-psave);
                    690:     q = 1.0-p;
                    691: S20:
                    692:     xnp = n*p;
                    693:     nsave = n;
                    694:     if(xnp < 30.0) goto S140;
                    695:     ffm = xnp+p;
                    696:     m = ffm;
                    697:     fm = m;
                    698:     xnpq = xnp*q;
                    699:     p1 = (long) (2.195*sqrt(xnpq)-4.6*q)+0.5;
                    700:     xm = fm+0.5;
                    701:     xl = xm-p1;
                    702:     xr = xm+p1;
                    703:     c = 0.134+20.5/(15.3+fm);
                    704:     al = (ffm-xl)/(ffm-xl*p);
                    705:     xll = al*(1.0+0.5*al);
                    706:     al = (xr-ffm)/(xr*q);
                    707:     xlr = al*(1.0+0.5*al);
                    708:     p2 = p1*(1.0+c+c);
                    709:     p3 = p2+c/xll;
                    710:     p4 = p3+c/xlr;
                    711: S30:
                    712: /*
                    713: *****GENERATE VARIATE
                    714: */
                    715:     u = ranf()*p4;
                    716:     v = ranf();
                    717: /*
                    718:      TRIANGULAR REGION
                    719: */
                    720:     if(u > p1) goto S40;
                    721:     ix = xm-p1*v+u;
                    722:     goto S170;
                    723: S40:
                    724: /*
                    725:      PARALLELOGRAM REGION
                    726: */
                    727:     if(u > p2) goto S50;
                    728:     x = xl+(u-p1)/c;
                    729:     v = v*c+1.0-abs(xm-x)/p1;
                    730:     if(v > 1.0 || v <= 0.0) goto S30;
                    731:     ix = x;
                    732:     goto S70;
                    733: S50:
                    734: /*
                    735:      LEFT TAIL
                    736: */
                    737:     if(u > p3) goto S60;
                    738:     ix = xl+log(v)/xll;
                    739:     if(ix < 0) goto S30;
                    740:     v *= ((u-p2)*xll);
                    741:     goto S70;
                    742: S60:
                    743: /*
                    744:      RIGHT TAIL
                    745: */
                    746:     ix = xr-log(v)/xlr;
                    747:     if(ix > n) goto S30;
                    748:     v *= ((u-p3)*xlr);
                    749: S70:
                    750: /*
                    751: *****DETERMINE APPROPRIATE WAY TO PERFORM ACCEPT/REJECT TEST
                    752: */
                    753:     k = abs(ix-m);
                    754:     if(k > 20 && k < xnpq/2-1) goto S130;
                    755: /*
                    756:      EXPLICIT EVALUATION
                    757: */
                    758:     f = 1.0;
                    759:     r = p/q;
                    760:     g = (n+1)*r;
                    761:     T1 = m-ix;
                    762:     if(T1 < 0) goto S80;
                    763:     else if(T1 == 0) goto S120;
                    764:     else  goto S100;
                    765: S80:
                    766:     mp = m+1;
                    767:     for(i=mp; i<=ix; i++) f *= (g/i-r);
                    768:     goto S120;
                    769: S100:
                    770:     ix1 = ix+1;
                    771:     for(i=ix1; i<=m; i++) f /= (g/i-r);
                    772: S120:
                    773:     if(v <= f) goto S170;
                    774:     goto S30;
                    775: S130:
                    776: /*
                    777:      SQUEEZING USING UPPER AND LOWER BOUNDS ON ALOG(F(X))
                    778: */
                    779:     amaxp = k/xnpq*((k*(k/3.0+0.625)+0.1666666666666)/xnpq+0.5);
                    780:     ynorm = -(k*k/(2.0*xnpq));
                    781:     alv = log(v);
                    782:     if(alv < ynorm-amaxp) goto S170;
                    783:     if(alv > ynorm+amaxp) goto S30;
                    784: /*
                    785:      STIRLING'S FORMULA TO MACHINE ACCURACY FOR
                    786:      THE FINAL ACCEPTANCE/REJECTION TEST
                    787: */
                    788:     x1 = ix+1.0;
                    789:     f1 = fm+1.0;
                    790:     z = n+1.0-fm;
                    791:     w = n-ix+1.0;
                    792:     z2 = z*z;
                    793:     x2 = x1*x1;
                    794:     f2 = f1*f1;
                    795:     w2 = w*w;
                    796:     if(alv <= xm*log(f1/x1)+(n-m+0.5)*log(z/w)+(ix-m)*log(w*p/(x1*q))+(13860.0-
                    797:       (462.0-(132.0-(99.0-140.0/f2)/f2)/f2)/f2)/f1/166320.0+(13860.0-(462.0-
                    798:       (132.0-(99.0-140.0/z2)/z2)/z2)/z2)/z/166320.0+(13860.0-(462.0-(132.0-
                    799:       (99.0-140.0/x2)/x2)/x2)/x2)/x1/166320.0+(13860.0-(462.0-(132.0-(99.0
                    800:       -140.0/w2)/w2)/w2)/w2)/w/166320.0) goto S170;
                    801:     goto S30;
                    802: S140:
                    803: /*
                    804:      INVERSE CDF LOGIC FOR MEAN LESS THAN 30
                    805: */
                    806:     qn = pow(q,(double)n);
                    807:     r = p/q;
                    808:     g = r*(n+1);
                    809: S150:
                    810:     ix = 0;
                    811:     f = qn;
                    812:     u = ranf();
                    813: S160:
                    814:     if(u < f) goto S170;
                    815:     if(ix > 110) goto S150;
                    816:     u -= f;
                    817:     ix += 1;
                    818:     f *= (g/ix-r);
                    819:     goto S160;
                    820: S170:
                    821:     if(psave > 0.5) ix = n-ix;
                    822:     ignbin = ix;
                    823:     return ignbin;
                    824: }
                    825: long ignpoi(float mu)
                    826: /*
                    827: **********************************************************************
                    828:      long ignpoi(float mu)
                    829:                     GENerate POIsson random deviate
                    830:                               Function
                    831:      Generates a single random deviate from a Poisson
                    832:      distribution with mean AV.
                    833:                               Arguments
                    834:      av --> The mean of the Poisson distribution from which
                    835:             a random deviate is to be generated.
                    836:      genexp <-- The random deviate.
                    837:                               Method
                    838:      Renames KPOIS from TOMS as slightly modified by BWB to use RANF
                    839:      instead of SUNIF.
                    840:      For details see:
                    841:                Ahrens, J.H. and Dieter, U.
                    842:                Computer Generation of Poisson Deviates
                    843:                From Modified Normal Distributions.
                    844:                ACM Trans. Math. Software, 8, 2
                    845:                (June 1982),163-179
                    846: **********************************************************************
                    847: **********************************************************************
                    848:                                                                       
                    849:                                                                       
                    850:      P O I S S O N  DISTRIBUTION                                      
                    851:                                                                       
                    852:                                                                       
                    853: **********************************************************************
                    854: **********************************************************************
                    855:                                                                       
                    856:      FOR DETAILS SEE:                                                 
                    857:                                                                       
                    858:                AHRENS, J.H. AND DIETER, U.                            
                    859:                COMPUTER GENERATION OF POISSON DEVIATES                
                    860:                FROM MODIFIED NORMAL DISTRIBUTIONS.                    
                    861:                ACM TRANS. MATH. SOFTWARE, 8,2 (JUNE 1982), 163 - 179. 
                    862:                                                                       
                    863:      (SLIGHTLY MODIFIED VERSION OF THE PROGRAM IN THE ABOVE ARTICLE)  
                    864:                                                                       
                    865: **********************************************************************
                    866:       INTEGER FUNCTION IGNPOI(IR,MU)
                    867:      INPUT:  IR=CURRENT STATE OF BASIC RANDOM NUMBER GENERATOR
                    868:              MU=MEAN MU OF THE POISSON DISTRIBUTION
                    869:      OUTPUT: IGNPOI=SAMPLE FROM THE POISSON-(MU)-DISTRIBUTION
                    870:      MUPREV=PREVIOUS MU, MUOLD=MU AT LAST EXECUTION OF STEP P OR B.
                    871:      TABLES: COEFFICIENTS A0-A7 FOR STEP F. FACTORIALS FACT
                    872:      COEFFICIENTS A(K) - FOR PX = FK*V*V*SUM(A(K)*V**K)-DEL
                    873:      SEPARATION OF CASES A AND B
                    874: */
                    875: {
                    876: extern float fsign( float num, float sign );
                    877: static float a0 = -0.5;
                    878: static float a1 = 0.3333333;
                    879: static float a2 = -0.2500068;
                    880: static float a3 = 0.2000118;
                    881: static float a4 = -0.1661269;
                    882: static float a5 = 0.1421878;
                    883: static float a6 = -0.1384794;
                    884: static float a7 = 0.125006;
                    885: static float muold = 0.0;
                    886: static float muprev = 0.0;
                    887: static float fact[10] = {
                    888:     1.0,1.0,2.0,6.0,24.0,120.0,720.0,5040.0,40320.0,362880.0
                    889: };
                    890: static long ignpoi,j,k,kflag,l,m;
                    891: static float b1,b2,c,c0,c1,c2,c3,d,del,difmuk,e,fk,fx,fy,g,omega,p,p0,px,py,q,s,
                    892:     t,u,v,x,xx,pp[35];
                    893: 
                    894:     if(mu == muprev) goto S10;
                    895:     if(mu < 10.0) goto S120;
                    896: /*
                    897:      C A S E  A. (RECALCULATION OF S,D,L IF MU HAS CHANGED)
                    898: */
                    899:     muprev = mu;
                    900:     s = sqrt(mu);
                    901:     d = 6.0*mu*mu;
                    902: /*
                    903:              THE POISSON PROBABILITIES PK EXCEED THE DISCRETE NORMAL
                    904:              PROBABILITIES FK WHENEVER K >= M(MU). L=IFIX(MU-1.1484)
                    905:              IS AN UPPER BOUND TO M(MU) FOR ALL MU >= 10 .
                    906: */
                    907:     l = (long) (mu-1.1484);
                    908: S10:
                    909: /*
                    910:      STEP N. NORMAL SAMPLE - SNORM(IR) FOR STANDARD NORMAL DEVIATE
                    911: */
                    912:     g = mu+s*snorm();
                    913:     if(g < 0.0) goto S20;
                    914:     ignpoi = (long) (g);
                    915: /*
                    916:      STEP I. IMMEDIATE ACCEPTANCE IF IGNPOI IS LARGE ENOUGH
                    917: */
                    918:     if(ignpoi >= l) return ignpoi;
                    919: /*
                    920:      STEP S. SQUEEZE ACCEPTANCE - SUNIF(IR) FOR (0,1)-SAMPLE U
                    921: */
                    922:     fk = (float)ignpoi;
                    923:     difmuk = mu-fk;
                    924:     u = ranf();
                    925:     if(d*u >= difmuk*difmuk*difmuk) return ignpoi;
                    926: S20:
                    927: /*
                    928:      STEP P. PREPARATIONS FOR STEPS Q AND H.
                    929:              (RECALCULATIONS OF PARAMETERS IF NECESSARY)
                    930:              .3989423=(2*PI)**(-.5)  .416667E-1=1./24.  .1428571=1./7.
                    931:              THE QUANTITIES B1, B2, C3, C2, C1, C0 ARE FOR THE HERMITE
                    932:              APPROXIMATIONS TO THE DISCRETE NORMAL PROBABILITIES FK.
                    933:              C=.1069/MU GUARANTEES MAJORIZATION BY THE 'HAT'-FUNCTION.
                    934: */
                    935:     if(mu == muold) goto S30;
                    936:     muold = mu;
                    937:     omega = 0.3989423/s;
                    938:     b1 = 4.166667E-2/mu;
                    939:     b2 = 0.3*b1*b1;
                    940:     c3 = 0.1428571*b1*b2;
                    941:     c2 = b2-15.0*c3;
                    942:     c1 = b1-6.0*b2+45.0*c3;
                    943:     c0 = 1.0-b1+3.0*b2-15.0*c3;
                    944:     c = 0.1069/mu;
                    945: S30:
                    946:     if(g < 0.0) goto S50;
                    947: /*
                    948:              'SUBROUTINE' F IS CALLED (KFLAG=0 FOR CORRECT RETURN)
                    949: */
                    950:     kflag = 0;
                    951:     goto S70;
                    952: S40:
                    953: /*
                    954:      STEP Q. QUOTIENT ACCEPTANCE (RARE CASE)
                    955: */
                    956:     if(fy-u*fy <= py*exp(px-fx)) return ignpoi;
                    957: S50:
                    958: /*
                    959:      STEP E. EXPONENTIAL SAMPLE - SEXPO(IR) FOR STANDARD EXPONENTIAL
                    960:              DEVIATE E AND SAMPLE T FROM THE LAPLACE 'HAT'
                    961:              (IF T <= -.6744 THEN PK < FK FOR ALL MU >= 10.)
                    962: */
                    963:     e = sexpo();
                    964:     u = ranf();
                    965:     u += (u-1.0);
                    966:     t = 1.8+fsign(e,u);
                    967:     if(t <= -0.6744) goto S50;
                    968:     ignpoi = (long) (mu+s*t);
                    969:     fk = (float)ignpoi;
                    970:     difmuk = mu-fk;
                    971: /*
                    972:              'SUBROUTINE' F IS CALLED (KFLAG=1 FOR CORRECT RETURN)
                    973: */
                    974:     kflag = 1;
                    975:     goto S70;
                    976: S60:
                    977: /*
                    978:      STEP H. HAT ACCEPTANCE (E IS REPEATED ON REJECTION)
                    979: */
                    980:     if(c*fabs(u) > py*exp(px+e)-fy*exp(fx+e)) goto S50;
                    981:     return ignpoi;
                    982: S70:
                    983: /*
                    984:      STEP F. 'SUBROUTINE' F. CALCULATION OF PX,PY,FX,FY.
                    985:              CASE IGNPOI .LT. 10 USES FACTORIALS FROM TABLE FACT
                    986: */
                    987:     if(ignpoi >= 10) goto S80;
                    988:     px = -mu;
                    989:     py = pow(mu,(double)ignpoi)/ *(fact+ignpoi);
                    990:     goto S110;
                    991: S80:
                    992: /*
                    993:              CASE IGNPOI .GE. 10 USES POLYNOMIAL APPROXIMATION
                    994:              A0-A7 FOR ACCURACY WHEN ADVISABLE
                    995:              .8333333E-1=1./12.  .3989423=(2*PI)**(-.5)
                    996: */
                    997:     del = 8.333333E-2/fk;
                    998:     del -= (4.8*del*del*del);
                    999:     v = difmuk/fk;
                   1000:     if(fabs(v) <= 0.25) goto S90;
                   1001:     px = fk*log(1.0+v)-difmuk-del;
                   1002:     goto S100;
                   1003: S90:
                   1004:     px = fk*v*v*(((((((a7*v+a6)*v+a5)*v+a4)*v+a3)*v+a2)*v+a1)*v+a0)-del;
                   1005: S100:
                   1006:     py = 0.3989423/sqrt(fk);
                   1007: S110:
                   1008:     x = (0.5-difmuk)/s;
                   1009:     xx = x*x;
                   1010:     fx = -0.5*xx;
                   1011:     fy = omega*(((c3*xx+c2)*xx+c1)*xx+c0);
                   1012:     if(kflag <= 0) goto S40;
                   1013:     goto S60;
                   1014: S120:
                   1015: /*
                   1016:      C A S E  B. (START NEW TABLE AND CALCULATE P0 IF NECESSARY)
                   1017: */
                   1018:     muprev = 0.0;
                   1019:     if(mu == muold) goto S130;
                   1020:     muold = mu;
                   1021:     m = max(1L,(long) (mu));
                   1022:     l = 0;
                   1023:     p = exp(-mu);
                   1024:     q = p0 = p;
                   1025: S130:
                   1026: /*
                   1027:      STEP U. UNIFORM SAMPLE FOR INVERSION METHOD
                   1028: */
                   1029:     u = ranf();
                   1030:     ignpoi = 0;
                   1031:     if(u <= p0) return ignpoi;
                   1032: /*
                   1033:      STEP T. TABLE COMPARISON UNTIL THE END PP(L) OF THE
                   1034:              PP-TABLE OF CUMULATIVE POISSON PROBABILITIES
                   1035:              (0.458=PP(9) FOR MU=10)
                   1036: */
                   1037:     if(l == 0) goto S150;
                   1038:     j = 1;
                   1039:     if(u > 0.458) j = min(l,m);
                   1040:     for(k=j; k<=l; k++) {
                   1041:         if(u <= *(pp+k-1)) goto S180;
                   1042:     }
                   1043:     if(l == 35) goto S130;
                   1044: S150:
                   1045: /*
                   1046:      STEP C. CREATION OF NEW POISSON PROBABILITIES P
                   1047:              AND THEIR CUMULATIVES Q=PP(K)
                   1048: */
                   1049:     l += 1;
                   1050:     for(k=l; k<=35; k++) {
                   1051:         p = p*mu/(float)k;
                   1052:         q += p;
                   1053:         *(pp+k-1) = q;
                   1054:         if(u <= q) goto S170;
                   1055:     }
                   1056:     l = 35;
                   1057:     goto S130;
                   1058: S170:
                   1059:     l = k;
                   1060: S180:
                   1061:     ignpoi = k;
                   1062:     return ignpoi;
                   1063: }
                   1064: long ignuin(long low,long high)
                   1065: /*
                   1066: **********************************************************************
                   1067:      long ignuin(long low,long high)
                   1068:                GeNerate Uniform INteger
                   1069:                               Function
                   1070:      Generates an integer uniformly distributed between LOW and HIGH.
                   1071:                               Arguments
                   1072:      low --> Low bound (inclusive) on integer value to be generated
                   1073:      high --> High bound (inclusive) on integer value to be generated
                   1074:                               Note
                   1075:      If (HIGH-LOW) > 2,147,483,561 prints error message on * unit and
                   1076:      stops the program.
                   1077: **********************************************************************
                   1078:      IGNLGI generates integers between 1 and 2147483562
                   1079:      MAXNUM is 1 less than maximum generable value
                   1080: */
                   1081: {
                   1082: #define maxnum 2147483561L
                   1083: static long ignuin,ign,maxnow,range,ranp1;
                   1084: 
                   1085:     if(!(low > high)) goto S10;
                   1086:     puts(" low > high in ignuin - ABORT");
                   1087:     exit(1);
                   1088: 
                   1089: S10:
                   1090:     range = high-low;
                   1091:     if(!(range > maxnum)) goto S20;
                   1092:     puts(" high - low too large in ignuin - ABORT");
                   1093:     exit(1);
                   1094: 
                   1095: S20:
                   1096:     if(!(low == high)) goto S30;
                   1097:     ignuin = low;
                   1098:     return ignuin;
                   1099: 
                   1100: S30:
                   1101: /*
                   1102:      Number to be generated should be in range 0..RANGE
                   1103:      Set MAXNOW so that the number of integers in 0..MAXNOW is an
                   1104:      integral multiple of the number in 0..RANGE
                   1105: */
                   1106:     ranp1 = range+1;
                   1107:     maxnow = maxnum/ranp1*ranp1;
                   1108: S40:
                   1109:     ign = ignlgi()-1;
                   1110:     if(!(ign <= maxnow)) goto S50;
                   1111:     ignuin = low+ign%ranp1;
                   1112:     return ignuin;
                   1113: S50:
                   1114:     goto S40;
                   1115: #undef maxnum
                   1116: #undef err1
                   1117: #undef err2
                   1118: }
                   1119: long lennob( char *str )
                   1120: /* 
                   1121: Returns the length of str ignoring trailing blanks but not 
                   1122: other white space.
                   1123: */
                   1124: {
                   1125: long i, i_nb;
                   1126: 
                   1127: for (i=0, i_nb= -1L; *(str+i); i++)
                   1128:     if ( *(str+i) != ' ' ) i_nb = i;
                   1129: return (i_nb+1);
                   1130:     }
                   1131: long mltmod(long a,long s,long m)
                   1132: /*
                   1133: **********************************************************************
                   1134:      long mltmod(long a,long s,long m)
                   1135:                     Returns (A*S) MOD M
                   1136:      This is a transcription from Pascal to Fortran of routine
                   1137:      MULtMod_Decompos from the paper
                   1138:      L'Ecuyer, P. and Cote, S. "Implementing a Random Number Package
                   1139:      with Splitting Facilities." ACM Transactions on Mathematical
                   1140:      Software, 17:98-111 (1991)
                   1141:                               Arguments
                   1142:      a, s, m  -->
                   1143: **********************************************************************
                   1144: */
                   1145: {
                   1146: #define h 32768L
                   1147: static long mltmod,a0,a1,k,p,q,qh,rh;
                   1148: /*
                   1149:      H = 2**((b-2)/2) where b = 32 because we are using a 32 bit
                   1150:       machine. On a different machine recompute H
                   1151: */
                   1152:     if(!(a <= 0 || a >= m || s <= 0 || s >= m)) goto S10;
                   1153:     puts(" a, m, s out of order in mltmod - ABORT!");
                   1154:     printf(" a = %12ld s = %12ld m = %12ld\n",a,s,m);
                   1155:     puts(" mltmod requires: 0 < a < m; 0 < s < m");
                   1156:     exit(1);
                   1157: S10:
                   1158:     if(!(a < h)) goto S20;
                   1159:     a0 = a;
                   1160:     p = 0;
                   1161:     goto S120;
                   1162: S20:
                   1163:     a1 = a/h;
                   1164:     a0 = a-h*a1;
                   1165:     qh = m/h;
                   1166:     rh = m-h*qh;
                   1167:     if(!(a1 >= h)) goto S50;
                   1168:     a1 -= h;
                   1169:     k = s/qh;
                   1170:     p = h*(s-k*qh)-k*rh;
                   1171: S30:
                   1172:     if(!(p < 0)) goto S40;
                   1173:     p += m;
                   1174:     goto S30;
                   1175: S40:
                   1176:     goto S60;
                   1177: S50:
                   1178:     p = 0;
                   1179: S60:
                   1180: /*
                   1181:      P = (A2*S*H)MOD M
                   1182: */
                   1183:     if(!(a1 != 0)) goto S90;
                   1184:     q = m/a1;
                   1185:     k = s/q;
                   1186:     p -= (k*(m-a1*q));
                   1187:     if(p > 0) p -= m;
                   1188:     p += (a1*(s-k*q));
                   1189: S70:
                   1190:     if(!(p < 0)) goto S80;
                   1191:     p += m;
                   1192:     goto S70;
                   1193: S90:
                   1194: S80:
                   1195:     k = p/qh;
                   1196: /*
                   1197:      P = ((A2*H + A1)*S)MOD M
                   1198: */
                   1199:     p = h*(p-k*qh)-k*rh;
                   1200: S100:
                   1201:     if(!(p < 0)) goto S110;
                   1202:     p += m;
                   1203:     goto S100;
                   1204: S120:
                   1205: S110:
                   1206:     if(!(a0 != 0)) goto S150;
                   1207: /*
                   1208:      P = ((A2*H + A1)*H*S)MOD M
                   1209: */
                   1210:     q = m/a0;
                   1211:     k = s/q;
                   1212:     p -= (k*(m-a0*q));
                   1213:     if(p > 0) p -= m;
                   1214:     p += (a0*(s-k*q));
                   1215: S130:
                   1216:     if(!(p < 0)) goto S140;
                   1217:     p += m;
                   1218:     goto S130;
                   1219: S150:
                   1220: S140:
                   1221:     mltmod = p;
                   1222:     return mltmod;
                   1223: #undef h
                   1224: }
                   1225: void phrtsd(char* phrase,long *seed1,long *seed2)
                   1226: /*
                   1227: **********************************************************************
                   1228:      void phrtsd(char* phrase,long *seed1,long *seed2)
                   1229:                PHRase To SeeDs
                   1230: 
                   1231:                               Function
                   1232: 
                   1233:      Uses a phrase (character string) to generate two seeds for the RGN
                   1234:      random number generator.
                   1235:                               Arguments
                   1236:      phrase --> Phrase to be used for random number generation
                   1237:       
                   1238:      seed1 <-- First seed for generator
                   1239:                         
                   1240:      seed2 <-- Second seed for generator
                   1241:                         
                   1242:                               Note
                   1243: 
                   1244:      Trailing blanks are eliminated before the seeds are generated.
                   1245:      Generated seed values will fall in the range 1..2^30
                   1246:      (1..1,073,741,824)
                   1247: **********************************************************************
                   1248: */
                   1249: {
                   1250: 
                   1251: static char table[] =
                   1252: "abcdefghijklmnopqrstuvwxyz\
                   1253: ABCDEFGHIJKLMNOPQRSTUVWXYZ\
                   1254: 0123456789\
                   1255: !@#$%^&*()_+[];:'\\\"<>?,./";
                   1256: 
                   1257: long ix;
                   1258: 
                   1259: static long twop30 = 1073741824L;
                   1260: static long shift[5] = {
                   1261:     1L,64L,4096L,262144L,16777216L
                   1262: };
                   1263: static long i,ichr,j,lphr,values[5];
                   1264: extern long lennob(char *str);
                   1265: 
                   1266:     *seed1 = 1234567890L;
                   1267:     *seed2 = 123456789L;
                   1268:     lphr = lennob(phrase); 
                   1269:     if(lphr < 1) return;
                   1270:     for(i=0; i<=(lphr-1); i++) {
                   1271: 	for (ix=0; table[ix]; ix++) if (*(phrase+i) == table[ix]) break; 
                   1272:         if (!table[ix]) ix = 0;
                   1273:         ichr = ix % 64;
                   1274:         if(ichr == 0) ichr = 63;
                   1275:         for(j=1; j<=5; j++) {
                   1276:             *(values+j-1) = ichr-j;
                   1277:             if(*(values+j-1) < 1) *(values+j-1) += 63;
                   1278:         }
                   1279:         for(j=1; j<=5; j++) {
                   1280:             *seed1 = ( *seed1+*(shift+j-1)**(values+j-1) ) % twop30;
                   1281:             *seed2 = ( *seed2+*(shift+j-1)**(values+6-j-1) )  % twop30;
                   1282:         }
                   1283:     }
                   1284: #undef twop30
                   1285: }
                   1286: float ranf(void)
                   1287: /*
                   1288: **********************************************************************
                   1289:      float ranf(void)
                   1290:                 RANDom number generator as a Function
                   1291:      Returns a random floating point number from a uniform distribution
                   1292:      over 0 - 1 (endpoints of this interval are not returned) using the
                   1293:      current generator
                   1294:      This is a transcription from Pascal to Fortran of routine
                   1295:      Uniform_01 from the paper
                   1296:      L'Ecuyer, P. and Cote, S. "Implementing a Random Number Package
                   1297:      with Splitting Facilities." ACM Transactions on Mathematical
                   1298:      Software, 17:98-111 (1991)
                   1299: **********************************************************************
                   1300: */
                   1301: {
                   1302: static float ranf;
                   1303: /*
                   1304:      4.656613057E-10 is 1/M1  M1 is set in a data statement in IGNLGI
                   1305:       and is currently 2147483563. If M1 changes, change this also.
                   1306: */
                   1307:     ranf = ignlgi()*4.656613057E-10;
                   1308:     return ranf;
                   1309: }
                   1310: void setgmn(float *meanv,float *covm,long p,float *parm)
                   1311: /*
                   1312: **********************************************************************
                   1313:      void setgmn(float *meanv,float *covm,long p,float *parm)
                   1314:             SET Generate Multivariate Normal random deviate
                   1315:                               Function
                   1316:       Places P, MEANV, and the Cholesky factoriztion of COVM
                   1317:       in GENMN.
                   1318:                               Arguments
                   1319:      meanv --> Mean vector of multivariate normal distribution.
                   1320:      covm   <--> (Input) Covariance   matrix    of  the  multivariate
                   1321:                  normal distribution
                   1322:                  (Output) Destroyed on output
                   1323:      p     --> Dimension of the normal, or length of MEANV.
                   1324:      parm <-- Array of parameters needed to generate multivariate norma
                   1325:                 deviates (P, MEANV and Cholesky decomposition of
                   1326:                 COVM).
                   1327:                 1 : 1                - P
                   1328:                 2 : P + 1            - MEANV
                   1329:                 P+2 : P*(P+3)/2 + 1  - Cholesky decomposition of COVM
                   1330:                Needed dimension is (p*(p+3)/2 + 1)
                   1331: **********************************************************************
                   1332: */
                   1333: {
                   1334: extern void spofa(float *a,long lda,long n,long *info);
                   1335: static long T1;
                   1336: static long i,icount,info,j,D2,D3,D4,D5;
                   1337:     T1 = p*(p+3)/2+1;
                   1338: /*
                   1339:      TEST THE INPUT
                   1340: */
                   1341:     if(!(p <= 0)) goto S10;
                   1342:     puts("P nonpositive in SETGMN");
                   1343:     printf("Value of P: %12ld\n",p);
                   1344:     exit(1);
                   1345: S10:
                   1346:     *parm = p;
                   1347: /*
                   1348:      PUT P AND MEANV INTO PARM
                   1349: */
                   1350:     for(i=2,D2=1,D3=(p+1-i+D2)/D2; D3>0; D3--,i+=D2) *(parm+i-1) = *(meanv+i-2);
                   1351: /*
                   1352:       Cholesky decomposition to find A s.t. trans(A)*(A) = COVM
                   1353: */
                   1354:     spofa(covm,p,p,&info);
                   1355:     if(!(info != 0)) goto S30;
                   1356:     puts(" COVM not positive definite in SETGMN");
                   1357:     exit(1);
                   1358: S30:
                   1359:     icount = p+1;
                   1360: /*
                   1361:      PUT UPPER HALF OF A, WHICH IS NOW THE CHOLESKY FACTOR, INTO PARM
                   1362:           COVM(1,1) = PARM(P+2)
                   1363:           COVM(1,2) = PARM(P+3)
                   1364:                     :
                   1365:           COVM(1,P) = PARM(2P+1)
                   1366:           COVM(2,2) = PARM(2P+2)  ...
                   1367: */
                   1368:     for(i=1,D4=1,D5=(p-i+D4)/D4; D5>0; D5--,i+=D4) {
                   1369:         for(j=i-1; j<p; j++) {
                   1370:             icount += 1;
                   1371:             *(parm+icount-1) = *(covm+i-1+j*p);
                   1372:         }
                   1373:     }
                   1374: }
                   1375: float sexpo(void)
                   1376: /*
                   1377: **********************************************************************
                   1378:                                                                       
                   1379:                                                                       
                   1380:      (STANDARD-)  E X P O N E N T I A L   DISTRIBUTION                
                   1381:                                                                       
                   1382:                                                                       
                   1383: **********************************************************************
                   1384: **********************************************************************
                   1385:                                                                       
                   1386:      FOR DETAILS SEE:                                                 
                   1387:                                                                       
                   1388:                AHRENS, J.H. AND DIETER, U.                            
                   1389:                COMPUTER METHODS FOR SAMPLING FROM THE                 
                   1390:                EXPONENTIAL AND NORMAL DISTRIBUTIONS.                  
                   1391:                COMM. ACM, 15,10 (OCT. 1972), 873 - 882.               
                   1392:                                                                       
                   1393:      ALL STATEMENT NUMBERS CORRESPOND TO THE STEPS OF ALGORITHM       
                   1394:      'SA' IN THE ABOVE PAPER (SLIGHTLY MODIFIED IMPLEMENTATION)       
                   1395:                                                                       
                   1396:      Modified by Barry W. Brown, Feb 3, 1988 to use RANF instead of   
                   1397:      SUNIF.  The argument IR thus goes away.                          
                   1398:                                                                       
                   1399: **********************************************************************
                   1400:      Q(N) = SUM(ALOG(2.0)**K/K!)    K=1,..,N ,      THE HIGHEST N
                   1401:      (HERE 8) IS DETERMINED BY Q(N)=1.0 WITHIN STANDARD PRECISION
                   1402: */
                   1403: {
                   1404: static float q[8] = {
                   1405:     0.6931472,0.9333737,0.9888778,0.9984959,0.9998293,0.9999833,0.9999986,1.0
                   1406: };
                   1407: static long i;
                   1408: static float sexpo,a,u,ustar,umin;
                   1409: static float *q1 = q;
                   1410:     a = 0.0;
                   1411:     u = ranf();
                   1412:     goto S30;
                   1413: S20:
                   1414:     a += *q1;
                   1415: S30:
                   1416:     u += u;
                   1417:     if(u <= 1.0) goto S20;
                   1418:     u -= 1.0;
                   1419:     if(u > *q1) goto S60;
                   1420:     sexpo = a+u;
                   1421:     return sexpo;
                   1422: S60:
                   1423:     i = 1;
                   1424:     ustar = ranf();
                   1425:     umin = ustar;
                   1426: S70:
                   1427:     ustar = ranf();
                   1428:     if(ustar < umin) umin = ustar;
                   1429:     i += 1;
                   1430:     if(u > *(q+i-1)) goto S70;
                   1431:     sexpo = a+umin**q1;
                   1432:     return sexpo;
                   1433: }
                   1434: float sgamma(float a)
                   1435: /*
                   1436: **********************************************************************
                   1437:                                                                       
                   1438:                                                                       
                   1439:      (STANDARD-)  G A M M A  DISTRIBUTION                             
                   1440:                                                                       
                   1441:                                                                       
                   1442: **********************************************************************
                   1443: **********************************************************************
                   1444:                                                                       
                   1445:                PARAMETER  A >= 1.0  !                                 
                   1446:                                                                       
                   1447: **********************************************************************
                   1448:                                                                       
                   1449:      FOR DETAILS SEE:                                                 
                   1450:                                                                       
                   1451:                AHRENS, J.H. AND DIETER, U.                            
                   1452:                GENERATING GAMMA VARIATES BY A                         
                   1453:                MODIFIED REJECTION TECHNIQUE.                          
                   1454:                COMM. ACM, 25,1 (JAN. 1982), 47 - 54.                  
                   1455:                                                                       
                   1456:      STEP NUMBERS CORRESPOND TO ALGORITHM 'GD' IN THE ABOVE PAPER     
                   1457:                                  (STRAIGHTFORWARD IMPLEMENTATION)     
                   1458:                                                                       
                   1459:      Modified by Barry W. Brown, Feb 3, 1988 to use RANF instead of   
                   1460:      SUNIF.  The argument IR thus goes away.                          
                   1461:                                                                       
                   1462: **********************************************************************
                   1463:                                                                       
                   1464:                PARAMETER  0.0 < A < 1.0  !                            
                   1465:                                                                       
                   1466: **********************************************************************
                   1467:                                                                       
                   1468:      FOR DETAILS SEE:                                                 
                   1469:                                                                       
                   1470:                AHRENS, J.H. AND DIETER, U.                            
                   1471:                COMPUTER METHODS FOR SAMPLING FROM GAMMA,              
                   1472:                BETA, POISSON AND BINOMIAL DISTRIBUTIONS.              
                   1473:                COMPUTING, 12 (1974), 223 - 246.                       
                   1474:                                                                       
                   1475:      (ADAPTED IMPLEMENTATION OF ALGORITHM 'GS' IN THE ABOVE PAPER)    
                   1476:                                                                       
                   1477: **********************************************************************
                   1478:      INPUT: A =PARAMETER (MEAN) OF THE STANDARD GAMMA DISTRIBUTION
                   1479:      OUTPUT: SGAMMA = SAMPLE FROM THE GAMMA-(A)-DISTRIBUTION
                   1480:      COEFFICIENTS Q(K) - FOR Q0 = SUM(Q(K)*A**(-K))
                   1481:      COEFFICIENTS A(K) - FOR Q = Q0+(T*T/2)*SUM(A(K)*V**K)
                   1482:      COEFFICIENTS E(K) - FOR EXP(Q)-1 = SUM(E(K)*Q**K)
                   1483:      PREVIOUS A PRE-SET TO ZERO - AA IS A', AAA IS A"
                   1484:      SQRT32 IS THE SQUAREROOT OF 32 = 5.656854249492380
                   1485: */
                   1486: {
                   1487: extern float fsign( float num, float sign );
                   1488: static float q1 = 4.166669E-2;
                   1489: static float q2 = 2.083148E-2;
                   1490: static float q3 = 8.01191E-3;
                   1491: static float q4 = 1.44121E-3;
                   1492: static float q5 = -7.388E-5;
                   1493: static float q6 = 2.4511E-4;
                   1494: static float q7 = 2.424E-4;
                   1495: static float a1 = 0.3333333;
                   1496: static float a2 = -0.250003;
                   1497: static float a3 = 0.2000062;
                   1498: static float a4 = -0.1662921;
                   1499: static float a5 = 0.1423657;
                   1500: static float a6 = -0.1367177;
                   1501: static float a7 = 0.1233795;
                   1502: static float e1 = 1.0;
                   1503: static float e2 = 0.4999897;
                   1504: static float e3 = 0.166829;
                   1505: static float e4 = 4.07753E-2;
                   1506: static float e5 = 1.0293E-2;
                   1507: static float aa = 0.0;
                   1508: static float aaa = 0.0;
                   1509: static float sqrt32 = 5.656854;
                   1510: static float sgamma,s2,s,d,t,x,u,r,q0,b,si,c,v,q,e,w,p;
                   1511:     if(a == aa) goto S10;
                   1512:     if(a < 1.0) goto S120;
                   1513: /*
                   1514:      STEP  1:  RECALCULATIONS OF S2,S,D IF A HAS CHANGED
                   1515: */
                   1516:     aa = a;
                   1517:     s2 = a-0.5;
                   1518:     s = sqrt(s2);
                   1519:     d = sqrt32-12.0*s;
                   1520: S10:
                   1521: /*
                   1522:      STEP  2:  T=STANDARD NORMAL DEVIATE,
                   1523:                X=(S,1/2)-NORMAL DEVIATE.
                   1524:                IMMEDIATE ACCEPTANCE (I)
                   1525: */
                   1526:     t = snorm();
                   1527:     x = s+0.5*t;
                   1528:     sgamma = x*x;
                   1529:     if(t >= 0.0) return sgamma;
                   1530: /*
                   1531:      STEP  3:  U= 0,1 -UNIFORM SAMPLE. SQUEEZE ACCEPTANCE (S)
                   1532: */
                   1533:     u = ranf();
                   1534:     if(d*u <= t*t*t) return sgamma;
                   1535: /*
                   1536:      STEP  4:  RECALCULATIONS OF Q0,B,SI,C IF NECESSARY
                   1537: */
                   1538:     if(a == aaa) goto S40;
                   1539:     aaa = a;
                   1540:     r = 1.0/ a;
                   1541:     q0 = ((((((q7*r+q6)*r+q5)*r+q4)*r+q3)*r+q2)*r+q1)*r;
                   1542: /*
                   1543:                APPROXIMATION DEPENDING ON SIZE OF PARAMETER A
                   1544:                THE CONSTANTS IN THE EXPRESSIONS FOR B, SI AND
                   1545:                C WERE ESTABLISHED BY NUMERICAL EXPERIMENTS
                   1546: */
                   1547:     if(a <= 3.686) goto S30;
                   1548:     if(a <= 13.022) goto S20;
                   1549: /*
                   1550:                CASE 3:  A .GT. 13.022
                   1551: */
                   1552:     b = 1.77;
                   1553:     si = 0.75;
                   1554:     c = 0.1515/s;
                   1555:     goto S40;
                   1556: S20:
                   1557: /*
                   1558:                CASE 2:  3.686 .LT. A .LE. 13.022
                   1559: */
                   1560:     b = 1.654+7.6E-3*s2;
                   1561:     si = 1.68/s+0.275;
                   1562:     c = 6.2E-2/s+2.4E-2;
                   1563:     goto S40;
                   1564: S30:
                   1565: /*
                   1566:                CASE 1:  A .LE. 3.686
                   1567: */
                   1568:     b = 0.463+s-0.178*s2;
                   1569:     si = 1.235;
                   1570:     c = 0.195/s-7.9E-2+1.6E-2*s;
                   1571: S40:
                   1572: /*
                   1573:      STEP  5:  NO QUOTIENT TEST IF X NOT POSITIVE
                   1574: */
                   1575:     if(x <= 0.0) goto S70;
                   1576: /*
                   1577:      STEP  6:  CALCULATION OF V AND QUOTIENT Q
                   1578: */
                   1579:     v = t/(s+s);
                   1580:     if(fabs(v) <= 0.25) goto S50;
                   1581:     q = q0-s*t+0.25*t*t+(s2+s2)*log(1.0+v);
                   1582:     goto S60;
                   1583: S50:
                   1584:     q = q0+0.5*t*t*((((((a7*v+a6)*v+a5)*v+a4)*v+a3)*v+a2)*v+a1)*v;
                   1585: S60:
                   1586: /*
                   1587:      STEP  7:  QUOTIENT ACCEPTANCE (Q)
                   1588: */
                   1589:     if(log(1.0-u) <= q) return sgamma;
                   1590: S70:
                   1591: /*
                   1592:      STEP  8:  E=STANDARD EXPONENTIAL DEVIATE
                   1593:                U= 0,1 -UNIFORM DEVIATE
                   1594:                T=(B,SI)-DOUBLE EXPONENTIAL (LAPLACE) SAMPLE
                   1595: */
                   1596:     e = sexpo();
                   1597:     u = ranf();
                   1598:     u += (u-1.0);
                   1599:     t = b+fsign(si*e,u);
                   1600: /*
                   1601:      STEP  9:  REJECTION IF T .LT. TAU(1) = -.71874483771719
                   1602: */
                   1603:     if(t < -0.7187449) goto S70;
                   1604: /*
                   1605:      STEP 10:  CALCULATION OF V AND QUOTIENT Q
                   1606: */
                   1607:     v = t/(s+s);
                   1608:     if(fabs(v) <= 0.25) goto S80;
                   1609:     q = q0-s*t+0.25*t*t+(s2+s2)*log(1.0+v);
                   1610:     goto S90;
                   1611: S80:
                   1612:     q = q0+0.5*t*t*((((((a7*v+a6)*v+a5)*v+a4)*v+a3)*v+a2)*v+a1)*v;
                   1613: S90:
                   1614: /*
                   1615:      STEP 11:  HAT ACCEPTANCE (H) (IF Q NOT POSITIVE GO TO STEP 8)
                   1616: */
                   1617:     if(q <= 0.0) goto S70;
                   1618:     if(q <= 0.5) goto S100;
                   1619:     w = exp(q)-1.0;
                   1620:     goto S110;
                   1621: S100:
                   1622:     w = ((((e5*q+e4)*q+e3)*q+e2)*q+e1)*q;
                   1623: S110:
                   1624: /*
                   1625:                IF T IS REJECTED, SAMPLE AGAIN AT STEP 8
                   1626: */
                   1627:     if(c*fabs(u) > w*exp(e-0.5*t*t)) goto S70;
                   1628:     x = s+0.5*t;
                   1629:     sgamma = x*x;
                   1630:     return sgamma;
                   1631: S120:
                   1632: /*
                   1633:      ALTERNATE METHOD FOR PARAMETERS A BELOW 1  (.3678794=EXP(-1.))
                   1634: */
                   1635:     aa = 0.0;
                   1636:     b = 1.0+0.3678794*a;
                   1637: S130:
                   1638:     p = b*ranf();
                   1639:     if(p >= 1.0) goto S140;
                   1640:     sgamma = exp(log(p)/ a);
                   1641:     if(sexpo() < sgamma) goto S130;
                   1642:     return sgamma;
                   1643: S140:
                   1644:     sgamma = -log((b-p)/ a);
                   1645:     if(sexpo() < (1.0-a)*log(sgamma)) goto S130;
                   1646:     return sgamma;
                   1647: }
                   1648: float snorm(void)
                   1649: /*
                   1650: **********************************************************************
                   1651:                                                                       
                   1652:                                                                       
                   1653:      (STANDARD-)  N O R M A L  DISTRIBUTION                           
                   1654:                                                                       
                   1655:                                                                       
                   1656: **********************************************************************
                   1657: **********************************************************************
                   1658:                                                                       
                   1659:      FOR DETAILS SEE:                                                 
                   1660:                                                                       
                   1661:                AHRENS, J.H. AND DIETER, U.                            
                   1662:                EXTENSIONS OF FORSYTHE'S METHOD FOR RANDOM             
                   1663:                SAMPLING FROM THE NORMAL DISTRIBUTION.                 
                   1664:                MATH. COMPUT., 27,124 (OCT. 1973), 927 - 937.          
                   1665:                                                                       
                   1666:      ALL STATEMENT NUMBERS CORRESPOND TO THE STEPS OF ALGORITHM 'FL'  
                   1667:      (M=5) IN THE ABOVE PAPER     (SLIGHTLY MODIFIED IMPLEMENTATION)  
                   1668:                                                                       
                   1669:      Modified by Barry W. Brown, Feb 3, 1988 to use RANF instead of   
                   1670:      SUNIF.  The argument IR thus goes away.                          
                   1671:                                                                       
                   1672: **********************************************************************
                   1673:      THE DEFINITIONS OF THE CONSTANTS A(K), D(K), T(K) AND
                   1674:      H(K) ARE ACCORDING TO THE ABOVEMENTIONED ARTICLE
                   1675: */
                   1676: {
                   1677: static float a[32] = {
                   1678:     0.0,3.917609E-2,7.841241E-2,0.11777,0.1573107,0.1970991,0.2372021,0.2776904,
                   1679:     0.3186394,0.36013,0.4022501,0.4450965,0.4887764,0.5334097,0.5791322,
                   1680:     0.626099,0.6744898,0.7245144,0.7764218,0.8305109,0.8871466,0.9467818,
                   1681:     1.00999,1.077516,1.150349,1.229859,1.318011,1.417797,1.534121,1.67594,
                   1682:     1.862732,2.153875
                   1683: };
                   1684: static float d[31] = {
                   1685:     0.0,0.0,0.0,0.0,0.0,0.2636843,0.2425085,0.2255674,0.2116342,0.1999243,
                   1686:     0.1899108,0.1812252,0.1736014,0.1668419,0.1607967,0.1553497,0.1504094,
                   1687:     0.1459026,0.14177,0.1379632,0.1344418,0.1311722,0.128126,0.1252791,
                   1688:     0.1226109,0.1201036,0.1177417,0.1155119,0.1134023,0.1114027,0.1095039
                   1689: };
                   1690: static float t[31] = {
                   1691:     7.673828E-4,2.30687E-3,3.860618E-3,5.438454E-3,7.0507E-3,8.708396E-3,
                   1692:     1.042357E-2,1.220953E-2,1.408125E-2,1.605579E-2,1.81529E-2,2.039573E-2,
                   1693:     2.281177E-2,2.543407E-2,2.830296E-2,3.146822E-2,3.499233E-2,3.895483E-2,
                   1694:     4.345878E-2,4.864035E-2,5.468334E-2,6.184222E-2,7.047983E-2,8.113195E-2,
                   1695:     9.462444E-2,0.1123001,0.136498,0.1716886,0.2276241,0.330498,0.5847031
                   1696: };
                   1697: static float h[31] = {
                   1698:     3.920617E-2,3.932705E-2,3.951E-2,3.975703E-2,4.007093E-2,4.045533E-2,
                   1699:     4.091481E-2,4.145507E-2,4.208311E-2,4.280748E-2,4.363863E-2,4.458932E-2,
                   1700:     4.567523E-2,4.691571E-2,4.833487E-2,4.996298E-2,5.183859E-2,5.401138E-2,
                   1701:     5.654656E-2,5.95313E-2,6.308489E-2,6.737503E-2,7.264544E-2,7.926471E-2,
                   1702:     8.781922E-2,9.930398E-2,0.11556,0.1404344,0.1836142,0.2790016,0.7010474
                   1703: };
                   1704: static long i;
                   1705: static float snorm,u,s,ustar,aa,w,y,tt;
                   1706:     u = ranf();
                   1707:     s = 0.0;
                   1708:     if(u > 0.5) s = 1.0;
                   1709:     u += (u-s);
                   1710:     u = 32.0*u;
                   1711:     i = (long) (u);
                   1712:     if(i == 32) i = 31;
                   1713:     if(i == 0) goto S100;
                   1714: /*
                   1715:                                 START CENTER
                   1716: */
                   1717:     ustar = u-(float)i;
                   1718:     aa = *(a+i-1);
                   1719: S40:
                   1720:     if(ustar <= *(t+i-1)) goto S60;
                   1721:     w = (ustar-*(t+i-1))**(h+i-1);
                   1722: S50:
                   1723: /*
                   1724:                                 EXIT   (BOTH CASES)
                   1725: */
                   1726:     y = aa+w;
                   1727:     snorm = y;
                   1728:     if(s == 1.0) snorm = -y;
                   1729:     return snorm;
                   1730: S60:
                   1731: /*
                   1732:                                 CENTER CONTINUED
                   1733: */
                   1734:     u = ranf();
                   1735:     w = u*(*(a+i)-aa);
                   1736:     tt = (0.5*w+aa)*w;
                   1737:     goto S80;
                   1738: S70:
                   1739:     tt = u;
                   1740:     ustar = ranf();
                   1741: S80:
                   1742:     if(ustar > tt) goto S50;
                   1743:     u = ranf();
                   1744:     if(ustar >= u) goto S70;
                   1745:     ustar = ranf();
                   1746:     goto S40;
                   1747: S100:
                   1748: /*
                   1749:                                 START TAIL
                   1750: */
                   1751:     i = 6;
                   1752:     aa = *(a+31);
                   1753:     goto S120;
                   1754: S110:
                   1755:     aa += *(d+i-1);
                   1756:     i += 1;
                   1757: S120:
                   1758:     u += u;
                   1759:     if(u < 1.0) goto S110;
                   1760:     u -= 1.0;
                   1761: S140:
                   1762:     w = u**(d+i-1);
                   1763:     tt = (0.5*w+aa)*w;
                   1764:     goto S160;
                   1765: S150:
                   1766:     tt = u;
                   1767: S160:
                   1768:     ustar = ranf();
                   1769:     if(ustar > tt) goto S50;
                   1770:     u = ranf();
                   1771:     if(ustar >= u) goto S150;
                   1772:     u = ranf();
                   1773:     goto S140;
                   1774: }
                   1775: float fsign( float num, float sign )
                   1776: /* Transfers sign of argument sign to argument num */
                   1777: {
                   1778: if ( ( sign>0.0f && num<0.0f ) || ( sign<0.0f && num>0.0f ) )
                   1779:     return -num;
                   1780: else return num;
                   1781: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>