summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/Random.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/src/System/Random.cs')
-rw-r--r--src/mscorlib/src/System/Random.cs74
1 files changed, 55 insertions, 19 deletions
diff --git a/src/mscorlib/src/System/Random.cs b/src/mscorlib/src/System/Random.cs
index adede6a101..f5941d6718 100644
--- a/src/mscorlib/src/System/Random.cs
+++ b/src/mscorlib/src/System/Random.cs
@@ -11,13 +11,14 @@
**
===========================================================*/
namespace System {
-
+
using System;
using System.Runtime;
using System.Runtime.CompilerServices;
using System.Globalization;
using System.Diagnostics.Contracts;
-[System.Runtime.InteropServices.ComVisible(true)]
+
+ [System.Runtime.InteropServices.ComVisible(true)]
[Serializable]
public class Random {
//
@@ -46,13 +47,19 @@ namespace System {
//
// Constructors
//
-
+
+ /*=========================================================================================
+ **Action: Initializes a new instance of the Random class, using a default seed value
+ ===========================================================================================*/
public Random()
- : this(Environment.TickCount) {
+ : this(GenerateSeed()) {
}
-
+
+ /*=========================================================================================
+ **Action: Initializes a new instance of the Random class, using a specified seed value
+ ===========================================================================================*/
public Random(int Seed) {
- int ii;
+ int ii = 0;
int mj, mk;
//Initialize our Seed array.
@@ -61,7 +68,7 @@ namespace System {
SeedArray[55]=mj;
mk=1;
for (int i=1; i<55; i++) { //Apparently the range [1..55] is special (Knuth) and so we're wasting the 0'th position.
- ii = (21*i)%55;
+ if ((ii += 21) >= 55) ii -= 55;
SeedArray[ii]=mk;
mk = mj - mk;
if (mk<0) mk+=MBIG;
@@ -69,19 +76,21 @@ namespace System {
}
for (int k=1; k<5; k++) {
for (int i=1; i<56; i++) {
- SeedArray[i] -= SeedArray[1+(i+30)%55];
- if (SeedArray[i]<0) SeedArray[i]+=MBIG;
+ int n = i + 30;
+ if (n >= 55) n -= 55;
+ SeedArray[i] -= SeedArray[1 + n];
+ if (SeedArray[i]<0) SeedArray[i]+=MBIG;
}
}
inext=0;
inextp = 21;
Seed = 1;
}
-
+
//
// Package Private Methods
//
-
+
/*====================================Sample====================================
**Action: Return a new random number [0..1) and reSeed the Seed array.
**Returns: A double [0..1)
@@ -115,11 +124,41 @@ namespace System {
return retVal;
}
+
+ [ThreadStatic]
+ private static Random t_threadRandom;
+ private static readonly Random s_globalRandom = new Random(GenerateGlobalSeed());
+
+ /*=====================================GenerateSeed=====================================
+ **Returns: An integer that can be used as seed values for consecutively
+ creating lots of instances on the same thread within a short period of time.
+ ========================================================================================*/
+ private static int GenerateSeed() {
+ Random rnd = t_threadRandom;
+ if (rnd == null) {
+ int seed;
+ lock (s_globalRandom) {
+ seed = s_globalRandom.Next();
+ }
+ rnd = new Random(seed);
+ t_threadRandom = rnd;
+ }
+ return rnd.Next();
+ }
+
+ /*==================================GenerateGlobalSeed====================================
+ **Action: Creates a number to use as global seed.
+ **Returns: An integer that is safe to use as seed values for thread-local seed generators.
+ ==========================================================================================*/
+ private static int GenerateGlobalSeed() {
+ return Guid.NewGuid().GetHashCode();
+ }
+
//
// Public Instance Methods
//
-
-
+
+
/*=====================================Next=====================================
**Returns: An int [0..Int32.MaxValue)
**Arguments: None
@@ -156,7 +195,7 @@ namespace System {
==============================================================================*/
public virtual int Next(int minValue, int maxValue) {
if (minValue>maxValue) {
- throw new ArgumentOutOfRangeException("minValue",Environment.GetResourceString("Argument_MinMaxValue", "minValue", "maxValue"));
+ throw new ArgumentOutOfRangeException(nameof(minValue),Environment.GetResourceString("Argument_MinMaxValue", nameof(minValue), nameof(maxValue)));
}
Contract.EndContractBlock();
@@ -177,7 +216,7 @@ namespace System {
==============================================================================*/
public virtual int Next(int maxValue) {
if (maxValue<0) {
- throw new ArgumentOutOfRangeException("maxValue", Environment.GetResourceString("ArgumentOutOfRange_MustBePositive", "maxValue"));
+ throw new ArgumentOutOfRangeException(nameof(maxValue), Environment.GetResourceString("ArgumentOutOfRange_MustBePositive", nameof(maxValue)));
}
Contract.EndContractBlock();
return (int)(Sample()*maxValue);
@@ -201,14 +240,11 @@ namespace System {
**Exceptions: None
==============================================================================*/
public virtual void NextBytes(byte [] buffer){
- if (buffer==null) throw new ArgumentNullException("buffer");
+ if (buffer==null) throw new ArgumentNullException(nameof(buffer));
Contract.EndContractBlock();
for (int i=0; i<buffer.Length; i++) {
buffer[i]=(byte)(InternalSample()%(Byte.MaxValue+1));
}
}
}
-
-
-
}