/Utilities/Math/Random250Algorithm.cs
C# | 173 lines | 102 code | 24 blank | 47 comment | 10 complexity | db5f855e4b5dab8266c3555c6916faa1 MD5 | raw file
Possible License(s): Apache-2.0
- using System;
- using NUnit.Framework;
-
- namespace Delta.Utilities.Math
- {
- /// <summary>
- /// This class represents an implementation of the R250 algorith comes
- /// originally from the "Random isn't Really Random -- C# Random Number
- /// Generation" article by Matthew Cochran. For more details see:
- /// http://www.shadlen.org/ichbin/random/generators.htm#r250
- /// http://www.c-sharpcorner.com/UploadFile/rmcochran/random07172006175425PM/random.aspx
- /// <para />
- /// Implements the GFSR: x_n = x_(n-P) ^ x_(n-Q), which has period 2^P - 1.
- /// </summary>
- public class Random250Algorithm : RandomBase
- {
- #region Constants
- /// <summary>
- /// P, used as degree of larger term (250 or 7)
- /// </summary>
- private static readonly int P = 250;
-
- /// <summary>
- /// Q, used as degree of smaller term (103 or 4)
- /// </summary>
- private static readonly int Q = 103;
-
- /// <summary>
- /// L, used as word length (32 or 3)
- /// </summary>
- private static readonly int L = 32;
- #endregion
-
- #region Private
-
- #region x (Private)
- /// <summary>
- /// X array with all the random values.
- /// </summary>
- private readonly uint[] x;
- #endregion
-
- #region pointer (Private)
- /// <summary>
- /// Pointer to element we are working on.
- /// </summary>
- private int pointer;
- #endregion
-
- #endregion
-
- #region Constructors
- /// <summary>
- /// Create R250
- /// </summary>
- public Random250Algorithm()
- : this(Convert.ToInt32(DateTime.Now.Ticks & 0x000000007FFFFFFF))
- {
- }
-
- /// <summary>
- /// Create R250
- /// </summary>
- /// <param name="seed">Seed</param>
- public Random250Algorithm(int seed)
- : base(seed)
- {
- x = new uint[P];
-
- // get the memory we need for initialization
- uint[] e = new uint[P]; // new unsigned long int[P];
- uint[] a = new uint[2 * P]; // new unsigned short int[2*P];
-
- for (int i = 0; i < 7; i++)
- {
- x[i] = GetBaseNextUInt32();
- }
-
- pointer = Convert.ToInt32(P * GetBaseNextDouble());
-
- // construct P linearly independent basis vectors
- for (int i = 0; i < P; i++)
- {
- //mini_rand(s);
- int k = L * i / P;
- e[i] = GetBaseNextUInt32() << k; // zeros to right of bit k
- e[i] = e[i] | (0x01U << k); // and a one at bit k
- }
-
- // construct 2P-1 coefficient bits
- for (int i = 0; i < P; i++)
- {
- a[i] =
- (uint)
- (GetBaseNextDouble() > 0.5
- ? 1
- : 0);
- }
-
- for (int i = P; i < 2 * P; i++)
- {
- a[i] = a[i - P] ^ a[i - Q];
- }
-
- // construct first P-1 entries (``matrix seed'') by
- // combining basis vectors according to coefficient bits
- for (int i = 0; i < P; i++)
- {
- x[i] = 0;
-
- for (int j = 0; j < P; j++)
- {
- if (a[i + j] != 0)
- {
- x[i] = x[i] ^ e[j];
- }
- }
- }
-
- // set pointer to last element
- pointer = P - 1;
- }
- #endregion
-
- #region Next (Public)
- /// <summary>
- /// Next
- /// </summary>
- public override int Next()
- {
- uint ret;
- int newP = pointer;
-
- // advance pointer
- if (newP == P - 1)
- {
- newP = 0;
- }
- else
- {
- newP++;
- }
-
- // compute next value
- ret =
- (newP < Q)
- ? x[newP] ^ x[(newP - Q + P)]
- : x[newP] ^ x[(newP - Q)];
-
- // replace value and pointer and return
- pointer = newP;
- x[pointer] = ret;
-
- return ConvertToInt32(ret & 0x7fffffffU);
- }
- #endregion
-
- /// <summary>
- /// Tests for Random250Algorithm
- /// </summary>
- internal class Random250AlgorithmTests
- {
- #region CreateRandom250Algorithm
- [Test]
- public void CreateRandom250Algorithm()
- {
- RandomBase generator = new Random250Algorithm();
- Assert.NotEqual(generator.NextDouble(), generator.NextDouble());
- }
- #endregion
- }
- }
- }