Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
2.4 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Basic random number generator
  4. //
  5. // $NoKeywords: $
  6. //===========================================================================//
  7. #include <time.h>
  8. #include "Random.h"
  9. // memdbgon must be the last include file in a .cpp file!!!
  10. #include "tier0/memdbgon.h"
  11. #define IA 16807
  12. #define IM 2147483647
  13. #define IQ 127773
  14. #define IR 2836
  15. #define NTAB 32
  16. #define NDIV (1+(IM-1)/NTAB)
  17. static long idum = 0;
  18. void SeedRandomNumberGenerator(long lSeed)
  19. {
  20. if (lSeed)
  21. {
  22. idum = lSeed;
  23. }
  24. else
  25. {
  26. idum = -time(NULL);
  27. }
  28. if (1000 < idum)
  29. {
  30. idum = -idum;
  31. }
  32. else if (-1000 < idum)
  33. {
  34. idum -= 22261048;
  35. }
  36. }
  37. long ran1(void)
  38. {
  39. int j;
  40. long k;
  41. static long iy=0;
  42. static long iv[NTAB];
  43. if (idum <= 0 || !iy)
  44. {
  45. if (-(idum) < 1) idum=1;
  46. else idum = -(idum);
  47. for (j=NTAB+7;j>=0;j--)
  48. {
  49. k=(idum)/IQ;
  50. idum=IA*(idum-k*IQ)-IR*k;
  51. if (idum < 0) idum += IM;
  52. if (j < NTAB) iv[j] = idum;
  53. }
  54. iy=iv[0];
  55. }
  56. k=(idum)/IQ;
  57. idum=IA*(idum-k*IQ)-IR*k;
  58. if (idum < 0) idum += IM;
  59. j=iy/NDIV;
  60. iy=iv[j];
  61. iv[j] = idum;
  62. return iy;
  63. }
  64. // fran1 -- return a random floating-point number on the interval [0,1)
  65. //
  66. #define AM (1.0/IM)
  67. #define EPS 1.2e-7
  68. #define RNMX (1.0-EPS)
  69. float fran1(void)
  70. {
  71. float temp = (float)AM*ran1();
  72. if (temp > RNMX) return (float)RNMX;
  73. else return temp;
  74. }
  75. #ifndef _XBOX
  76. float RandomFloat( float flLow, float flHigh )
  77. {
  78. if (idum == 0)
  79. {
  80. SeedRandomNumberGenerator(0);
  81. }
  82. float fl = fran1(); // float in [0,1)
  83. return (fl * (flHigh-flLow)) + flLow; // float in [low,high)
  84. }
  85. #endif
  86. long RandomLong( long lLow, long lHigh )
  87. {
  88. if (idum == 0)
  89. {
  90. SeedRandomNumberGenerator(0);
  91. }
  92. unsigned long maxAcceptable;
  93. unsigned long x = lHigh-lLow+1;
  94. unsigned long n;
  95. if (x <= 0 || MAX_RANDOM_RANGE < x-1)
  96. {
  97. return lLow;
  98. }
  99. // The following maps a uniform distribution on the interval [0,MAX_RANDOM_RANGE]
  100. // to a smaller, client-specified range of [0,x-1] in a way that doesn't bias
  101. // the uniform distribution unfavorably. Even for a worst case x, the loop is
  102. // guaranteed to be taken no more than half the time, so for that worst case x,
  103. // the average number of times through the loop is 2. For cases where x is
  104. // much smaller than MAX_RANDOM_RANGE, the average number of times through the
  105. // loop is very close to 1.
  106. //
  107. maxAcceptable = MAX_RANDOM_RANGE - ((MAX_RANDOM_RANGE+1) % x );
  108. do
  109. {
  110. n = ran1();
  111. } while (n > maxAcceptable);
  112. return lLow + (n % x);
  113. }