#### /Utilities/Math/Random250Algorithm.cs

#
C# | 173 lines | 102 code | 24 blank | 47 comment | 10 complexity | db5f855e4b5dab8266c3555c6916faa1 MD5 | raw file
``````
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:

/// <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>

#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;

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

}

}

}

``````