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

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

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