gb_flip.w
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:11k
源码类别:

通讯编程

开发平台:

Visual C++

  1. % This file is part of the Stanford GraphBase (c) Stanford University 1993
  2. @i boilerplate.w %<< legal stuff: PLEASE READ IT BEFORE MAKING ANY CHANGES!
  3. deftitle{GB_,FLIP}
  4. hyphenation{semi-numer-ical}
  5. @* Introduction. This is {sc GB_,FLIP}, the module used by GraphBase
  6. programs to generate random numbers.
  7. To use the routines in this file, first call the function |gb_init_rand(seed)|.
  8. Subsequent uses of the macro |gb_next_rand()| will then return pseudo-random
  9. integers between 0 and $2^{31}-1$, inclusive.
  10. GraphBase programs are designed to produce identical results on almost
  11. all existing computers and operating systems.  An improved version of the
  12. portable subtractive method recommended in {sl Seminumerical Algorithms},
  13. Section~3.6, is used to generate random numbers in the routines below.
  14. The period length of the generated numbers is at least $2^{55}-1$, and
  15. it is in fact plausibly conjectured to be $2^{85}-2^{30}$ for all but
  16. at most one choice of the |seed| value.  The low-order bits of the
  17. generated numbers are just as random as the high-order bits.
  18. @ Changes might be needed when these routines are ported to different
  19. systems, because the programs have been written to be most efficient
  20. on binary computers that use two's complement notation. Almost all
  21. modern computers are based on two's complement arithmetic, but if you have a
  22. nonconformist machine you might have to revise the code in sections that
  23. are listed under `system dependencies' in the index.
  24. A validation program is provided so that installers can tell if
  25. {sc GB_,FLIP} is working properly. To make the test, simply run
  26. .{test_flip}.
  27. @(test_flip.c@>=
  28. #include <stdio.h>
  29. #include "gb_flip.h"   /* all users of {sc GB_,FLIP} should do this */
  30. @#@;
  31. int main()
  32. {@+long j;
  33.   gb_init_rand(-314159L);
  34.   if (gb_next_rand()!=119318998) {
  35.      fprintf(stderr,"Failure on the first try!n"); return -1;
  36.   }
  37.   for (j=1; j<=133; j++)
  38.     gb_next_rand();
  39.   if (gb_unif_rand(0x55555555L)!=748103812) {
  40.      fprintf(stderr,"Failure on the second try!n"); return -2;
  41.   }
  42.   fprintf(stderr,"OK, the gb_flip routines seem to work!n");
  43.   return 0;
  44. }
  45. @ The CEE/ code for {sc GB_,FLIP} doesn't have a main routine; it's just a
  46. bunch of subroutines to be incorporated into programs at a higher level
  47. via the system loading routine. Here is the general outline of .{gb_flip.c}:
  48. @p
  49. @<Private declarations@>@;
  50. @<External declarations@>@;
  51. @<External functions@>
  52. @* The subtractive method. If $m$ is any even number and if the
  53. numbers $a_0$, $a_1$, dots,~$a_{54}$ are not all even, then the numbers
  54. generated by the recurrence
  55. $$ a_n=(a_{n-55}-a_{n-24})bmod m $$
  56. have a period length of at least $2^{55}-1$, because the residues
  57. $a_nbmod2$ have a period of this length. Furthermore, the numbers 24 and~55
  58. in this recurrence are sufficiently large that deficiencies in randomness
  59. due to the simplicity of the recurrence are negligible in most applications.
  60. Here we take $m=2^{31}$ so that we get the full set of nonnegative numbers
  61. on a 32-bit computer. The recurrence is computed by maintaining an array
  62. of 55 values, $A[1]ldots A[55]$. We also set |A[0]=-1| to act as a sentinel.
  63. @<Private...@>=
  64. static long A[56] = {-1}; /* pseudo-random values */
  65. @ Every external variable should be declared twice in this .{CWEB}
  66. file: once for {sc GB_,FLIP} itself (the ``real'' declaration for
  67. storage allocation purposes), and once in .{gb_flip.h} (for
  68. cross-references by {sc GB_,FLIP} users).
  69. The pointer variable |gb_fptr| should not be mentioned explicitly
  70. by user routines. It is made public only for efficiency, so that the
  71. |gb_next_rand| macro can access the private |A| table.
  72. @<External declarations@>=
  73. long *gb_fptr=A; /* the next |A| value to be exported */
  74. @ The numbers generated by |gb_next_rand()| seem to be satisfactory for most
  75. purposes, but they do fail a stringent test called the ``birthday spacings
  76. test,'' devised by George Marsaglia. [See, for example, {sl Statistics and
  77. Probability Letters/ bf8} (1990), 35--39.] One way to get numbers that
  78. pass the birthday test is to discard half of the values, for example
  79. by changing `|gb_flip_cycle()|' to `|(gb_flip_cycle(),gb_flip_cycle())|'
  80. in the definition of |gb_next_rand()|. Users who wish to make such a change
  81. should define their own substitute macro.
  82. Incidentally, we hope that optimizing compilers are smart enough to
  83. do the right thing with |gb_next_rand|.
  84. @d gb_next_rand() (*gb_fptr>=0? *gb_fptr--: gb_flip_cycle())
  85. @(gb_flip.h@>=
  86. #define gb_next_rand() @tquad@>(*gb_fptr>=0?*gb_fptr--:gb_flip_cycle())
  87. extern long *gb_fptr; /* the next |A| value to be used */
  88. extern long gb_flip_cycle(); /* compute 55 more pseudo-random numbers */
  89. @ The user is not supposed to call |gb_flip_cycle| directly either.
  90. It is a routine invoked by the macro |gb_next_rand()| when |gb_fptr|
  91. points to the negative value in |A[0]|.
  92. The purpose of |gb_flip_cycle| is to do 55 more steps of the basic
  93. recurrence, at high speed, and to reset |gb_fptr|.
  94. The nonnegative remainder of $(x-y)$ divided by $2^{31}$ is computed here by
  95. doing a logical-and with the constant |0x7fffffff|. This technique
  96. doesn't work on computers that do not perform two's complement
  97. arithmetic. An alternative for such machines is to add the value
  98. $2^{30}$ twice to $(x-y)$, when $(x-y)$ turns out to be negative.
  99. Careful calculations are essential because the GraphBase results
  100. must be identical on all computer systems.
  101. @^system dependencies@>
  102. The sequence of random numbers returned by successive calls of |gb_next_rand()|
  103. isn't really $a_n$, $a_{n+1}$, dots, as defined by the basic recurrence above.
  104. Blocks of 55 consecutive values are essentially being ``flipped'' or
  105. ``reflected''---output in reverse order---because |gb_next_rand()|
  106. makes the value of |gb_fptr| decrease instead of increase.
  107. But such flips don't make the results any less random.
  108. @d mod_diff(x,y) (((x)-(y))&0x7fffffff) /* difference modulo $2^{31}$ */
  109. @<External functions@>=
  110. long gb_flip_cycle()
  111. {@+register long *ii, *jj;
  112.   for (ii=&A[1],jj=&A[32];jj<=&A[55];ii++,jj++)
  113.     *ii=mod_diff(*ii,*jj);
  114.   for (jj=&A[1];ii<=&A[55];ii++,jj++)
  115.     *ii=mod_diff(*ii,*jj);
  116.   gb_fptr=&A[54];
  117.   return A[55];
  118. }
  119.   
  120. @* Initialization. To get everything going, we use a scheme like that
  121. recommended in {sl Seminumerical Algorithms}, but revised so that the
  122. least significant bits of the starting values depend on the entire
  123. seed, not just on the seed's least significant bits.
  124. Notice that we jump around in the array by increments of 21, a number that is
  125. relatively prime to~55. Repeated skipping by steps of 21~mod~55 keeps the
  126. values we're computing spread out as far from each other as possible in the
  127. array, since 21, 34, and 55 are consecutive
  128. Fibonacci numbers (see the discussion of Fibonacci hashing in
  129. Section 6.4 of {sl Sorting and Searching/}). Our initialization mechanism
  130. would be rather poor if we didn't do something like that to disperse the values
  131. (see {sl Seminumerical Algorithms}, exercise 3.2.2--2).
  132. @<External f...@>=
  133. void gb_init_rand(seed)
  134.     long seed;
  135. {@+register long i;
  136.   register long prev=seed, next=1;
  137.   seed=prev=mod_diff(prev,0); /* strip off the sign */
  138.   A[55]=prev;
  139.   for (i=21; i; i=(i+21)%55) {
  140.     A[i]=next;
  141.     @<Compute a new |next| value, based on |next|, |prev|, and |seed|@>;
  142.     prev=A[i];
  143.   }
  144.   @<Get the array values ``warmed up''@>;
  145. }
  146. @ Incidentally, if .{test_flip} fails, the person debugging these
  147. routines will want to know some of the intermediate numbers computed
  148. during initialization.  The first nontrivial values calculated by
  149. |gb_init_rand| are |A[42]=2147326568|, |A[8]=1073977445|, and
  150. |A[29]=536517481|.  Once you get those right, the rest should be easy.
  151. An early version of this routine simply said `|seed>>1|' instead of making
  152. |seed| shift cyclically. This method had an interesting flaw:
  153. When the original |seed| was a number of the form $4s+1$, the first
  154. 54 elements $A[1]$, dots,~$A[54]$ were set to exactly the same values
  155. as when |seed| was $4s+2$. Therefore one out of every four seed values
  156. was effectively being wasted.
  157. @<Compute a new |next|...@>=
  158. next=mod_diff(prev,next);
  159. if (seed&1) seed=0x40000000+(seed>>1);
  160. else seed>>=1; /* cyclic shift right 1 */
  161. next=mod_diff(next,seed);
  162. @ After the first 55 values have been computed as a function of |seed|,
  163. they aren't random enough for us to start using them right away. For example,
  164. we have set |A[21]=1| in order to ensure that at least one starting value
  165. is an odd number. But once the sequence $a_n$ gets going far enough from
  166. its roots, the initial transients become imperceptible. Therefore we call
  167. |gb_flip_cycle| five times, effectively skipping past the first 275
  168. elements of the sequence; this has the desired effect. It also
  169. initializes |gb_fptr|.
  170. Note: It is possible to express the least significant bit of the
  171. generated numbers as a linear combination mod~2 of the 31 bits of
  172. |seed| and of the constant~1.  For example, the first generated number
  173. turns out to be odd if and only if
  174. $$s_{24}+s_{23}+s_{22}+s_{21}+s_{19}+s_{18}+s_{15}+s_{14}+s_{13}+s_{11}+
  175. s_{10}+s_{8}+s_{7}+s_{6}+s_{2}+s_{1}+s_{0}$$ is odd, when
  176. $|seed|=(s_{31}ldots s_1s_0)_2$.  We can represent this linear
  177. combination conveniently by the hexadecimal number |0x01ecedc7|; the
  178. .1 stands for $s_{24}$ and the final .7 stands for $s_2+s_1+s_0$.
  179. The first ten least-significant bits turn out to be respectively
  180. |0x01ecedc7|, |0xdbbdc362|, |0x400e0b06|, |0x0eb73780|, |0xda0d66ae|,
  181. |0x002b63bc|, |0xadb801ed|, |0x8077bbbc|, |0x803d9db5|, and
  182. |0x401a0eda| in this notation (using the sign bit to indicate cases
  183. when 1 must be added to the sum).
  184. We must admit that these ten 32-bit patterns do not look at all
  185. random; the number of .b's, .d's, and .0's is unusually high. (Before
  186. the ``warmup cycles,'' the patterns are even more regular.) This
  187. phenomenon eventually disappears, however, as the sequence proceeds;
  188. and it does not seem to imply any serious deficiency in practice, even
  189. at the beginning of the sequence, once we've done the warmup exercises.
  190. @<Get the array...@>=
  191. (void) gb_flip_cycle();
  192. (void) gb_flip_cycle();
  193. (void) gb_flip_cycle();
  194. (void) gb_flip_cycle();
  195. (void) gb_flip_cycle();
  196. @ @(gb_flip.h@>=
  197. extern void gb_init_rand();
  198. @* Uniform integers.
  199. Here is a simple routine that produces a uniform integer between
  200. 0 and~$m-1$, inclusive, when $m$ is any positive integer less than $2^{31}$.
  201. It avoids the bias toward small values that would occur if we simply
  202. calculated |gb_next_rand()%m|. (The bias is insignificant when |m| is
  203. small, but it can be serious when |m| is large. For example, if
  204. $mapprox 2^{32}!/3$, the simple remainder algorithm would give an answer
  205. less than $m/2$ about 2/3 of the time.)
  206. This routine consumes fewer than two random numbers, on the average,
  207. for any fixed~$m$.
  208. In the .{test_flip} program (|main|), this routine should compute |t=m|,
  209. then it should reject the values |r=2081307921|, 1621414801, and
  210. 1469108743 before returning the answer 748103812.
  211. @d two_to_the_31 ((unsigned long)0x80000000)
  212. @<External f...@>=
  213. long gb_unif_rand(m)
  214.     long m;
  215. {@+register unsigned long t=two_to_the_31-(two_to_the_31 % m);
  216.   register long r;
  217.   do@+{
  218.     r=gb_next_rand();
  219.   }@+while (t<=(unsigned long)r);
  220.   return r%m;
  221. }
  222. @ @(gb_flip.h@>=
  223. extern long gb_unif_rand();
  224. @* Index. Here is a list that shows where the identifiers of this program are
  225. defined and used.