Annotation of capa/capa51/pProj/com.c, revision 1.2
1.2 ! albertel 1: /* library of functions for the Random number generator
! 2: Copyright (C) 1992-2000 Michigan State University
! 3:
! 4: The CAPA system is free software; you can redistribute it and/or
! 5: modify it under the terms of the GNU Library General Public License as
! 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
! 12: Library General Public License for more details.
! 13:
! 14: You should have received a copy of the GNU Library General Public
! 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,
! 17: Boston, MA 02111-1307, USA. */
! 18:
1.1 albertel 19: #include "ranlib.h"
20: #include <stdio.h>
21: #include <stdlib.h>
22: void advnst(long k)
23: /*
24: **********************************************************************
25: void advnst(long k)
26: ADV-a-N-ce ST-ate
27: Advances the state of the current generator by 2^K values and
28: resets the initial seed to that value.
29: This is a transcription from Pascal to Fortran of routine
30: Advance_State from the paper
31: L'Ecuyer, P. and Cote, S. "Implementing a Random Number Package
32: with Splitting Facilities." ACM Transactions on Mathematical
33: Software, 17:98-111 (1991)
34: Arguments
35: k -> The generator is advanced by2^K values
36: **********************************************************************
37: */
38: {
39: #define numg 32L
40: extern void gsrgs(long getset,long *qvalue);
41: extern void gscgn(long getset,long *g);
42: extern long Xm1,Xm2,Xa1,Xa2,Xcg1[],Xcg2[];
43: static long g,i,ib1,ib2;
44: static long qrgnin;
45: /*
46: Abort unless random number generator initialized
47: */
48: gsrgs(0L,&qrgnin);
49: if(qrgnin) goto S10;
50: puts(" ADVNST called before random generator initialized - ABORT");
51: exit(1);
52: S10:
53: gscgn(0L,&g);
54: ib1 = Xa1;
55: ib2 = Xa2;
56: for(i=1; i<=k; i++) {
57: ib1 = mltmod(ib1,ib1,Xm1);
58: ib2 = mltmod(ib2,ib2,Xm2);
59: }
60: setsd(mltmod(ib1,*(Xcg1+g-1),Xm1),mltmod(ib2,*(Xcg2+g-1),Xm2));
61: /*
62: NOW, IB1 = A1**K AND IB2 = A2**K
63: */
64: #undef numg
65: }
66: void getsd(long *iseed1,long *iseed2)
67: /*
68: **********************************************************************
69: void getsd(long *iseed1,long *iseed2)
70: GET SeeD
71: Returns the value of two integer seeds of the current generator
72: This is a transcription from Pascal to Fortran of routine
73: Get_State from the paper
74: L'Ecuyer, P. and Cote, S. "Implementing a Random Number Package
75: with Splitting Facilities." ACM Transactions on Mathematical
76: Software, 17:98-111 (1991)
77: Arguments
78: iseed1 <- First integer seed of generator G
79: iseed2 <- Second integer seed of generator G
80: **********************************************************************
81: */
82: {
83: #define numg 32L
84: extern void gsrgs(long getset,long *qvalue);
85: extern void gscgn(long getset,long *g);
86: extern long Xcg1[],Xcg2[];
87: static long g;
88: static long qrgnin;
89: /*
90: Abort unless random number generator initialized
91: */
92: gsrgs(0L,&qrgnin);
93: if(qrgnin) goto S10;
94: printf(
95: " GETSD called before random number generator initialized -- abort!\n");
96: exit(0);
97: S10:
98: gscgn(0L,&g);
99: *iseed1 = *(Xcg1+g-1);
100: *iseed2 = *(Xcg2+g-1);
101: #undef numg
102: }
103: long ignlgi(void)
104: /*
105: **********************************************************************
106: long ignlgi(void)
107: GeNerate LarGe Integer
108: Returns a random integer following a uniform distribution over
109: (1, 2147483562) using the current generator.
110: This is a transcription from Pascal to Fortran of routine
111: Random from the paper
112: L'Ecuyer, P. and Cote, S. "Implementing a Random Number Package
113: with Splitting Facilities." ACM Transactions on Mathematical
114: Software, 17:98-111 (1991)
115: **********************************************************************
116: */
117: {
118: #define numg 32L
119: extern void gsrgs(long getset,long *qvalue);
120: extern void gssst(long getset,long *qset);
121: extern void gscgn(long getset,long *g);
122: extern void inrgcm(void);
123: extern long Xm1,Xm2,Xa1,Xa2,Xcg1[],Xcg2[];
124: extern long Xqanti[];
125: static long ignlgi,curntg,k,s1,s2,z;
126: static long qqssd,qrgnin;
127: /*
128: IF THE RANDOM NUMBER PACKAGE HAS NOT BEEN INITIALIZED YET, DO SO.
129: IT CAN BE INITIALIZED IN ONE OF TWO WAYS : 1) THE FIRST CALL TO
130: THIS ROUTINE 2) A CALL TO SETALL.
131: */
132: gsrgs(0L,&qrgnin);
133: if(!qrgnin) inrgcm();
134: gssst(0,&qqssd);
135: if(!qqssd) setall(1234567890L,123456789L);
136: /*
137: Get Current Generator
138: */
139: gscgn(0L,&curntg);
140: s1 = *(Xcg1+curntg-1);
141: s2 = *(Xcg2+curntg-1);
142: k = s1/53668L;
143: s1 = Xa1*(s1-k*53668L)-k*12211;
144: if(s1 < 0) s1 += Xm1;
145: k = s2/52774L;
146: s2 = Xa2*(s2-k*52774L)-k*3791;
147: if(s2 < 0) s2 += Xm2;
148: *(Xcg1+curntg-1) = s1;
149: *(Xcg2+curntg-1) = s2;
150: z = s1-s2;
151: if(z < 1) z += (Xm1-1);
152: if(*(Xqanti+curntg-1)) z = Xm1-z;
153: ignlgi = z;
154: return ignlgi;
155: #undef numg
156: }
157: void initgn(long isdtyp)
158: /*
159: **********************************************************************
160: void initgn(long isdtyp)
161: INIT-ialize current G-e-N-erator
162: Reinitializes the state of the current generator
163: This is a transcription from Pascal to Fortran of routine
164: Init_Generator from the paper
165: L'Ecuyer, P. and Cote, S. "Implementing a Random Number Package
166: with Splitting Facilities." ACM Transactions on Mathematical
167: Software, 17:98-111 (1991)
168: Arguments
169: isdtyp -> The state to which the generator is to be set
170: isdtyp = -1 => sets the seeds to their initial value
171: isdtyp = 0 => sets the seeds to the first value of
172: the current block
173: isdtyp = 1 => sets the seeds to the first value of
174: the next block
175: **********************************************************************
176: */
177: {
178: #define numg 32L
179: extern void gsrgs(long getset,long *qvalue);
180: extern void gscgn(long getset,long *g);
181: extern long Xm1,Xm2,Xa1w,Xa2w,Xig1[],Xig2[],Xlg1[],Xlg2[],Xcg1[],Xcg2[];
182: static long g;
183: static long qrgnin;
184: /*
185: Abort unless random number generator initialized
186: */
187: gsrgs(0L,&qrgnin);
188: if(qrgnin) goto S10;
189: printf(
190: " INITGN called before random number generator initialized -- abort!\n");
191: exit(1);
192: S10:
193: gscgn(0L,&g);
194: if(-1 != isdtyp) goto S20;
195: *(Xlg1+g-1) = *(Xig1+g-1);
196: *(Xlg2+g-1) = *(Xig2+g-1);
197: goto S50;
198: S20:
199: if(0 != isdtyp) goto S30;
200: goto S50;
201: S30:
202: /*
203: do nothing
204: */
205: if(1 != isdtyp) goto S40;
206: *(Xlg1+g-1) = mltmod(Xa1w,*(Xlg1+g-1),Xm1);
207: *(Xlg2+g-1) = mltmod(Xa2w,*(Xlg2+g-1),Xm2);
208: goto S50;
209: S40:
210: printf("isdtyp not in range in INITGN");
211: exit(1);
212: S50:
213: *(Xcg1+g-1) = *(Xlg1+g-1);
214: *(Xcg2+g-1) = *(Xlg2+g-1);
215: #undef numg
216: }
217: void inrgcm(void)
218: /*
219: **********************************************************************
220: void inrgcm(void)
221: INitialize Random number Generator CoMmon
222: Function
223: Initializes common area for random number generator. This saves
224: the nuisance of a BLOCK DATA routine and the difficulty of
225: assuring that the routine is loaded with the other routines.
226: **********************************************************************
227: */
228: {
229: #define numg 32L
230: extern void gsrgs(long getset,long *qvalue);
231: extern long Xm1,Xm2,Xa1,Xa2,Xa1w,Xa2w,Xa1vw,Xa2vw;
232: extern long Xqanti[];
233: static long T1;
234: static long i;
235: /*
236: V=20; W=30;
237: A1W = MOD(A1**(2**W),M1) A2W = MOD(A2**(2**W),M2)
238: A1VW = MOD(A1**(2**(V+W)),M1) A2VW = MOD(A2**(2**(V+W)),M2)
239: If V or W is changed A1W, A2W, A1VW, and A2VW need to be recomputed.
240: An efficient way to precompute a**(2*j) MOD m is to start with
241: a and square it j times modulo m using the function MLTMOD.
242: */
243: Xm1 = 2147483563L;
244: Xm2 = 2147483399L;
245: Xa1 = 40014L;
246: Xa2 = 40692L;
247: Xa1w = 1033780774L;
248: Xa2w = 1494757890L;
249: Xa1vw = 2082007225L;
250: Xa2vw = 784306273L;
251: for(i=0; i<numg; i++) *(Xqanti+i) = 0;
252: T1 = 1;
253: /*
254: Tell the world that common has been initialized
255: */
256: gsrgs(1L,&T1);
257: #undef numg
258: }
259: void setall(long iseed1,long iseed2)
260: /*
261: **********************************************************************
262: void setall(long iseed1,long iseed2)
263: SET ALL random number generators
264: Sets the initial seed of generator 1 to ISEED1 and ISEED2. The
265: initial seeds of the other generators are set accordingly, and
266: all generators states are set to these seeds.
267: This is a transcription from Pascal to Fortran of routine
268: Set_Initial_Seed from the paper
269: L'Ecuyer, P. and Cote, S. "Implementing a Random Number Package
270: with Splitting Facilities." ACM Transactions on Mathematical
271: Software, 17:98-111 (1991)
272: Arguments
273: iseed1 -> First of two integer seeds
274: iseed2 -> Second of two integer seeds
275: **********************************************************************
276: */
277: {
278: #define numg 32L
279: extern void gsrgs(long getset,long *qvalue);
280: extern void gssst(long getset,long *qset);
281: extern void gscgn(long getset,long *g);
282: extern long Xm1,Xm2,Xa1vw,Xa2vw,Xig1[],Xig2[];
283: static long T1;
284: static long g,ocgn;
285: static long qrgnin;
286: T1 = 1;
287: /*
288: TELL IGNLGI, THE ACTUAL NUMBER GENERATOR, THAT THIS ROUTINE
289: HAS BEEN CALLED.
290: */
291: gssst(1,&T1);
292: gscgn(0L,&ocgn);
293: /*
294: Initialize Common Block if Necessary
295: */
296: gsrgs(0L,&qrgnin);
297: if(!qrgnin) inrgcm();
298: *Xig1 = iseed1;
299: *Xig2 = iseed2;
300: initgn(-1L);
301: for(g=2; g<=numg; g++) {
302: *(Xig1+g-1) = mltmod(Xa1vw,*(Xig1+g-2),Xm1);
303: *(Xig2+g-1) = mltmod(Xa2vw,*(Xig2+g-2),Xm2);
304: gscgn(1L,&g);
305: initgn(-1L);
306: }
307: gscgn(1L,&ocgn);
308: #undef numg
309: }
310: void setant(long qvalue)
311: /*
312: **********************************************************************
313: void setant(long qvalue)
314: SET ANTithetic
315: Sets whether the current generator produces antithetic values. If
316: X is the value normally returned from a uniform [0,1] random
317: number generator then 1 - X is the antithetic value. If X is the
318: value normally returned from a uniform [0,N] random number
319: generator then N - 1 - X is the antithetic value.
320: All generators are initialized to NOT generate antithetic values.
321: This is a transcription from Pascal to Fortran of routine
322: Set_Antithetic from the paper
323: L'Ecuyer, P. and Cote, S. "Implementing a Random Number Package
324: with Splitting Facilities." ACM Transactions on Mathematical
325: Software, 17:98-111 (1991)
326: Arguments
327: qvalue -> nonzero if generator G is to generating antithetic
328: values, otherwise zero
329: **********************************************************************
330: */
331: {
332: #define numg 32L
333: extern void gsrgs(long getset,long *qvalue);
334: extern void gscgn(long getset,long *g);
335: extern long Xqanti[];
336: static long g;
337: static long qrgnin;
338: /*
339: Abort unless random number generator initialized
340: */
341: gsrgs(0L,&qrgnin);
342: if(qrgnin) goto S10;
343: printf(
344: " SETANT called before random number generator initialized -- abort!\n");
345: exit(1);
346: S10:
347: gscgn(0L,&g);
348: Xqanti[g-1] = qvalue;
349: #undef numg
350: }
351: void setsd(long iseed1,long iseed2)
352: /*
353: **********************************************************************
354: void setsd(long iseed1,long iseed2)
355: SET S-ee-D of current generator
356: Resets the initial seed of the current generator to ISEED1 and
357: ISEED2. The seeds of the other generators remain unchanged.
358: This is a transcription from Pascal to Fortran of routine
359: Set_Seed from the paper
360: L'Ecuyer, P. and Cote, S. "Implementing a Random Number Package
361: with Splitting Facilities." ACM Transactions on Mathematical
362: Software, 17:98-111 (1991)
363: Arguments
364: iseed1 -> First integer seed
365: iseed2 -> Second integer seed
366: **********************************************************************
367: */
368: {
369: #define numg 32L
370: extern void gsrgs(long getset,long *qvalue);
371: extern void gscgn(long getset,long *g);
372: extern long Xig1[],Xig2[];
373: static long g;
374: static long qrgnin;
375: /*
376: Abort unless random number generator initialized
377: */
378: gsrgs(0L,&qrgnin);
379: if(qrgnin) goto S10;
380: printf(
381: " SETSD called before random number generator initialized -- abort!\n");
382: exit(1);
383: S10:
384: gscgn(0L,&g);
385: *(Xig1+g-1) = iseed1;
386: *(Xig2+g-1) = iseed2;
387: initgn(-1L);
388: #undef numg
389: }
390: long Xm1,Xm2,Xa1,Xa2,Xcg1[32],Xcg2[32],Xa1w,Xa2w,Xig1[32],Xig2[32],Xlg1[32],
391: Xlg2[32],Xa1vw,Xa2vw;
392: long Xqanti[32];
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>