Advertisement
Guest User

MS-RL System.Random Source Code

a guest
Aug 31st, 2013
178
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 7.45 KB | None | 0 0
  1. // ==++==
  2. //
  3. //   Copyright (c) Microsoft Corporation.  All rights reserved.
  4. //
  5. // ==--==
  6. /*============================================================
  7. **
  8. ** Class:  Random
  9. **
  10. **
  11. ** Purpose: A random number generator.
  12. **
  13. **
  14. ===========================================================*/
  15. namespace System {
  16.  
  17.     using System;
  18.     using System.Runtime;
  19.     using System.Runtime.CompilerServices;
  20.     using System.Globalization;
  21.     using System.Diagnostics.Contracts;
  22. [System.Runtime.InteropServices.ComVisible(true)]
  23.     [Serializable]
  24.     public class Random {
  25.       //
  26.       // Private Constants
  27.       //
  28.       private const int MBIG =  Int32.MaxValue;
  29.       private const int MSEED = 161803398;
  30.       private const int MZ = 0;
  31.  
  32.  
  33.       //
  34.       // Member Variables
  35.       //
  36.       private int inext;
  37.       private int inextp;
  38.       private int[] SeedArray = new int[56];
  39.  
  40.       //
  41.       // Public Constants
  42.       //
  43.  
  44.       //
  45.       // Native Declarations
  46.       //
  47.  
  48.       //
  49.       // Constructors
  50.       //
  51.  
  52.       public Random()
  53.         : this(Environment.TickCount) {
  54.       }
  55.  
  56.       public Random(int Seed) {
  57.         int ii;
  58.         int mj, mk;
  59.  
  60.         //Initialize our Seed array.
  61.         //This algorithm comes from Numerical Recipes in C (2nd Ed.)
  62.         int subtraction = (Seed == Int32.MinValue) ? Int32.MaxValue : Math.Abs(Seed);
  63.         mj = MSEED - subtraction;
  64.         SeedArray[55]=mj;
  65.         mk=1;
  66.         for (int i=1; i<55; i++) {  //Apparently the range [1..55] is special (Knuth) and so we're wasting the 0'th position.
  67.           ii = (21*i)%55;
  68.           SeedArray[ii]=mk;
  69.           mk = mj - mk;
  70.           if (mk<0) mk+=MBIG;
  71.           mj=SeedArray[ii];
  72.         }
  73.         for (int k=1; k<5; k++) {
  74.           for (int i=1; i<56; i++) {
  75.         SeedArray[i] -= SeedArray[1+(i+30)%55];
  76.         if (SeedArray[i]<0) SeedArray[i]+=MBIG;
  77.           }
  78.         }
  79.         inext=0;
  80.         inextp = 21;
  81.         Seed = 1;
  82.       }
  83.  
  84.       //
  85.       // Package Private Methods
  86.       //
  87.  
  88.       /*====================================Sample====================================
  89.       **Action: Return a new random number [0..1) and reSeed the Seed array.
  90.       **Returns: A double [0..1)
  91.       **Arguments: None
  92.       **Exceptions: None
  93.       ==============================================================================*/
  94. #if !FEATURE_CORECLR
  95.       [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
  96. #endif
  97.       protected virtual double Sample() {
  98.           //Including this division at the end gives us significantly improved
  99.           //random number distribution.
  100.           return (InternalSample()*(1.0/MBIG));
  101.       }
  102.  
  103.       private int InternalSample() {
  104.           int retVal;
  105.           int locINext = inext;
  106.           int locINextp = inextp;
  107.  
  108.           if (++locINext >=56) locINext=1;
  109.           if (++locINextp>= 56) locINextp = 1;
  110.  
  111.           retVal = SeedArray[locINext]-SeedArray[locINextp];
  112.  
  113.           if (retVal == MBIG) retVal--;
  114.           if (retVal<0) retVal+=MBIG;
  115.  
  116.           SeedArray[locINext]=retVal;
  117.  
  118.           inext = locINext;
  119.           inextp = locINextp;
  120.  
  121.           return retVal;
  122.       }
  123.  
  124.       //
  125.       // Public Instance Methods
  126.       //
  127.  
  128.  
  129.       /*=====================================Next=====================================
  130.       **Returns: An int [0..Int32.MaxValue)
  131.       **Arguments: None
  132.       **Exceptions: None.
  133.       ==============================================================================*/
  134. #if !FEATURE_CORECLR
  135.       [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
  136. #endif
  137.       public virtual int Next() {
  138.         return InternalSample();
  139.       }
  140.  
  141.       private double GetSampleForLargeRange() {
  142.           // The distribution of double value returned by Sample
  143.           // is not distributed well enough for a large range.
  144.           // If we use Sample for a range [Int32.MinValue..Int32.MaxValue)
  145.           // We will end up getting even numbers only.
  146.  
  147.           int result = InternalSample();
  148.           // Note we can't use addition here. The distribution will be bad if we do that.
  149.           bool negative = (InternalSample()%2 == 0) ? true : false;  // decide the sign based on second sample
  150.           if( negative) {
  151.               result = -result;
  152.           }
  153.           double d = result;
  154.           d += (Int32.MaxValue - 1); // get a number in range [0 .. 2 * Int32MaxValue - 1)
  155.           d /= 2*(uint)Int32.MaxValue - 1  ;
  156.           return d;
  157.       }
  158.  
  159.  
  160.       /*=====================================Next=====================================
  161.       **Returns: An int [minvalue..maxvalue)
  162.       **Arguments: minValue -- the least legal value for the Random number.
  163.       **           maxValue -- One greater than the greatest legal return value.
  164.       **Exceptions: None.
  165.       ==============================================================================*/
  166.       public virtual int Next(int minValue, int maxValue) {
  167.           if (minValue>maxValue) {
  168.               throw new ArgumentOutOfRangeException("minValue",Environment.GetResourceString("Argument_MinMaxValue", "minValue", "maxValue"));
  169.           }
  170.           Contract.EndContractBlock();
  171.  
  172.           long range = (long)maxValue-minValue;
  173.           if( range <= (long)Int32.MaxValue) {
  174.               return ((int)(Sample() * range) + minValue);
  175.           }
  176.           else {
  177.               return (int)((long)(GetSampleForLargeRange() * range) + minValue);
  178.           }
  179.       }
  180.  
  181.  
  182.       /*=====================================Next=====================================
  183.       **Returns: An int [0..maxValue)
  184.       **Arguments: maxValue -- One more than the greatest legal return value.
  185.       **Exceptions: None.
  186.       ==============================================================================*/
  187.       public virtual int Next(int maxValue) {
  188.           if (maxValue<0) {
  189.               throw new ArgumentOutOfRangeException("maxValue", Environment.GetResourceString("ArgumentOutOfRange_MustBePositive", "maxValue"));
  190.           }
  191.           Contract.EndContractBlock();
  192.           return (int)(Sample()*maxValue);
  193.       }
  194.  
  195.  
  196.       /*=====================================Next=====================================
  197.       **Returns: A double [0..1)
  198.       **Arguments: None
  199.       **Exceptions: None
  200.       ==============================================================================*/
  201. #if !FEATURE_CORECLR
  202.       [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
  203. #endif
  204.       public virtual double NextDouble() {
  205.         return Sample();
  206.       }
  207.  
  208.  
  209.       /*==================================NextBytes===================================
  210.       **Action:  Fills the byte array with random bytes [0..0x7f].  The entire array is filled.
  211.       **Returns:Void
  212.       **Arugments:  buffer -- the array to be filled.
  213.       **Exceptions: None
  214.       ==============================================================================*/
  215.       public virtual void NextBytes(byte [] buffer){
  216.         if (buffer==null) throw new ArgumentNullException("buffer");
  217.         Contract.EndContractBlock();
  218.         for (int i=0; i<buffer.Length; i++) {
  219.           buffer[i]=(byte)(InternalSample()%(Byte.MaxValue+1));
  220.         }
  221.       }
  222.     }
  223.  
  224.  
  225.  
  226. }
  227.  
  228. // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement