📄 randomlib.c
字号:
deviate with DF-1 degrees of freedom plus the square of a normal deviate with mean XNONC and standard deviation 1.***********************************************************************/{static float gennch; if(!(df < 1.0 || xnonc < 0.0)) goto S10; mexPrintf("Value of DF: %16.6E Value of XNONC: %16.6E\n",df,xnonc); mexErrMsgTxt("Problem generating non-central chi-squared deviate"); exit(1);/* JJV changed code to call SGAMMA, SNORM directly */S10: if(df >= 1.000001) goto S20;/* * JJV case df == 1.0 * gennch = pow(gennor(sqrt(xnonc),1.0),2.0); <- OLD */ gennch = pow(snorm()+sqrt(xnonc),2.0); goto S30;S20:/* * JJV case df > 1.0 * gennch = genchi(df-1.0)+pow(gennor(sqrt(xnonc),1.0),2.0); <- OLD */ gennch = 2.0*sgamma((df-1.0)/2.0)+pow(snorm()+sqrt(xnonc),2.0);S30: return gennch;}float gennf(float dfn,float dfd,float xnonc)/*********************************************************************** float gennf(float dfn,float dfd,float xnonc) GENerate random deviate from the Noncentral F distribution Function Generates a random deviate from the noncentral F (variance ratio) distribution with DFN degrees of freedom in the numerator, and DFD degrees of freedom in the denominator, and noncentrality parameter XNONC. Arguments dfn --> Numerator degrees of freedom (Must be >= 1.0) dfd --> Denominator degrees of freedom (Must be positive) xnonc --> Noncentrality parameter (Must be nonnegative) Method Directly generates ratio of noncentral numerator chisquare variate to central denominator chisquare variate.***********************************************************************/{static float gennf,xden,xnum;static long qcond; /* JJV changed qcond, error message to allow dfn == 1.0 */ qcond = dfn < 1.0 || dfd <= 0.0 || xnonc < 0.0; if(!qcond) goto S10; mexPrintf("DFN value: %16.6E DFD value: %16.6E XNONC value: \n%16.6E\n",dfn,dfd,xnonc); mexErrMsgTxt("Problem generating non-central F-deviate"); exit(1);S10:/* * JJV changed the code to call SGAMMA and SNORM directly * GENNF = ( GENNCH( DFN, XNONC ) / DFN ) / ( GENCHI( DFD ) / DFD ) * xnum = gennch(dfn,xnonc)/dfn; <- OLD * xden = genchi(dfd)/dfd; <- OLD */ if(dfn >= 1.000001) goto S20;/* JJV case dfn == 1.0, dfn is counted as exactly 1.0 */ xnum = pow(snorm()+sqrt(xnonc),2.0); goto S30;S20:/* JJV case df > 1.0 */ xnum = (2.0*sgamma((dfn-1.0)/2.0)+pow(snorm()+sqrt(xnonc),2.0))/dfn;S30: xden = 2.0*sgamma(dfd/2.0)/dfd;/* * JJV changed constant to prevent underflow at compile time. * if(!(xden <= 9.999999999998E-39*xnum)) goto S40; */ if(!(xden <= 1.0E-37*xnum)) goto S40; mexPrintf(" Numerator %16.6E Denominator %16.6E\n",xnum,xden); mexErrMsgTxt("Problem generating non-central F-deviate");/* * JJV changed next 2 lines to reflect constant change above in the * JJV truncated value returned. * fputs(" GENNF returning 1.0E38\n",stderr); * gennf = 1.0E38; */ gennf = 1.0E37; goto S50;S40: gennf = xnum/xden;S50: return gennf;}float gennor(float av,float sd)/*********************************************************************** float gennor(float av,float sd) GENerate random deviate from a NORmal distribution Function Generates a single random deviate from a normal distribution with mean, AV, and standard deviation, SD. Arguments av --> Mean of the normal distribution. sd --> Standard deviation of the normal distribution. JJV (sd >= 0) Method Renames SNORM from TOMS as slightly modified by BWB to use RANF instead of SUNIF. For details see: Ahrens, J.H. and Dieter, U. Extensions of Forsythe's Method for Random Sampling from the Normal Distribution. Math. Comput., 27,124 (Oct. 1973), 927 - 937.***********************************************************************/{static float gennor;/* JJV added argument checker */ if(sd >= 0.0) goto S10; mexPrintf(" Value of SD: %16.6E\n",sd); mexErrMsgTxt("Problem generating normal deviate"); exit(1);S10: gennor = sd*snorm()+av; return gennor;}void genprm(long *iarray,int larray)/*********************************************************************** void genprm(long *iarray,int larray) GENerate random PeRMutation of iarray Arguments iarray <--> On output IARRAY is a random permutation of its value on input larray <--> Length of IARRAY***********************************************************************/{static long i,itmp,iwhich,D1,D2; for(i=1,D1=1,D2=(larray-i+D1)/D1; D2>0; D2--,i+=D1) { iwhich = ignuin(i,larray); itmp = *(iarray+iwhich-1); *(iarray+iwhich-1) = *(iarray+i-1); *(iarray+i-1) = itmp; }}float genunf(float low,float high)/*********************************************************************** float genunf(float low,float high) GeNerate Uniform Real between LOW and HIGH Function Generates a real uniformly distributed between LOW and HIGH. Arguments low --> Low bound (exclusive) on real value to be generated high --> High bound (exclusive) on real value to be generated***********************************************************************/{static float genunf; if(!(low > high)) goto S10; mexPrintf("LOW > HIGH in GENUNF: LOW %16.6E HIGH: %16.6E\n",low,high); mexErrMsgTxt("Problem generating uniform deviate"); exit(1);S10: genunf = low+(high-low)*ranf(); return genunf;}void gscgn(long getset,long *g)/*********************************************************************** void gscgn(long getset,long *g) Get/Set GeNerator Gets or returns in G the number of the current generator Arguments getset --> 0 Get 1 Set g <-- Number of the current random number generator (1..32)***********************************************************************/{#define numg 32Lstatic long curntg = 1; if(getset == 0) *g = curntg; else { if(*g < 0 || *g > numg) { exit(0); } curntg = *g; }#undef numg}void gsrgs(long getset,long *qvalue)/*********************************************************************** void gsrgs(long getset,long *qvalue) Get/Set Random Generators Set Gets or sets whether random generators set (initialized). Initially (data statement) state is not set If getset is 1 state is set to qvalue If getset is 0 state returned in qvalue***********************************************************************/{static long qinit = 0; if(getset == 0) *qvalue = qinit; else qinit = *qvalue;}void gssst(long getset,long *qset)/*********************************************************************** void gssst(long getset,long *qset) Get or Set whether Seed is Set Initialize to Seed not Set If getset is 1 sets state to Seed Set If getset is 0 returns T in qset if Seed Set Else returns F in qset***********************************************************************/{static long qstate = 0; if(getset != 0) qstate = 1; else *qset = qstate;}long ignbin(long n,float pp)/*********************************************************************** long ignbin(long n,float pp) GENerate BINomial random deviate Function Generates a single random deviate from a binomial distribution whose number of trials is N and whose probability of an event in each trial is P. Arguments n --> The number of trials in the binomial distribution from which a random deviate is to be generated. JJV (N >= 0) pp --> The probability of an event in each trial of the binomial distribution from which a random deviate is to be generated. JJV (0.0 <= PP <= 1.0) ignbin <-- A random deviate yielding the number of events from N independent trials, each of which has a probability of event P. Method This is algorithm BTPE from: Kachitvichyanukul, V. and Schmeiser, B. W. Binomial Random Variate Generation. Communications of the ACM, 31, 2 (February, 1988) 216.********************************************************************** SUBROUTINE BTPEC(N,PP,ISEED,JX) BINOMIAL RANDOM VARIATE GENERATOR MEAN .LT. 30 -- INVERSE CDF MEAN .GE. 30 -- ALGORITHM BTPE: ACCEPTANCE-REJECTION VIA FOUR REGION COMPOSITION. THE FOUR REGIONS ARE A TRIANGLE (SYMMETRIC IN THE CENTER), A PAIR OF PARALLELOGRAMS (ABOVE THE TRIANGLE), AND EXPONENTIAL LEFT AND RIGHT TAILS. BTPE REFERS TO BINOMIAL-TRIANGLE-PARALLELOGRAM-EXPONENTIAL. BTPEC REFERS TO BTPE AND "COMBINED." THUS BTPE IS THE RESEARCH AND BTPEC IS THE IMPLEMENTATION OF A COMPLETE USABLE ALGORITHM. REFERENCE: VORATAS KACHITVICHYANUKUL AND BRUCE SCHMEISER, "BINOMIAL RANDOM VARIATE GENERATION," COMMUNICATIONS OF THE ACM, FORTHCOMING WRITTEN: SEPTEMBER 1980. LAST REVISED: MAY 1985, JULY 1987 REQUIRED SUBPROGRAM: RAND() -- A UNIFORM (0,1) RANDOM NUMBER GENERATOR ARGUMENTS N : NUMBER OF BERNOULLI TRIALS (INPUT) PP : PROBABILITY OF SUCCESS IN EACH TRIAL (INPUT) ISEED: RANDOM NUMBER SEED (INPUT AND OUTPUT) JX: RANDOMLY GENERATED OBSERVATION (OUTPUT) VARIABLES PSAVE: VALUE OF PP FROM THE LAST CALL TO BTPEC NSAVE: VALUE OF N FROM THE LAST CALL TO BTPEC XNP: VALUE OF THE MEAN FROM THE LAST CALL TO BTPEC P: PROBABILITY USED IN THE GENERATION PHASE OF BTPEC FFM: TEMPORARY VARIABLE EQUAL TO XNP + P M: INTEGER VALUE OF THE CURRENT MODE FM: FLOATING POINT VALUE OF THE CURRENT MODE XNPQ: TEMPORARY VARIABLE USED IN SETUP AND SQUEEZING STEPS P1: AREA OF THE TRIANGLE C: HEIGHT OF THE PARALLELOGRAMS XM: CENTER OF THE TRIANGLE XL: LEFT END OF THE TRIANGLE XR: RIGHT END OF THE TRIANGLE AL: TEMPORARY VARIABLE XLL: RATE FOR THE LEFT EXPONENTIAL TAIL XLR: RATE FOR THE RIGHT EXPONENTIAL TAIL P2: AREA OF THE PARALLELOGRAMS P3: AREA OF THE LEFT EXPONENTIAL TAIL P4: AREA OF THE RIGHT EXPONENTIAL TAIL U: A U(0,P4) RANDOM VARIATE USED FIRST TO SELECT ONE OF THE FOUR REGIONS AND THEN CONDITIONALLY TO GENERATE A VALUE FROM THE REGION V: A U(0,1) RANDOM NUMBER USED TO GENERATE THE RANDOM VALUE (REGION 1) OR TRANSFORMED INTO THE VARIATE TO ACCEPT OR REJECT THE CANDIDATE VALUE IX: INTEGER CANDIDATE VALUE X: PRELIMINARY CONTINUOUS CANDIDATE VALUE IN REGION 2 LOGIC AND A FLOATING POINT IX IN THE ACCEPT/REJECT LOGIC K: ABSOLUTE VALUE OF (IX-M) F: THE HEIGHT OF THE SCALED DENSITY FUNCTION USED IN THE ACCEPT/REJECT DECISION WHEN BOTH M AND IX ARE SMALL ALSO USED IN THE INVERSE TRANSFORMATION R: THE RATIO P/Q G: CONSTANT USED IN CALCULATION OF PROBABILITY MP: MODE PLUS ONE, THE LOWER INDEX FOR EXPLICIT CALCULATION OF F WHEN IX IS GREATER THAN M IX1: CANDIDATE VALUE PLUS ONE, THE LOWER INDEX FOR EXPLICIT CALCULATION OF F WHEN IX IS LESS THAN M I: INDEX FOR EXPLICIT CALCULATION OF F FOR BTPE AMAXP: MAXIMUM ERROR OF THE LOGARITHM OF NORMAL BOUND YNORM: LOGARITHM OF NORMAL BOUND ALV: NATURAL LOGARITHM OF THE ACCEPT/REJECT VARIATE V X1,F1,Z,W,Z2,X2,F2, AND W2 ARE TEMPORARY VARIABLES TO BE USED IN THE FINAL ACCEPT/REJECT TEST QN: PROBABILITY OF NO SUCCESS IN N TRIALS REMARK IX AND JX COULD LOGICALLY BE THE SAME VARIABLE, WHICH WOULD SAVE A MEMORY POSITION AND A LINE OF CODE. HOWEVER, SOME COMPILERS (E.G.,CDC MNF) OPTIMIZE BETTER WHEN THE ARGUMENTS ARE NOT INVOLVED. ISEED NEEDS TO BE DOUBLE PRECISION IF THE IMSL ROUTINE GGUBFS IS USED TO GENERATE UNIFORM RANDOM NUMBER, OTHERWISE TYPE OF ISEED SHOULD BE DICTATED BY THE UNIFORM GENERATOR***************************************************************************DETERMINE APPROPRIATE ALGORITHM AND WHETHER SETUP IS NECESSARY*/{/* JJV changed initial values to ridiculous values */static float psave = -1.0E37;static long nsave = -214748365;static long ignbin,i,ix,ix1,k,m,mp,T1;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, x2,xl,xll,xlr,xm,xnp,xnpq,xr,ynorm,z,z2; if(pp != psave) goto S10; if(n != nsave) goto S20; if(xnp < 30.0) goto S150; goto S30;S10:/******SETUP, PERFORM ONLY WHEN PARAMETERS CHANGEJJV added checks to ensure 0.0 <= PP <= 1.0*/ if(pp < 0.0F) ftnstop("PP < 0.0 in IGNBIN"); if(pp > 1.0F) ftnstop("PP > 1.0 in IGNBIN"); psave = pp; p = min(psave,1.0-psave); q = 1.0-p;S20:/*JJV added check to ensure N >= 0*/ if(n < 0L) ftnstop("N < 0 in IGNBIN"); xnp = n*p; nsave = n; if(xnp < 30.0) goto S140; ffm = xnp+p; m = ffm; fm = m; xnpq = xnp*q; p1 = (long) (2.195*sqrt(xnpq)-4.6*q)+0.5; xm = fm+0.5; xl = xm-p1; xr = xm+p1; c = 0.134+20.5/(15.3+fm); al = (ffm-xl)/(ffm-xl*p); xll = al*(1.0+0.5*al); al = (xr-ffm)/(xr*q); xlr = al*(1.0+0.5*al); p2 = p1*(1.0+c+c); p3 = p2+c/xll; p4 = p3+c/xlr;S30:/******GENERATE VARIATE*/ u = ranf()*p4; v = ranf();/* TRIANGULAR REGION*/ if(u > p1) goto S40; ix = xm-p1*v+u; goto S170;S40:/* PARALLELOGRAM REGION*/ if(u > p2) goto S50; x = xl+(u-p1)/c; v = v*c+1.0-ABS(xm-x)/p1; if(v > 1.0 || v <= 0.0) goto S30; ix = x; goto S70;S50:/* LEFT TAIL*/ if(u > p3) goto S60; ix = xl+log(v)/xll; if(ix < 0) goto S30; v *= ((u-p2)*xll); goto S70;S60:/* RIGHT TAIL*/ ix = xr-log(v)/xlr; if(ix > n) goto S30; v *= ((u-p3)*xlr);S70:/******DETERMINE APPROPRIATE WAY TO PERFORM ACCEPT/REJECT TEST*/ k = ABS(ix-m); if(k > 20 && k < xnpq/2-1) goto S130;/* EXPLICIT EVALUATION*/ f = 1.0; r = p/q; g = (n+1)*r; T1 = m-ix; if(T1 < 0) goto S80; else if(T1 == 0) goto S120; else goto S100;S80: mp = m+1; for(i=mp; i<=ix; i++) f *= (g/i-r); goto S120;S100: ix1 = ix+1; for(i=ix1; i<=m; i++) f /= (g/i-r);S120: if(v <= f) goto S170; goto S30;S130:/* SQUEEZING USING UPPER AND LOWER BOUNDS ON ALOG(F(X))*/ amaxp = k/xnpq*((k*(k/3.0+0.625)+0.1666666666666)/xnpq+0.5); ynorm = -(k*k/(2.0*xnpq));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -