Leaked source code of windows server 2003
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.

170 lines
6.5 KiB

  1. #include "pch.hxx"
  2. #include "randpeak.hxx"
  3. /////////////////////////////////////////////////////////////////////////////
  4. // //
  5. // randpeak.c -- Functions to provide 32-bit random numbers, including //
  6. // a linear distribution (Random32 and RandomInRange), //
  7. // and a peaked distribution (RandomPeaked). //
  8. // //
  9. // Assumptions: ULONG is 32-bit unsigned data type, and //
  10. // BOOL is an integral boolean type. //
  11. // //
  12. // If MULTITHREADED is defined, critical //
  13. // section primitives must be defined and //
  14. // supported. //
  15. // //
  16. // Two's complement wraparound (mod 2^32) //
  17. // occurs on addition and multiplication //
  18. // where result is greater than (2^32-1) //
  19. // //
  20. // Author: Tom McGuire (tommcg), 03/29/94 //
  21. // //
  22. // (C) Copyright 1994, Microsoft Corporation //
  23. // //
  24. /////////////////////////////////////////////////////////////////////////////
  25. #define MULTIPLIER ((ULONG) 1664525 ) // From Knuth. Guarantees 2^32 non-
  26. // repeating values.
  27. ULONG ulInternalSeed;
  28. ULONG ulInternalAdder;
  29. #ifdef MULTITHREADED
  30. CRITICAL_SECTION ulInternalSeedCritSect;
  31. BOOL bInternalSeedCritSectInitialized;
  32. #endif
  33. ULONG BitReverse32( ULONG ulNumber ) {
  34. ULONG ulNewValue = 0;
  35. ULONG ulReadMask = 0x00000001;
  36. ULONG ulWriteBit = 0x80000000;
  37. do {
  38. if ( ulNumber & ulReadMask )
  39. ulNewValue |= ulWriteBit;
  40. ulReadMask <<= 1;
  41. ulWriteBit >>= 1;
  42. }
  43. while ( ulWriteBit );
  44. return ulNewValue;
  45. }
  46. void SeedRandom32( ULONG ulSeed ) {
  47. //
  48. // Assume this is called from a single thread only before any calls
  49. // to Random32(), RandomInRange(), or RandomPeaked().
  50. //
  51. #ifdef MULTITHREADED
  52. if ( ! bInternalSeedCritSectInitialized ) {
  53. InitializeCriticalSection( &ulInternalSeedCritSect );
  54. bInternalSeedCritSectInitialized = TRUE;
  55. }
  56. #endif
  57. ulInternalSeed = ulSeed;
  58. ulInternalAdder = ((( ulSeed ^ 0xFFFFFFFF ) | 0x00000001 ) & 0x7FFFFFFF );
  59. }
  60. ULONG Random32( void ) {
  61. ULONG ulRand;
  62. #ifdef MULTITHREADED
  63. EnterCriticalSection( &ulInternalSeedCritSect );
  64. #endif
  65. ulRand = ( ulInternalSeed * MULTIPLIER ) + ulInternalAdder;
  66. ulInternalSeed = ulRand;
  67. #ifdef MULTITHREADED
  68. LeaveCriticalSection( &ulInternalSeedCritSect );
  69. #endif
  70. return BitReverse32( ulRand );
  71. }
  72. ULONG RandomInRange( ULONG ulMinInclusive, ULONG ulMaxInclusive ) {
  73. ULONG ulRange = ( ulMaxInclusive - ulMinInclusive + 1 );
  74. ULONG ulRand = Random32();
  75. if ( ulRange )
  76. ulRand %= ulRange;
  77. return ( ulRand + ulMinInclusive );
  78. }
  79. ULONG RandomPeaked( ULONG ulMaxInclusive,
  80. ULONG ulPeakFrequency,
  81. ULONG ulPeakWidth,
  82. ULONG ulPeakDensity,
  83. ULONG ulPeakDecay ) {
  84. ULONG ulWhichPeak, ulPeakValue, ulRange, ulHigh, ulLow;
  85. ulWhichPeak = ( ulMaxInclusive / ulPeakFrequency );
  86. do {
  87. ulWhichPeak = RandomInRange( 0, ulWhichPeak );
  88. }
  89. while ( ulPeakDecay-- );
  90. ulPeakValue = ulWhichPeak * ulPeakFrequency;
  91. ulRange = ( ulPeakFrequency * ( ulPeakDensity + 1 )) / ( ulPeakDensity + 2 );
  92. while ( ulPeakDensity-- )
  93. ulRange = RandomInRange( ulPeakWidth / 2, ulRange );
  94. ulLow = ( ulPeakValue > ulRange ) ? ( ulPeakValue - ulRange ) : 0;
  95. ulHigh = ( ulPeakValue + ulRange );
  96. if ( ulHigh > ulMaxInclusive )
  97. ulHigh = ulMaxInclusive;
  98. ulPeakValue = RandomInRange( ulLow, ulHigh );
  99. return ulPeakValue;
  100. }
  101. /////////////////////////////////////////////////////////////////////////////
  102. // //
  103. // | Peaked Distribution | //
  104. // |_ | //
  105. // | \ | //
  106. // | \ _ | //
  107. // | \ / \ _ | //
  108. // | \ / \ / \ _ | //
  109. // | \ / \ / \ / \ _| //
  110. // | \_____/ \________/ \__ __/ \____________/ | //
  111. // |_______________________________________________________________| //
  112. // 0 P 2P nP Max //
  113. // //
  114. // The center of each peak occurs at ulPeakFreq intervals starting //
  115. // from zero, and the tops of the peaks are linear-distributed across //
  116. // ulPeakWidth (ie, +/- ulPeakWidth/2). ulPeakDensity controls the //
  117. // slope of the distribution off each peak with higher numbers causing //
  118. // steeper slopes (and hence wider, lower valleys). ulPeakDecay //
  119. // controls the declining peak-to-peak slope with higher numbers //
  120. // causing higher peaks near zero and lower peaks toward ulMax. //
  121. // Note that ulPeakDensity and ulPeakDecay are computationally //
  122. // expensive with higher values (they represent internal iteration //
  123. // counts), so moderate numbers such as 3-5 for ulPeakDensity and //
  124. // 1-2 for ulPeakDecay are recommended. //
  125. // //
  126. /////////////////////////////////////////////////////////////////////////////