home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / PROG_C / SNIP9404.ZIP / RG_RAND.C < prev    next >
C/C++ Source or Header  |  1994-04-03  |  2KB  |  89 lines

  1. /*
  2. **  longrand() -- generate 2**31-2 random numbers
  3. **
  4. **  public domain by Ray Gardner
  5. ** 
  6. **  based on "Random Number Generators: Good Ones Are Hard to Find",
  7. **  S.K. Park and K.W. Miller, Communications of the ACM 31:10 (Oct 1988),
  8. **  and "Two Fast Implementations of the 'Minimal Standard' Random
  9. **  Number Generator", David G. Carta, Comm. ACM 33, 1 (Jan 1990), p. 87-88
  10. **
  11. **  linear congruential generator f(z) = 16807 z mod (2 ** 31 - 1)
  12. **
  13. **  uses L. Schrage's method to avoid overflow problems
  14. */
  15.  
  16. #define a 16807         /* multiplier */
  17. #define m 2147483647L   /* 2**31 - 1 */
  18. #define q 127773L       /* m div a */
  19. #define r 2836          /* m mod a */
  20.  
  21. long nextlongrand(long seed)
  22. {
  23.       unsigned long lo, hi;
  24.  
  25.       lo = a * (long)(seed & 0xFFFF);
  26.       hi = a * (long)((unsigned long)seed >> 16);
  27.       lo += (hi & 0x7FFF) << 16;
  28.       if (lo > m)
  29.       {
  30.             lo &= m;
  31.             ++lo;
  32.       }
  33.       lo += hi >> 15;
  34.       if (lo > m)
  35.       {
  36.             lo &= m;
  37.             ++lo;
  38.       }
  39.       return (long)lo;
  40. }
  41.  
  42. static long randomnum = 1;
  43.  
  44. long longrand(void)                     /* return next random long */
  45. {
  46.       randomnum = nextlongrand(randomnum);
  47.       return randomnum;
  48. }
  49.  
  50. void slongrand(unsigned long seed)      /* to seed it */
  51. {
  52.       randomnum = seed ? (seed & m) : 1;  /* nonzero seed */
  53. }
  54.  
  55.  
  56. #ifdef TEST
  57.  
  58. #include <stdio.h>
  59. #include <stdlib.h>
  60.  
  61. int main(int argc, char *argv[])
  62. {
  63.       long reps, k, num;
  64.       unsigned long seed;
  65.  
  66.       reps = 10000;
  67.       seed = 1;
  68.  
  69.       /*
  70.       ** correctness test: after 10000 reps starting with seed 1,
  71.       ** result should be 1043618065
  72.       */
  73.     
  74.       if (argc > 1)
  75.             reps = atol(argv[1]);
  76.       if (argc > 2)
  77.             seed = atol(argv[2]);
  78.  
  79.       printf("seed %ld for %ld reps...\n", seed, reps);
  80.       slongrand(seed);
  81.       for (k = 0; k < reps; ++k)
  82.             num = longrand();
  83.       printf("%ld\n", num);
  84.  
  85.       return 0;
  86. }
  87.  
  88. #endif
  89.