home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / snip9707.zip / RG_RAND.C < prev    next >
C/C++ Source or Header  |  1997-07-05  |  2KB  |  91 lines

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