drand.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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. #include "mconf.h"
  41. /* Three-generator random number algorithm
  42. * of Brian Wichmann and David Hill
  43. * BYTE magazine, March, 1987 pp 127-8
  44. *
  45. * The period, given by them, is (p-1)(q-1)(r-1)/4 = 6.95e12.
  46. */
  47. static int sx = 1;
  48. static int sy = 10000;
  49. static int sz = 3000;
  50. static union {
  51. double d;
  52. unsigned short s[4];
  53. } unkans;
  54. /* This function implements the three
  55. * congruential generators.
  56. */
  57. int ranwh()
  58. {
  59. int r, s;
  60. /* sx = sx * 171 mod 30269 */
  61. r = sx/177;
  62. s = sx - 177 * r;
  63. sx = 171 * s - 2 * r;
  64. if( sx < 0 )
  65. sx += 30269;
  66. /* sy = sy * 172 mod 30307 */
  67. r = sy/176;
  68. s = sy - 176 * r;
  69. sy = 172 * s - 35 * r;
  70. if( sy < 0 )
  71. sy += 30307;
  72. /* sz = 170 * sz mod 30323 */
  73. r = sz/178;
  74. s = sz - 178 * r;
  75. sz = 170 * s - 63 * r;
  76. if( sz < 0 )
  77. sz += 30323;
  78. /* The results are in static sx, sy, sz. */
  79. return 0;
  80. }
  81. /* drand.c
  82. *
  83. * Random double precision floating point number between 1 and 2.
  84. *
  85. * C callable:
  86. * drand( &x );
  87. */
  88. int drand( a )
  89. double *a;
  90. {
  91. unsigned short r;
  92. #ifdef DEC
  93. unsigned short s, t;
  94. #endif
  95. /* This algorithm of Wichmann and Hill computes a floating point
  96. * result:
  97. */
  98. ranwh();
  99. unkans.d = sx/30269.0 + sy/30307.0 + sz/30323.0;
  100. r = unkans.d;
  101. unkans.d -= r;
  102. unkans.d += 1.0;
  103. /* if UNK option, do nothing further.
  104. * Otherwise, make a random 16 bit integer
  105. * to overwrite the least significant word
  106. * of unkans.
  107. */
  108. #ifdef UNK
  109. /* do nothing */
  110. #else
  111. ranwh();
  112. r = sx * sy + sz;
  113. #endif
  114. #ifdef DEC
  115. /* To make the numbers as similar as possible
  116. * in all arithmetics, the random integer has
  117. * to be inserted 3 bits higher up in a DEC number.
  118. * An alternative would be put it 3 bits lower down
  119. * in all the other number types.
  120. */
  121. s = unkans.s[2];
  122. t = s & 07; /* save these bits to put in at the bottom */
  123. s &= 0177770;
  124. s |= (r >> 13) & 07;
  125. unkans.s[2] = s;
  126. t |= r << 3;
  127. unkans.s[3] = t;
  128. #endif
  129. #ifdef IBMPC
  130. unkans.s[0] = r;
  131. #endif
  132. #ifdef MIEEE
  133. unkans.s[3] = r;
  134. #endif
  135. *a = unkans.d;
  136. return 0;
  137. }