PageRenderTime 83ms CodeModel.GetById 40ms app.highlight 7ms RepoModel.GetById 34ms app.codeStats 0ms

/Utilities/Math/Random250Algorithm.cs

#
C# | 173 lines | 102 code | 24 blank | 47 comment | 10 complexity | db5f855e4b5dab8266c3555c6916faa1 MD5 | raw file
  1using System;
  2using NUnit.Framework;
  3
  4namespace Delta.Utilities.Math
  5{
  6	/// <summary>
  7	/// This class represents an implementation of the R250 algorith comes
  8	/// originally from the "Random isn't Really Random -- C# Random Number
  9	/// Generation" article by Matthew Cochran. For more details see:
 10	/// http://www.shadlen.org/ichbin/random/generators.htm#r250
 11	/// http://www.c-sharpcorner.com/UploadFile/rmcochran/random07172006175425PM/random.aspx
 12	/// <para />
 13	/// Implements the GFSR: x_n = x_(n-P) ^ x_(n-Q), which has period 2^P - 1.
 14	/// </summary>
 15	public class Random250Algorithm : RandomBase
 16	{
 17		#region Constants
 18		/// <summary>
 19		/// P, used as degree of larger term (250 or 7)
 20		/// </summary>
 21		private static readonly int P = 250;
 22
 23		/// <summary>
 24		/// Q, used as degree of smaller term (103 or 4)
 25		/// </summary>
 26		private static readonly int Q = 103;
 27
 28		/// <summary>
 29		/// L, used as word length (32 or 3)
 30		/// </summary>
 31		private static readonly int L = 32;
 32		#endregion
 33
 34		#region Private
 35
 36		#region x (Private)
 37		/// <summary>
 38		/// X array with all the random values.
 39		/// </summary>
 40		private readonly uint[] x;
 41		#endregion
 42
 43		#region pointer (Private)
 44		/// <summary>
 45		/// Pointer to element we are working on.
 46		/// </summary>
 47		private int pointer;
 48		#endregion
 49
 50		#endregion
 51
 52		#region Constructors
 53		/// <summary>
 54		/// Create R250
 55		/// </summary>
 56		public Random250Algorithm()
 57			: this(Convert.ToInt32(DateTime.Now.Ticks & 0x000000007FFFFFFF))
 58		{
 59		}
 60
 61		/// <summary>
 62		/// Create R250
 63		/// </summary>
 64		/// <param name="seed">Seed</param>
 65		public Random250Algorithm(int seed)
 66			: base(seed)
 67		{
 68			x = new uint[P];
 69
 70			// get the memory we need for initialization
 71			uint[] e = new uint[P]; // new unsigned long int[P];
 72			uint[] a = new uint[2 * P]; // new unsigned short int[2*P];
 73
 74			for (int i = 0; i < 7; i++)
 75			{
 76				x[i] = GetBaseNextUInt32();
 77			}
 78
 79			pointer = Convert.ToInt32(P * GetBaseNextDouble());
 80
 81			// construct P linearly independent basis vectors
 82			for (int i = 0; i < P; i++)
 83			{
 84				//mini_rand(s);
 85				int k = L * i / P;
 86				e[i] = GetBaseNextUInt32() << k; // zeros to right of bit k
 87				e[i] = e[i] | (0x01U << k); // and a one at bit k
 88			}
 89
 90			// construct 2P-1 coefficient bits
 91			for (int i = 0; i < P; i++)
 92			{
 93				a[i] =
 94					(uint)
 95					(GetBaseNextDouble() > 0.5
 96					 	? 1
 97					 	: 0);
 98			}
 99
100			for (int i = P; i < 2 * P; i++)
101			{
102				a[i] = a[i - P] ^ a[i - Q];
103			}
104
105			// construct first P-1 entries (``matrix seed'') by
106			// combining basis vectors according to coefficient bits
107			for (int i = 0; i < P; i++)
108			{
109				x[i] = 0;
110
111				for (int j = 0; j < P; j++)
112				{
113					if (a[i + j] != 0)
114					{
115						x[i] = x[i] ^ e[j];
116					}
117				}
118			}
119
120			// set pointer to last element
121			pointer = P - 1;
122		}
123		#endregion
124
125		#region Next (Public)
126		/// <summary>
127		/// Next
128		/// </summary>
129		public override int Next()
130		{
131			uint ret;
132			int newP = pointer;
133
134			// advance pointer
135			if (newP == P - 1)
136			{
137				newP = 0;
138			}
139			else
140			{
141				newP++;
142			}
143
144			// compute next value
145			ret =
146				(newP < Q)
147					? x[newP] ^ x[(newP - Q + P)]
148					: x[newP] ^ x[(newP - Q)];
149
150			// replace value and pointer and return
151			pointer = newP;
152			x[pointer] = ret;
153
154			return ConvertToInt32(ret & 0x7fffffffU);
155		}
156		#endregion
157
158		/// <summary>
159		/// Tests for Random250Algorithm
160		/// </summary>
161		internal class Random250AlgorithmTests
162		{
163			#region CreateRandom250Algorithm
164			[Test]
165			public void CreateRandom250Algorithm()
166			{
167				RandomBase generator = new Random250Algorithm();
168				Assert.NotEqual(generator.NextDouble(), generator.NextDouble());
169			}
170			#endregion
171		}
172	}
173}