1
0

drand.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /* drand.c
  2. *
  3. * Pseudorandom number generator
  4. *
  5. *
  6. *
  7. * SYNOPSIS:
  8. *
  9. * double y, drand();
  10. *
  11. * drand( &y );
  12. *
  13. *
  14. *
  15. * DESCRIPTION:
  16. *
  17. * Yields a random number 1.0 <= y < 2.0.
  18. *
  19. * The three-generator congruential algorithm by Brian
  20. * Wichmann and David Hill (BYTE magazine, March, 1987,
  21. * pp 127-8) is used. The period, given by them, is
  22. * 6953607871644.
  23. *
  24. * Versions invoked by the different arithmetic compile
  25. * time options DEC, IBMPC, and MIEEE, produce
  26. * approximately the same sequences, differing only in the
  27. * least significant bits of the numbers. The UNK option
  28. * implements the algorithm as recommended in the BYTE
  29. * article. It may be used on all computers. However,
  30. * the low order bits of a double precision number may
  31. * not be adequately random, and may vary due to arithmetic
  32. * implementation details on different computers.
  33. *
  34. * The other compile options generate an additional random
  35. * integer that overwrites the low order bits of the double
  36. * precision number. This reduces the period by a factor of
  37. * two but tends to overcome the problems mentioned.
  38. *
  39. */
  40. /* Three-generator random number algorithm
  41. * of Brian Wichmann and David Hill
  42. * BYTE magazine, March, 1987 pp 127-8
  43. *
  44. * The period, given by them, is (p-1)(q-1)(r-1)/4 = 6.95e12.
  45. */
  46. #include "mconf.h"
  47. #ifdef ANSIPROT
  48. static int ranwh ( void );
  49. #else
  50. static int ranwh();
  51. #endif
  52. static int sx = 1;
  53. static int sy = 10000;
  54. static int sz = 3000;
  55. static union {
  56. double d;
  57. unsigned short s[4];
  58. } unkans;
  59. /* This function implements the three
  60. * congruential generators.
  61. */
  62. static int ranwh()
  63. {
  64. int r, s;
  65. /* sx = sx * 171 mod 30269 */
  66. r = sx/177;
  67. s = sx - 177 * r;
  68. sx = 171 * s - 2 * r;
  69. if( sx < 0 )
  70. sx += 30269;
  71. /* sy = sy * 172 mod 30307 */
  72. r = sy/176;
  73. s = sy - 176 * r;
  74. sy = 172 * s - 35 * r;
  75. if( sy < 0 )
  76. sy += 30307;
  77. /* sz = 170 * sz mod 30323 */
  78. r = sz/178;
  79. s = sz - 178 * r;
  80. sz = 170 * s - 63 * r;
  81. if( sz < 0 )
  82. sz += 30323;
  83. /* The results are in static sx, sy, sz. */
  84. return 0;
  85. }
  86. /* drand.c
  87. *
  88. * Random double precision floating point number between 1 and 2.
  89. *
  90. * C callable:
  91. * drand( &x );
  92. */
  93. int drand( a )
  94. double *a;
  95. {
  96. unsigned short r;
  97. #ifdef DEC
  98. unsigned short s, t;
  99. #endif
  100. /* This algorithm of Wichmann and Hill computes a floating point
  101. * result:
  102. */
  103. ranwh();
  104. unkans.d = sx/30269.0 + sy/30307.0 + sz/30323.0;
  105. r = unkans.d;
  106. unkans.d -= r;
  107. unkans.d += 1.0;
  108. /* if UNK option, do nothing further.
  109. * Otherwise, make a random 16 bit integer
  110. * to overwrite the least significant word
  111. * of unkans.
  112. */
  113. #ifdef UNK
  114. /* do nothing */
  115. #else
  116. ranwh();
  117. r = sx * sy + sz;
  118. #endif
  119. #ifdef DEC
  120. /* To make the numbers as similar as possible
  121. * in all arithmetics, the random integer has
  122. * to be inserted 3 bits higher up in a DEC number.
  123. * An alternative would be put it 3 bits lower down
  124. * in all the other number types.
  125. */
  126. s = unkans.s[2];
  127. t = s & 07; /* save these bits to put in at the bottom */
  128. s &= 0177770;
  129. s |= (r >> 13) & 07;
  130. unkans.s[2] = s;
  131. t |= r << 3;
  132. unkans.s[3] = t;
  133. #endif
  134. #ifdef IBMPC
  135. unkans.s[0] = r;
  136. #endif
  137. #ifdef MIEEE
  138. unkans.s[3] = r;
  139. #endif
  140. *a = unkans.d;
  141. return 0;
  142. }