lrand.c 1.1 KB

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