lrand.c 1.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #include "all.h"
  2. /*
  3. * algorithm by
  4. * D. P. Mitchell & J. A. Reeds
  5. */
  6. enum {
  7. LEN = 607,
  8. TAP = 273,
  9. MASK = 0x7fffffffL,
  10. A = 48271,
  11. M = 2147483647,
  12. Q = 44488,
  13. R = 3399,
  14. };
  15. #define NORM (1.0/(1.0+MASK))
  16. static ulong rng_vec[LEN];
  17. static ulong* rng_tap = rng_vec;
  18. static ulong* rng_feed = 0;
  19. static Lock lk;
  20. static void
  21. isrand(long seed)
  22. {
  23. long lo, hi, x;
  24. int i;
  25. rng_tap = rng_vec;
  26. rng_feed = rng_vec+LEN-TAP;
  27. seed %= M;
  28. if(seed < 0)
  29. seed += M;
  30. if(seed == 0)
  31. seed = 89482311;
  32. x = seed;
  33. /*
  34. * Initialize by x[n+1] = 48271 * x[n] mod (2**31 - 1)
  35. */
  36. for(i = -20; i < LEN; i++) {
  37. hi = x / Q;
  38. lo = x % Q;
  39. x = A*lo - R*hi;
  40. if(x < 0)
  41. x += M;
  42. if(i >= 0)
  43. rng_vec[i] = x;
  44. }
  45. }
  46. void
  47. srand(long seed)
  48. {
  49. lock(&lk);
  50. isrand(seed);
  51. unlock(&lk);
  52. }
  53. long
  54. lrand(void)
  55. {
  56. ulong x;
  57. lock(&lk);
  58. rng_tap--;
  59. if(rng_tap < rng_vec) {
  60. if(rng_feed == 0) {
  61. isrand(1);
  62. rng_tap--;
  63. }
  64. rng_tap += LEN;
  65. }
  66. rng_feed--;
  67. if(rng_feed < rng_vec)
  68. rng_feed += LEN;
  69. x = (*rng_feed + *rng_tap) & MASK;
  70. *rng_feed = x;
  71. unlock(&lk);
  72. return x;
  73. }