|
|
|
@ -32,47 +32,126 @@ namespace MathNet.Numerics.Random |
|
|
|
using System; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Xor-shift pseudo random number generator (RNG) specified in Marsaglia, George. (2003). Xorshift RNGs.
|
|
|
|
/// http://www.jstatsoft.org/v08/i14/xorshift.pdf
|
|
|
|
/// Implements a multiply-with-carry Xorshift pseudo random number generator (RNG) specified in Marsaglia, George. (2003). Xorshift RNGs.
|
|
|
|
/// <code>Xn = a * Xn−3 + c mod 2^32</code>
|
|
|
|
/// http://www.jstatsoft.org/v08/i14/paper
|
|
|
|
/// </summary>
|
|
|
|
public class Xorshift : AbstractRandomNumberGenerator |
|
|
|
{ |
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
/// Initializes a new instance of the <see cref="Xorshift"/> class using
|
|
|
|
/// the current time as the seed.
|
|
|
|
/// </summary>
|
|
|
|
/// <remarks>If the seed value is zero, it is set to one. Uses the
|
|
|
|
/// value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to
|
|
|
|
/// set whether the instance is thread safe.</remarks>
|
|
|
|
/// set whether the instance is thread safe.
|
|
|
|
/// Uses the default values of:
|
|
|
|
/// <list>
|
|
|
|
/// <item>a = 916905990</item>
|
|
|
|
/// <item>c = 13579</item>
|
|
|
|
/// <item>X1 = 77465321</item>
|
|
|
|
/// <item>X2 = 362436069</item>
|
|
|
|
/// </list></remarks>
|
|
|
|
public Xorshift() : this((int)DateTime.Now.Ticks) |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Initializes a new instance of the <see cref="Xorshift"/> class using
|
|
|
|
/// the current time as the seed.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="a">The multiply value</param>
|
|
|
|
/// <param name="c">The initial carry value.</param>
|
|
|
|
/// <param name="x1">The initial value if X1.</param>
|
|
|
|
/// <param name="x2">The initial value if X2.</param>
|
|
|
|
/// <remarks>If the seed value is zero, it is set to one. Uses the
|
|
|
|
/// value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to
|
|
|
|
/// set whether the instance is thread safe.
|
|
|
|
/// </remarks>
|
|
|
|
public Xorshift(long a, long c, long x1, long x2) |
|
|
|
: this((int)DateTime.Now.Ticks, a, c, x1, x2) |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Initializes a new instance of the <see cref="Xorshift"/> class using
|
|
|
|
/// the current time as the seed.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param>
|
|
|
|
public Xorshift(bool threadSafe) : this((int)DateTime.Now.Ticks, threadSafe) |
|
|
|
/// <remarks>
|
|
|
|
/// Uses the default values of:
|
|
|
|
/// <list>
|
|
|
|
/// <item>a = 916905990</item>
|
|
|
|
/// <item>c = 13579</item>
|
|
|
|
/// <item>X1 = 77465321</item>
|
|
|
|
/// <item>X2 = 362436069</item>
|
|
|
|
/// </list></remarks>
|
|
|
|
public Xorshift(bool threadSafe) |
|
|
|
: this((int)DateTime.Now.Ticks, threadSafe) |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
/// Initializes a new instance of the <see cref="Xorshift"/> class using
|
|
|
|
/// the current time as the seed.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param>
|
|
|
|
/// <param name="a">The multiply value</param>
|
|
|
|
/// <param name="c">The initial carry value.</param>
|
|
|
|
/// <param name="x1">The initial value if X1.</param>
|
|
|
|
/// <param name="x2">The initial value if X2.</param>
|
|
|
|
public Xorshift(bool threadSafe, long a, long c, long x1, long x2) |
|
|
|
: this((int)DateTime.Now.Ticks, threadSafe, a, c, x1, x2) |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Initializes a new instance of the <see cref="Xorshift"/> class.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="seed">The seed value.</param>
|
|
|
|
/// <remarks>If the seed value is zero, it is set to one. Uses the
|
|
|
|
/// value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to
|
|
|
|
/// set whether the instance is thread safe.</remarks>
|
|
|
|
/// set whether the instance is thread safe.
|
|
|
|
/// Uses the default values of:
|
|
|
|
/// <list>
|
|
|
|
/// <item>a = 916905990</item>
|
|
|
|
/// <item>c = 13579</item>
|
|
|
|
/// <item>X1 = 77465321</item>
|
|
|
|
/// <item>X2 = 362436069</item>
|
|
|
|
/// </list></remarks>
|
|
|
|
public Xorshift(int seed) : this(seed, Control.ThreadSafeRandomNumberGenerators) |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Initializes a new instance of the <see cref="Xorshift"/> class.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="seed">The seed value.</param>
|
|
|
|
/// <remarks>If the seed value is zero, it is set to one. Uses the
|
|
|
|
/// value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to
|
|
|
|
/// set whether the instance is thread safe.</remarks>
|
|
|
|
/// <param name="a">The multiply value</param>
|
|
|
|
/// <param name="c">The initial carry value.</param>
|
|
|
|
/// <param name="x1">The initial value if X1.</param>
|
|
|
|
/// <param name="x2">The initial value if X2.</param>
|
|
|
|
public Xorshift(int seed, long a, long c, long x1, long x2) |
|
|
|
: this(seed, Control.ThreadSafeRandomNumberGenerators, a, c, x1, x2) |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Initializes a new instance of the <see cref="Xorshift"/> class.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="seed">The seed value.</param>
|
|
|
|
/// <param name="threadSafe">if set to <c>true</c>, the class is thread safe.</param>
|
|
|
|
/// <remarks>
|
|
|
|
/// Uses the default values of:
|
|
|
|
/// <list>
|
|
|
|
/// <item>a = 916905990</item>
|
|
|
|
/// <item>c = 13579</item>
|
|
|
|
/// <item>X1 = 77465321</item>
|
|
|
|
/// <item>X2 = 362436069</item>
|
|
|
|
/// </list></remarks>
|
|
|
|
public Xorshift(int seed, bool threadSafe) : base(threadSafe) |
|
|
|
{ |
|
|
|
if (seed == 0) |
|
|
|
@ -83,48 +162,83 @@ namespace MathNet.Numerics.Random |
|
|
|
_x = (uint)seed; |
|
|
|
_y = YSeed; |
|
|
|
_z = ZSeed; |
|
|
|
_w = WSeed; |
|
|
|
_c = CSeed; |
|
|
|
_a = ASeed; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Y seed is 423864282.
|
|
|
|
/// Initializes a new instance of the <see cref="Xorshift"/> class.
|
|
|
|
/// </summary>
|
|
|
|
private const uint YSeed = 423864282; |
|
|
|
/// <param name="seed">The seed value.</param>
|
|
|
|
/// <param name="threadSafe">if set to <c>true</c>, the class is thread safe.</param>
|
|
|
|
/// <param name="a">The multiply value</param>
|
|
|
|
/// <param name="c">The initial carry value.</param>
|
|
|
|
/// <param name="x1">The initial value if X1.</param>
|
|
|
|
/// <param name="x2">The initial value if X2.</param>
|
|
|
|
public Xorshift(int seed, bool threadSafe, long a, long c, long x1, long x2) |
|
|
|
: base(threadSafe) |
|
|
|
{ |
|
|
|
if (seed == 0) |
|
|
|
{ |
|
|
|
seed = 1; |
|
|
|
} |
|
|
|
|
|
|
|
_x = (uint)seed; |
|
|
|
_y = (ulong)x1; |
|
|
|
_z = (ulong)x2; |
|
|
|
_a = (ulong)a; |
|
|
|
_c = (ulong)c; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// The default value for X1.
|
|
|
|
/// </summary>
|
|
|
|
private const uint YSeed = 362436069; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Y seed is 643534723.
|
|
|
|
/// The default value for X2.
|
|
|
|
/// </summary>
|
|
|
|
private const uint ZSeed = 643534723; |
|
|
|
private const uint ZSeed = 77465321; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// W seed is 84452734.
|
|
|
|
/// The default value for the multiplier.
|
|
|
|
/// </summary>
|
|
|
|
private const uint WSeed = 84452734; |
|
|
|
private const uint ASeed = 916905990; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// The default value for the carry over.
|
|
|
|
/// </summary>
|
|
|
|
private const uint CSeed = 13579; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// The multiplier to compute a double-precision floating point number [0, 1)
|
|
|
|
/// </summary>
|
|
|
|
private const double IntToDoubleMultiplier = 1.0 / (int.MaxValue + 1.0); |
|
|
|
private const double UlongToDoubleMultiplier = 1.0 / (uint.MaxValue + 1.0); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Seed or last but three unsigned random number.
|
|
|
|
/// </summary>
|
|
|
|
private uint _x; |
|
|
|
private ulong _x; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Last but two unsigned random number.
|
|
|
|
/// </summary>
|
|
|
|
private uint _y; |
|
|
|
private ulong _y; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Last but one unsigned random number.
|
|
|
|
/// </summary>
|
|
|
|
private uint _z; |
|
|
|
private ulong _z; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// The value of the carry over.
|
|
|
|
/// </summary>
|
|
|
|
private ulong _c; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Last generated unsigned random number.
|
|
|
|
/// The multiplier.
|
|
|
|
/// </summary>
|
|
|
|
private uint _w; |
|
|
|
private ulong _a; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Returns a random number between 0.0 and 1.0.
|
|
|
|
@ -134,13 +248,12 @@ namespace MathNet.Numerics.Random |
|
|
|
/// </returns>
|
|
|
|
protected override double DoSample() |
|
|
|
{ |
|
|
|
var t = _x ^ (_x << 11); |
|
|
|
var t = (_a * _x) + _c; |
|
|
|
_x = _y; |
|
|
|
_y = _z; |
|
|
|
_z = _w; |
|
|
|
_w = (_w ^ (_w >> 19)) ^ (t ^ (t >> 8)); |
|
|
|
|
|
|
|
return (int)(_w >> 1) * IntToDoubleMultiplier; |
|
|
|
_c = t >> 32; |
|
|
|
_z = t & 0xffffffff; |
|
|
|
return _z * UlongToDoubleMultiplier; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|