ldrand.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /* ldrand.c
  2. *
  3. * Pseudorandom number generator
  4. *
  5. *
  6. *
  7. * SYNOPSIS:
  8. *
  9. * double y;
  10. * int ldrand();
  11. *
  12. * ldrand( &y );
  13. *
  14. *
  15. *
  16. * DESCRIPTION:
  17. *
  18. * Yields a random number 1.0 <= y < 2.0.
  19. *
  20. * The three-generator congruential algorithm by Brian
  21. * Wichmann and David Hill (BYTE magazine, March, 1987,
  22. * pp 127-8) is used.
  23. *
  24. * Versions invoked by the different arithmetic compile
  25. * time options IBMPC, and MIEEE, produce the same sequences.
  26. *
  27. */
  28. #include <math.h>
  29. #ifdef ANSIPROT
  30. int ranwh ( void );
  31. #else
  32. int ranwh();
  33. #endif
  34. #ifdef UNK
  35. #undef UNK
  36. #if BIGENDIAN
  37. #define MIEEE
  38. #else
  39. #define IBMPC
  40. #endif
  41. #endif
  42. /* Three-generator random number algorithm
  43. * of Brian Wichmann and David Hill
  44. * BYTE magazine, March, 1987 pp 127-8
  45. *
  46. * The period, given by them, is (p-1)(q-1)(r-1)/4 = 6.95e12.
  47. */
  48. static int sx = 1;
  49. static int sy = 10000;
  50. static int sz = 3000;
  51. static union {
  52. long double d;
  53. unsigned short s[8];
  54. } unkans;
  55. /* This function implements the three
  56. * congruential generators.
  57. */
  58. int ranwh()
  59. {
  60. int r, s;
  61. /* sx = sx * 171 mod 30269 */
  62. r = sx/177;
  63. s = sx - 177 * r;
  64. sx = 171 * s - 2 * r;
  65. if( sx < 0 )
  66. sx += 30269;
  67. /* sy = sy * 172 mod 30307 */
  68. r = sy/176;
  69. s = sy - 176 * r;
  70. sy = 172 * s - 35 * r;
  71. if( sy < 0 )
  72. sy += 30307;
  73. /* sz = 170 * sz mod 30323 */
  74. r = sz/178;
  75. s = sz - 178 * r;
  76. sz = 170 * s - 63 * r;
  77. if( sz < 0 )
  78. sz += 30323;
  79. /* The results are in static sx, sy, sz. */
  80. return 0;
  81. }
  82. /* ldrand.c
  83. *
  84. * Random double precision floating point number between 1 and 2.
  85. *
  86. * C callable:
  87. * drand( &x );
  88. */
  89. int ldrand( a )
  90. long double *a;
  91. {
  92. unsigned short r;
  93. /* This algorithm of Wichmann and Hill computes a floating point
  94. * result:
  95. */
  96. ranwh();
  97. unkans.d = sx/30269.0L + sy/30307.0L + sz/30323.0L;
  98. r = unkans.d;
  99. unkans.d -= r;
  100. unkans.d += 1.0L;
  101. if( sizeof(long double) == 16 )
  102. {
  103. #ifdef MIEEE
  104. ranwh();
  105. r = sx * sy + sz;
  106. unkans.s[7] = r;
  107. ranwh();
  108. r = sx * sy + sz;
  109. unkans.s[6] = r;
  110. ranwh();
  111. r = sx * sy + sz;
  112. unkans.s[5] = r;
  113. ranwh();
  114. r = sx * sy + sz;
  115. unkans.s[4] = r;
  116. ranwh();
  117. r = sx * sy + sz;
  118. unkans.s[3] = r;
  119. #endif
  120. #ifdef IBMPC
  121. ranwh();
  122. r = sx * sy + sz;
  123. unkans.s[0] = r;
  124. ranwh();
  125. r = sx * sy + sz;
  126. unkans.s[1] = r;
  127. ranwh();
  128. r = sx * sy + sz;
  129. unkans.s[2] = r;
  130. ranwh();
  131. r = sx * sy + sz;
  132. unkans.s[3] = r;
  133. ranwh();
  134. r = sx * sy + sz;
  135. unkans.s[4] = r;
  136. #endif
  137. }
  138. else
  139. {
  140. #ifdef MIEEE
  141. ranwh();
  142. r = sx * sy + sz;
  143. unkans.s[5] = r;
  144. ranwh();
  145. r = sx * sy + sz;
  146. unkans.s[4] = r;
  147. #endif
  148. #ifdef IBMPC
  149. ranwh();
  150. r = sx * sy + sz;
  151. unkans.s[0] = r;
  152. ranwh();
  153. r = sx * sy + sz;
  154. unkans.s[1] = r;
  155. #endif
  156. }
  157. *a = unkans.d;
  158. return 0;
  159. }