Browse Source

Random: rework

pull/184/head
Christoph Ruegg 13 years ago
parent
commit
02f6960c50
  1. 6
      src/Examples/RandomNumberGeneration.cs
  2. 4
      src/FSharp/Random.fs
  3. 6
      src/Numerics/Numerics.csproj
  4. 32
      src/Numerics/Random/CryptoRandomSource.cs
  5. 34
      src/Numerics/Random/Mcg31m1.cs
  6. 41
      src/Numerics/Random/Mcg59.cs
  7. 62
      src/Numerics/Random/MersenneTwister.cs
  8. 51
      src/Numerics/Random/Mrg32k3a.cs
  9. 46
      src/Numerics/Random/Palf.cs
  10. 2
      src/Numerics/Random/RandomExtensions.cs
  11. 138
      src/Numerics/Random/RandomSource.cs
  12. 46
      src/Numerics/Random/WH1982.cs
  13. 55
      src/Numerics/Random/WH2006.cs
  14. 57
      src/Numerics/Random/Xorshift.cs
  15. 6
      src/UnitTests/Random/SystemCryptoTests.cs

6
src/Examples/RandomNumberGeneration.cs

@ -89,7 +89,7 @@ namespace Examples
// 1. Multiplicative congruential generator using a modulus of 2^31-1 and a multiplier of 1132489760
var mcg31M1 = new Mcg31m1(1);
Console.WriteLine(@"1. Generate 10 random double values using Multiplicative congruential generator with a modulus of 2^31-1 and a multiplier of 1132489760");
var randomValues = mcg31M1.NextDouble(10);
var randomValues = mcg31M1.NextDoubles(10);
for (var i = 0; i < randomValues.Length; i++)
{
Console.Write(randomValues[i].ToString("N") + @" ");
@ -145,11 +145,11 @@ namespace Examples
Console.WriteLine();
// 6. A random number generator based on the "System.Security.Cryptography.RandomNumberGenerator" class in the .NET library
var systemCryptoRandomNumberGenerator = new SystemCryptoRandomNumberGenerator();
var systemCrypto = new CryptoRandomSource();
Console.WriteLine(@"6. Generate 10 random decimal values using RNG based on the 'System.Security.Cryptography.RandomNumberGenerator'");
for (var i = 0; i < 10; i++)
{
Console.Write(systemCryptoRandomNumberGenerator.NextDecimal().ToString("N") + @" ");
Console.Write(systemCrypto.NextDecimal().ToString("N") + @" ");
}
Console.WriteLine();

4
src/FSharp/Random.fs

@ -43,8 +43,8 @@ module Random =
#if PORTABLE
#else
/// Creates a default .Net cryptographic system pRNG
let crypto () = new SystemCryptoRandomNumberGenerator() :> System.Random
let cryptoWith (threadSafe:bool) = new SystemCryptoRandomNumberGenerator(threadSafe) :> System.Random
let crypto () = new CryptoRandomSource() :> System.Random
let cryptoWith (threadSafe:bool) = new CryptoRandomSource(threadSafe) :> System.Random
#endif
/// Creates a Mersenne Twister 19937 pRNG with a custom seed based on uinque GUIDs

6
src/Numerics/Numerics.csproj

@ -395,14 +395,14 @@
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Random\AbstractRandomNumberGenerator.cs" />
<Compile Include="Random\RandomSource.cs" />
<Compile Include="Random\Mcg31m1.cs" />
<Compile Include="Random\Mcg59.cs" />
<Compile Include="Random\MersenneTwister.cs" />
<Compile Include="Random\Mrg32k3a.cs" />
<Compile Include="Random\Palf.cs" />
<Compile Include="Random\SystemCrypto.cs" />
<Compile Include="Random\SystemRandomExtensions.cs" />
<Compile Include="Random\CryptoRandomSource.cs" />
<Compile Include="Random\RandomExtensions.cs" />
<Compile Include="Random\WH1982.cs" />
<Compile Include="Random\WH2006.cs" />
<Compile Include="Random\Xorshift.cs" />

32
src/Numerics/Random/SystemCrypto.cs → src/Numerics/Random/CryptoRandomSource.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2012 Math.NET
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -38,19 +38,19 @@ namespace MathNet.Numerics.Random
/// <summary>
/// A random number generator based on the <see cref="System.Security.Cryptography.RandomNumberGenerator"/> class in the .NET library.
/// </summary>
public class SystemCryptoRandomNumberGenerator : AbstractRandomNumberGenerator, IDisposable
public class CryptoRandomSource : RandomSource, IDisposable
{
private const double Reciprocal = 1.0 / uint.MaxValue;
private readonly RandomNumberGenerator _random;
const double Reciprocal = 1.0/uint.MaxValue;
readonly RandomNumberGenerator _crypto;
/// <summary>
/// Construct a new random number generator with a random seed.
/// </summary>
/// <remarks>Uses <see cref="System.Security.Cryptography.RNGCryptoServiceProvider"/> and uses the value of
/// <see cref="Control.ThreadSafeRandomNumberGenerators"/> to set whether the instance is thread safe.</remarks>
public SystemCryptoRandomNumberGenerator(): this(new RNGCryptoServiceProvider(), Control.ThreadSafeRandomNumberGenerators)
public CryptoRandomSource()
{
_random = new RNGCryptoServiceProvider();
_crypto = new RNGCryptoServiceProvider();
}
/// <summary>
@ -58,8 +58,9 @@ namespace MathNet.Numerics.Random
/// </summary>
/// <param name="rng">The <see cref="RandomNumberGenerator"/> to use.</param>
/// <remarks>Uses the value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to set whether the instance is thread safe.</remarks>
public SystemCryptoRandomNumberGenerator(RandomNumberGenerator rng) : this(rng, Control.ThreadSafeRandomNumberGenerators)
public CryptoRandomSource(RandomNumberGenerator rng)
{
_crypto = rng;
}
/// <summary>
@ -67,8 +68,9 @@ namespace MathNet.Numerics.Random
/// </summary>
/// <remarks>Uses <see cref="System.Security.Cryptography.RNGCryptoServiceProvider"/></remarks>
/// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param>
public SystemCryptoRandomNumberGenerator(bool threadSafe): this(new RNGCryptoServiceProvider(), threadSafe)
public CryptoRandomSource(bool threadSafe) : base(threadSafe)
{
_crypto = new RNGCryptoServiceProvider();
}
/// <summary>
@ -76,13 +78,9 @@ namespace MathNet.Numerics.Random
/// </summary>
/// <param name="rng">The <see cref="RandomNumberGenerator"/> to use.</param>
/// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param>
public SystemCryptoRandomNumberGenerator(RandomNumberGenerator rng, bool threadSafe) : base(threadSafe)
public CryptoRandomSource(RandomNumberGenerator rng, bool threadSafe) : base(threadSafe)
{
if (rng == null)
{
throw new ArgumentNullException("rng");
}
_random = rng;
_crypto = rng;
}
@ -95,14 +93,14 @@ namespace MathNet.Numerics.Random
protected override double DoSample()
{
var bytes = new byte[4];
_random.GetBytes(bytes);
return BitConverter.ToUInt32(bytes, 0) * Reciprocal;
_crypto.GetBytes(bytes);
return BitConverter.ToUInt32(bytes, 0)*Reciprocal;
}
public void Dispose()
{
#if !NET35
_random.Dispose();
_crypto.Dispose();
#endif
}
}

34
src/Numerics/Random/Mcg31m1.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2010 Math.NET
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -28,36 +28,33 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
namespace MathNet.Numerics.Random
{
/// <summary>
/// Multiplicative congruential generator using a modulus of 2^31-1 and a multiplier of 1132489760.
/// </summary>
public class Mcg31m1 : AbstractRandomNumberGenerator
public class Mcg31m1 : RandomSource
{
private const ulong Modulus = 2147483647;
private const ulong Multiplier = 1132489760;
private const double Reciprocal = 1.0 / Modulus;
private ulong _xn;
const ulong Modulus = 2147483647;
const ulong Multiplier = 1132489760;
const double Reciprocal = 1.0/Modulus;
ulong _xn;
/// <summary>
/// Initializes a new instance of the <see cref="Mcg31m1"/> class using
/// the current time as the seed.
/// a seed based on time and unique GUIDs.
/// </summary>
public Mcg31m1() : this((int) DateTime.Now.Ticks)
public Mcg31m1() : this(RandomSeed.Guid())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Mcg31m1"/> class using
/// the current time as the seed.
/// a seed based on time and unique GUIDs.
/// </summary>
/// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param>
public Mcg31m1(bool threadSafe) : this((int)DateTime.Now.Ticks, threadSafe)
public Mcg31m1(bool threadSafe) : this(RandomSeed.Guid(), threadSafe)
{
}
/// <summary>
@ -67,8 +64,13 @@ namespace MathNet.Numerics.Random
/// <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 Mcg31m1(int seed) : this(seed, Control.ThreadSafeRandomNumberGenerators)
public Mcg31m1(int seed)
{
if (seed == 0)
{
seed = 1;
}
_xn = (uint)seed%Modulus;
}
/// <summary>
@ -82,7 +84,7 @@ namespace MathNet.Numerics.Random
{
seed = 1;
}
_xn = (uint) seed%Modulus;
_xn = (uint)seed%Modulus;
}
/// <summary>
@ -98,4 +100,4 @@ namespace MathNet.Numerics.Random
return ret;
}
}
}
}

41
src/Numerics/Random/Mcg59.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2010 Math.NET
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -28,36 +28,34 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
namespace MathNet.Numerics.Random
{
/// <summary>
/// Multiplicative congruential generator using a modulus of 2^59 and a multiplier of 13^13.
/// </summary>
public class Mcg59 : AbstractRandomNumberGenerator
public class Mcg59 : RandomSource
{
private const double Reciprocal = 1.0 / Modulus;
private const ulong Modulus = 576460752303423488;
private const ulong Multiplier = 302875106592253;
private ulong _xn;
const double Reciprocal = 1.0/Modulus;
const ulong Modulus = 576460752303423488;
const ulong Multiplier = 302875106592253;
ulong _xn;
/// <summary>
/// Initializes a new instance of the <see cref="Mcg59"/> class using
/// the current time as the seed.
/// a seed based on time and unique GUIDs.
/// </summary>
public Mcg59() : this((int) DateTime.Now.Ticks)
public Mcg59() : this(RandomSeed.Guid())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Mcg59"/> class using
/// the current time as the seed.
/// a seed based on time and unique GUIDs.
/// </summary>
/// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param>
public Mcg59(bool threadSafe) : this((int)DateTime.Now.Ticks, threadSafe)
public Mcg59(bool threadSafe) : this(RandomSeed.Guid(), threadSafe)
{
}
/// <summary>
@ -67,8 +65,13 @@ namespace MathNet.Numerics.Random
/// <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 Mcg59(int seed) : this(seed, Control.ThreadSafeRandomNumberGenerators)
public Mcg59(int seed)
{
if (seed == 0)
{
seed = 1;
}
_xn = (uint)seed%Modulus;
}
/// <summary>
@ -79,11 +82,11 @@ namespace MathNet.Numerics.Random
/// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param>
public Mcg59(int seed, bool threadSafe) : base(threadSafe)
{
if( seed == 0)
if (seed == 0)
{
seed = 1;
}
_xn = (uint) seed % Modulus;
_xn = (uint)seed%Modulus;
}
/// <summary>
@ -94,9 +97,9 @@ namespace MathNet.Numerics.Random
/// </returns>
protected override double DoSample()
{
double ret = _xn * Reciprocal;
_xn = (_xn * Multiplier) % Modulus;
double ret = _xn*Reciprocal;
_xn = (_xn*Multiplier)%Modulus;
return ret;
}
}
}
}

62
src/Numerics/Random/MersenneTwister.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2010 Math.NET
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -66,7 +66,6 @@
email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
*/
using System;
using System.Threading;
namespace MathNet.Numerics.Random
@ -74,70 +73,70 @@ namespace MathNet.Numerics.Random
/// <summary>
/// Random number generator using Mersenne Twister 19937 algorithm.
/// </summary>
public class MersenneTwister : AbstractRandomNumberGenerator, IDisposable
public class MersenneTwister : RandomSource
{
/// <summary>
/// Mersenne twister constant.
/// </summary>
private const uint LowerMask = 0x7fffffff;
const uint LowerMask = 0x7fffffff;
/// <summary>
/// Mersenne twister constant.
/// </summary>
private const int M = 397;
const int M = 397;
/// <summary>
/// Mersenne twister constant.
/// </summary>
private const uint MatrixA = 0x9908b0df;
const uint MatrixA = 0x9908b0df;
/// <summary>
/// Mersenne twister constant.
/// </summary>
private const int N = 624;
const int N = 624;
/// <summary>
/// Mersenne twister constant.
/// </summary>
private const double Reciprocal = 1.0/4294967296.0;
const double Reciprocal = 1.0/4294967296.0;
/// <summary>
/// Mersenne twister constant.
/// </summary>
private const uint UpperMask = 0x80000000;
const uint UpperMask = 0x80000000;
/// <summary>
/// Mersenne twister constant.
/// </summary>
private static readonly uint[] Mag01 = {0x0U, MatrixA};
static readonly uint[] Mag01 = { 0x0U, MatrixA };
/// <summary>
/// Mersenne twister constant.
/// </summary>
private readonly uint[] _mt = new uint[624];
readonly uint[] _mt = new uint[624];
/// <summary>
/// Mersenne twister constant.
/// </summary>
private int _mti = N + 1;
int _mti = N + 1;
/// <summary>
/// Initializes a new instance of the <see cref="MersenneTwister"/> class using
/// the current time as the seed.
/// a seed based on time and unique GUIDs.
/// </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>
public MersenneTwister() : this((int) DateTime.Now.Ticks)
public MersenneTwister() : this(RandomSeed.Guid())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="MersenneTwister"/> class using
/// the current time as the seed.
/// a seed based on time and unique GUIDs.
/// </summary>
/// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param>
public MersenneTwister(bool threadSafe) : this((int) DateTime.Now.Ticks, threadSafe)
public MersenneTwister(bool threadSafe) : this(RandomSeed.Guid(), threadSafe)
{
}
@ -147,8 +146,9 @@ namespace MathNet.Numerics.Random
/// <param name="seed">The seed value.</param>
/// <remarks>Uses the value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to
/// set whether the instance is thread safe.</remarks>
public MersenneTwister(int seed) : this(seed, Control.ThreadSafeRandomNumberGenerators)
public MersenneTwister(int seed)
{
init_genrand((uint)seed);
}
/// <summary>
@ -190,7 +190,7 @@ namespace MathNet.Numerics.Random
get { return DefaultInstance.Value; }
}
#endif
/*/// <summary>
/// Initializes a new instance of the <see cref="MersenneTwister"/> class.
/// </summary>
@ -211,12 +211,12 @@ namespace MathNet.Numerics.Random
*/
/* initializes _mt[_n] with a seed */
private void init_genrand(uint s)
void init_genrand(uint s)
{
_mt[0] = s & 0xffffffff;
for (_mti = 1; _mti < N; _mti++)
{
_mt[_mti] = (1812433253*(_mt[_mti - 1] ^ (_mt[_mti - 1] >> 30)) + (uint) _mti);
_mt[_mti] = (1812433253*(_mt[_mti - 1] ^ (_mt[_mti - 1] >> 30)) + (uint)_mti);
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
/* In the previous versions, MSBs of the seed affect */
/* only MSBs of the array _mt[]. */
@ -231,7 +231,7 @@ namespace MathNet.Numerics.Random
/* init_key is the array for initializing keys */
/* slight change for C++, 2004/2/26 */
/* private void init_by_array(uint[] init_key)
/* private void init_by_array(uint[] init_key)
{
uint key_length = (uint) init_key.Length;
init_genrand(19650218);
@ -268,7 +268,7 @@ namespace MathNet.Numerics.Random
/* generates a random number on [0,0xffffffff]-interval */
private uint genrand_int32()
uint genrand_int32()
{
uint y;
@ -317,10 +317,10 @@ namespace MathNet.Numerics.Random
/// </returns>
protected override double DoSample()
{
return genrand_int32() * Reciprocal;
return genrand_int32()*Reciprocal;
}
/* /// <summary>
/* /// <summary>
/// Generates a random number on [0,1) with 53-bit resolution.
/// </summary>
/// <returns>A random number on [0,1) with 53-bit resolution.</returns>
@ -329,17 +329,5 @@ namespace MathNet.Numerics.Random
ulong a = genrand_int32() >> 5, b = genrand_int32() >> 6;
return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0);
}*/
#region IDisposable Members
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
//do nothing in the managed version.
}
#endregion
}
}
}

51
src/Numerics/Random/Mrg32k3a.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2010 Math.NET
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -36,40 +36,40 @@ namespace MathNet.Numerics.Random
/// A 32-bit combined multiple recursive generator with 2 components of order 3.
/// </summary>
///<remarks>Based off of P. L'Ecuyer, "Combined Multiple Recursive Random Number Generators," Operations Research, 44, 5 (1996), 816--822. </remarks>
public class Mrg32k3a : AbstractRandomNumberGenerator
public class Mrg32k3a : RandomSource
{
private const double A12 = 1403580;
private const double A13 = 810728;
private const double A21 = 527612;
private const double A23 = 1370589;
private const double Modulus1 = 4294967087;
private const double Modulus2 = 4294944443;
const double A12 = 1403580;
const double A13 = 810728;
const double A21 = 527612;
const double A23 = 1370589;
const double Modulus1 = 4294967087;
const double Modulus2 = 4294944443;
private const double Reciprocal = 1.0 / Modulus1;
private double _xn1 = 1;
private double _xn2 = 1;
private double _xn3;
private double _yn1 = 1;
private double _yn2 = 1;
private double _yn3 = 1;
const double Reciprocal = 1.0/Modulus1;
double _xn1 = 1;
double _xn2 = 1;
double _xn3;
double _yn1 = 1;
double _yn2 = 1;
double _yn3 = 1;
/// <summary>
/// Initializes a new instance of the <see cref="Mcg31m1"/> class using
/// the current time as the seed.
/// a seed based on time and unique GUIDs.
/// </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>
public Mrg32k3a() : this((int)DateTime.Now.Ticks)
public Mrg32k3a() : this(RandomSeed.Guid())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Mcg31m1"/> class using
/// the current time as the seed.
/// a seed based on time and unique GUIDs.
/// </summary>
/// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param>
public Mrg32k3a(bool threadSafe) : this((int)DateTime.Now.Ticks, threadSafe)
public Mrg32k3a(bool threadSafe) : this(RandomSeed.Guid(), threadSafe)
{
}
@ -80,8 +80,13 @@ namespace MathNet.Numerics.Random
/// <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 Mrg32k3a(int seed) : this(seed, Control.ThreadSafeRandomNumberGenerators)
public Mrg32k3a(int seed)
{
if (seed == 0)
{
seed = 1;
}
_xn3 = (uint)seed;
}
/// <summary>
@ -108,7 +113,7 @@ namespace MathNet.Numerics.Random
protected override double DoSample()
{
double xn = A12*_xn2 - A13*_xn3;
double k = (long) (xn/Modulus1);
double k = (long)(xn/Modulus1);
xn -= k*Modulus1;
if (xn < 0)
{
@ -116,7 +121,7 @@ namespace MathNet.Numerics.Random
}
double yn = A21*_yn1 - A23*_yn3;
k = (long) (yn/Modulus2);
k = (long)(yn/Modulus2);
yn -= k*Modulus2;
if (yn < 0)
{
@ -136,4 +141,4 @@ namespace MathNet.Numerics.Random
return (xn - yn)*Reciprocal;
}
}
}
}

46
src/Numerics/Random/Palf.cs

@ -43,7 +43,7 @@ namespace MathNet.Numerics.Random
/// It uses the modulus 2<sup>32</sup> and by default the "lags" 418 and 1279. Some popular pairs are presented on
/// <a href="http://en.wikipedia.org/wiki/Lagged_Fibonacci_generator">Wikipedia - Lagged Fibonacci generator</a>.
/// </remarks>
public class Palf : AbstractRandomNumberGenerator
public class Palf : RandomSource
{
/// <summary>
/// Default value for the ShortLag
@ -62,23 +62,21 @@ namespace MathNet.Numerics.Random
/// <summary>
/// Initializes a new instance of the <see cref="Palf"/> class using
/// the current time as the seed.
/// a seed based on time and unique GUIDs.
/// </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>
public Palf()
: this((int) DateTime.Now.Ticks)
public Palf() : this(RandomSeed.Guid(), Control.ThreadSafeRandomNumberGenerators, DefaultShortLag, DefaultLongLag)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Palf"/> class using
/// the current time as the seed.
/// a seed based on time and unique GUIDs.
/// </summary>
/// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param>
public Palf(bool threadSafe)
: this((int) DateTime.Now.Ticks, threadSafe, DefaultShortLag, DefaultLongLag)
public Palf(bool threadSafe) : this(RandomSeed.Guid(), threadSafe, DefaultShortLag, DefaultLongLag)
{
}
@ -89,8 +87,7 @@ namespace MathNet.Numerics.Random
/// <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 Palf(int seed)
: this(seed, Control.ThreadSafeRandomNumberGenerators, DefaultShortLag, DefaultLongLag)
public Palf(int seed) : this(seed, Control.ThreadSafeRandomNumberGenerators, DefaultShortLag, DefaultLongLag)
{
}
@ -101,8 +98,7 @@ namespace MathNet.Numerics.Random
/// <param name="threadSafe">if set to <c>true</c>, the class is thread safe.</param>
/// <param name="shortLag">The ShortLag value</param>
/// <param name="longLag">TheLongLag value</param>
public Palf(int seed, bool threadSafe, int shortLag, int longLag)
: base(threadSafe)
public Palf(int seed, bool threadSafe, int shortLag, int longLag) : base(threadSafe)
{
if (shortLag < 1)
{
@ -135,7 +131,7 @@ namespace MathNet.Numerics.Random
var gen = new MersenneTwister(seed, threadSafe);
for (var j = 0; j < LongLag; ++j)
{
_x[j] = (uint) (gen.NextDouble()*uint.MaxValue);
_x[j] = (uint)(gen.NextDouble()*uint.MaxValue);
}
_i = LongLag;
@ -171,21 +167,21 @@ namespace MathNet.Numerics.Random
void Fill()
{
CommonParallel.For(0, Control.NumberOfParallelWorkerThreads, (u, v) =>
{
for (int index = u; index < v; index++)
{
for (int index = u; index < v; index++)
// Two loops to avoid costly modulo operations
for (var j = index; j < ShortLag; j = j + Control.NumberOfParallelWorkerThreads)
{
_x[j] += _x[j + (LongLag - ShortLag)];
}
for (var j = ShortLag + index; j < LongLag; j = j + Control.NumberOfParallelWorkerThreads)
{
// Two loops to avoid costly modulo operations
for (var j = index; j < ShortLag; j = j + Control.NumberOfParallelWorkerThreads)
{
_x[j] += _x[j + (LongLag - ShortLag)];
}
for (var j = ShortLag + index; j < LongLag; j = j + Control.NumberOfParallelWorkerThreads)
{
_x[j] += _x[j - ShortLag - index];
}
_x[j] += _x[j - ShortLag - index];
}
});
}
});
_i = 0;
}
@ -203,7 +199,7 @@ namespace MathNet.Numerics.Random
}
var x = _x[_i++];
return (int) (x >> 1)*IntToDoubleMultiplier;
return (int)(x >> 1)*IntToDoubleMultiplier;
}
}
}

2
src/Numerics/Random/SystemRandomExtensions.cs → src/Numerics/Random/RandomExtensions.cs

@ -36,7 +36,7 @@ namespace MathNet.Numerics.Random
/// This class implements extension methods for the System.Random class. The extension methods generate
/// pseudo-random distributed numbers for types other than double and int32.
/// </summary>
public static class SystemRandomExtensions
public static class RandomExtensions
{
/// <summary>
/// Returns a nonnegative random number less than <see cref="Int64.MaxValue"/>.

138
src/Numerics/Random/AbstractRandomNumberGenerator.cs → src/Numerics/Random/RandomSource.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2010 Math.NET
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -28,52 +28,63 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.Random
{
using System;
/// <summary>
/// Abstract class for random number generators. This class introduces a layer between <see cref="System.Random"/>
/// Base class for random number generators. This class introduces a layer between <see cref="System.Random"/>
/// and the Math.Net Numerics random number generators to provide thread safety.
/// When used directly it use the System.Random as random number source.
/// </summary>
public abstract class AbstractRandomNumberGenerator : Random
public class RandomSource : System.Random
{
/// <summary>
/// A delegate type that represents a method that generates random numbers.
/// </summary>
/// <returns>Randomly distributed numbers.</returns>
private delegate double SampleMethod();
readonly bool _threadSafe;
readonly object _lock = new object();
/// <summary>
/// The method that actually generates samples.
/// Initializes a new instance of the <see cref="RandomSource"/> class using
/// the value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to set whether
/// the instance is thread safe or not.
/// </summary>
private readonly SampleMethod _sampleMethod;
public RandomSource() : base(RandomSeed.Guid())
{
_threadSafe = Control.ThreadSafeRandomNumberGenerators;
}
/// <summary>
/// The object that will be locked for thread safety.
/// Initializes a new instance of the <see cref="RandomSource"/> class.
/// </summary>
private readonly object _lock = new object();
/// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param>
/// <remarks>Thread safe instances are two and half times slower than non-thread
/// safe classes.</remarks>
public RandomSource(bool threadSafe) : base(RandomSeed.Guid())
{
_threadSafe = threadSafe;
}
/// <summary>
/// Initializes a new instance of the <see cref="AbstractRandomNumberGenerator"/> class using
/// Initializes a new instance of the <see cref="RandomSource"/> class using
/// the value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to set whether
/// the instance is thread safe or not.
/// </summary>
protected AbstractRandomNumberGenerator() : this(Control.ThreadSafeRandomNumberGenerators)
/// <param name="systemRandomSeed">The seed value.</param>
public RandomSource(int systemRandomSeed) : base(systemRandomSeed)
{
_threadSafe = Control.ThreadSafeRandomNumberGenerators;
}
/// <summary>
/// Initializes a new instance of the <see cref="AbstractRandomNumberGenerator"/> class.
/// Initializes a new instance of the <see cref="RandomSource"/> class.
/// </summary>
/// <param name="systemRandomSeed">The seed value.</param>
/// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param>
/// <remarks>Thread safe instances are two and half times slower than non-thread
/// safe classes.</remarks>
protected AbstractRandomNumberGenerator(bool threadSafe)
public RandomSource(int systemRandomSeed, bool threadSafe) : base(systemRandomSeed)
{
_sampleMethod = threadSafe ? (SampleMethod)ThreadSafeSample : DoSample;
_threadSafe = threadSafe;
}
/// <summary>
@ -84,7 +95,7 @@ namespace MathNet.Numerics.Random
/// An array of uniformly distributed random doubles in the interval [0.0,1.0].
/// </returns>
/// <exception cref="ArgumentException">if n is not greater than 0.</exception>
public double[] NextDouble(int n)
public double[] NextDoubles(int n)
{
if (n < 1)
{
@ -92,11 +103,23 @@ namespace MathNet.Numerics.Random
}
var ret = new double[n];
for (var i = 0; i < ret.Length; i++)
if (_threadSafe)
{
ret[i] = Sample();
lock (_lock)
{
for (var i = 0; i < ret.Length; i++)
{
ret[i] = DoSample();
}
}
}
else
{
for (var i = 0; i < ret.Length; i++)
{
ret[i] = DoSample();
}
}
return ret;
}
@ -106,9 +129,17 @@ namespace MathNet.Numerics.Random
/// <returns>
/// A 32-bit signed integer greater than or equal to zero and less than <see cref="F:System.Int32.MaxValue"/>.
/// </returns>
public override int Next()
public override sealed int Next()
{
return (int)(Sample() * int.MaxValue);
if (_threadSafe)
{
lock (_lock)
{
return (int)(DoSample()*int.MaxValue);
}
}
return (int)(DoSample()*int.MaxValue);
}
/// <summary>
@ -117,14 +148,22 @@ namespace MathNet.Numerics.Random
/// <param name="maxValue">The exclusive upper bound of the random number returned.</param>
/// <returns>A 32-bit signed integer less than <paramref name="maxValue"/>.</returns>
/// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="maxValue"/> is negative. </exception>
public override int Next(int maxValue)
public override sealed int Next(int maxValue)
{
if (maxValue <= 0)
{
throw new ArgumentOutOfRangeException(Resources.ArgumentMustBePositive);
}
return (int)(Sample() * maxValue);
if (_threadSafe)
{
lock (_lock)
{
return (int)(DoSample()*maxValue);
}
}
return (int)(DoSample()*maxValue);
}
/// <summary>
@ -136,14 +175,22 @@ namespace MathNet.Numerics.Random
/// A 32-bit signed integer greater than or equal to <paramref name="minValue"/> and less than <paramref name="maxValue"/>; that is, the range of return values includes <paramref name="minValue"/> but not <paramref name="maxValue"/>. If <paramref name="minValue"/> equals <paramref name="maxValue"/>, <paramref name="minValue"/> is returned.
/// </returns>
/// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="minValue"/> is greater than <paramref name="maxValue"/>. </exception>
public override int Next(int minValue, int maxValue)
public override sealed int Next(int minValue, int maxValue)
{
if (minValue > maxValue)
{
throw new ArgumentOutOfRangeException(Resources.ArgumentMinValueGreaterThanMaxValue);
}
return (int)(Sample() * (maxValue - minValue)) + minValue;
if (_threadSafe)
{
lock (_lock)
{
return (int)(DoSample()*(maxValue - minValue)) + minValue;
}
}
return (int)(DoSample()*(maxValue - minValue)) + minValue;
}
/// <summary>
@ -158,9 +205,21 @@ namespace MathNet.Numerics.Random
throw new ArgumentNullException("buffer");
}
if (_threadSafe)
{
lock (_lock)
{
for (var i = 0; i < buffer.Length; i++)
{
buffer[i] = (byte)(((int)(DoSample()*int.MaxValue))%256);
}
}
return;
}
for (var i = 0; i < buffer.Length; i++)
{
buffer[i] = (byte)(Next() % 256);
buffer[i] = (byte)(((int)(DoSample()*int.MaxValue))%256);
}
}
@ -170,14 +229,22 @@ namespace MathNet.Numerics.Random
/// <returns>A double-precision floating point number greater than or equal to 0.0, and less than 1.0.</returns>
protected override double Sample()
{
return _sampleMethod();
if (_threadSafe)
{
lock (_lock)
{
return DoSample();
}
}
return DoSample();
}
/// <summary>
/// Thread safe version of <seealso cref="DoSample"/> which returns a random number between 0.0 and 1.0.
/// </summary>
/// <returns>A double-precision floating point number greater than or equal to 0.0, and less than 1.0</returns>
private double ThreadSafeSample()
double ThreadSafeSample()
{
lock (_lock)
{
@ -191,6 +258,9 @@ namespace MathNet.Numerics.Random
/// <returns>
/// A double-precision floating point number greater than or equal to 0.0, and less than 1.0.
/// </returns>
protected abstract double DoSample();
protected virtual double DoSample()
{
return base.Sample();
}
}
}
}

46
src/Numerics/Random/WH1982.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2010 Math.NET
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -28,8 +28,6 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
namespace MathNet.Numerics.Random
{
/// <summary>
@ -38,33 +36,32 @@ namespace MathNet.Numerics.Random
/// <remarks>See: Wichmann, B. A. &amp; Hill, I. D. (1982), "Algorithm AS 183:
/// An efficient and portable pseudo-random number generator". Applied Statistics 31 (1982) 188-190
///</remarks>
public class WH1982 : AbstractRandomNumberGenerator
public class WH1982 : RandomSource
{
private const uint Modx = 30269;
private const double ModxRecip = 1.0/Modx;
private const uint Mody = 30307;
private const double ModyRecip = 1.0/Mody;
private const uint Modz = 30323;
private const double ModzRecip = 1.0/Modz;
private uint _xn;
private uint _yn = 1;
private uint _zn = 1;
const uint Modx = 30269;
const double ModxRecip = 1.0/Modx;
const uint Mody = 30307;
const double ModyRecip = 1.0/Mody;
const uint Modz = 30323;
const double ModzRecip = 1.0/Modz;
uint _xn;
uint _yn = 1;
uint _zn = 1;
/// <summary>
/// Initializes a new instance of the <see cref="WH1982"/> class using
/// the current time as the seed.
/// a seed based on time and unique GUIDs.
/// </summary>
public WH1982() : this((int) DateTime.Now.Ticks)
public WH1982() : this(RandomSeed.Guid())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="WH1982"/> class using
/// the current time as the seed.
/// a seed based on time and unique GUIDs.
/// </summary>
/// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param>
public WH1982(bool threadSafe)
: this((int) DateTime.Now.Ticks, threadSafe)
public WH1982(bool threadSafe) : this(RandomSeed.Guid(), threadSafe)
{
}
@ -75,8 +72,13 @@ namespace MathNet.Numerics.Random
/// <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 WH1982(int seed) : this(seed, Control.ThreadSafeRandomNumberGenerators)
public WH1982(int seed)
{
if (seed == 0)
{
seed = 1;
}
_xn = (uint)seed%Modx;
}
/// <summary>
@ -92,7 +94,7 @@ namespace MathNet.Numerics.Random
{
seed = 1;
}
_xn = (uint) seed%Modx;
_xn = (uint)seed%Modx;
}
/// <summary>
@ -108,8 +110,8 @@ namespace MathNet.Numerics.Random
_zn = (170*_zn)%Modz;
double w = _xn*ModxRecip + _yn*ModyRecip + _zn*ModzRecip;
w -= (int) w;
w -= (int)w;
return w;
}
}
}
}

55
src/Numerics/Random/WH2006.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2010 Math.NET
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -28,8 +28,6 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
namespace MathNet.Numerics.Random
{
/// <summary>
@ -38,36 +36,35 @@ namespace MathNet.Numerics.Random
/// <remarks>See: Wichmann, B. A. &amp; Hill, I. D. (2006), "Generating good pseudo-random numbers".
/// Computational Statistics &amp; Data Analysis 51:3 (2006) 1614-1622
/// </remarks>
public class WH2006 : AbstractRandomNumberGenerator
public class WH2006 : RandomSource
{
private const uint Modw = 2147483123;
private const double ModwRecip = 1.0/Modw;
private const uint Modx = 2147483579;
private const double ModxRecip = 1.0/Modx;
private const uint Mody = 2147483543;
private const double ModyRecip = 1.0/Mody;
private const uint Modz = 2147483423;
private const double ModzRecip = 1.0/Modz;
private ulong _wn = 1;
private ulong _xn;
private ulong _yn = 1;
private ulong _zn = 1;
const uint Modw = 2147483123;
const double ModwRecip = 1.0/Modw;
const uint Modx = 2147483579;
const double ModxRecip = 1.0/Modx;
const uint Mody = 2147483543;
const double ModyRecip = 1.0/Mody;
const uint Modz = 2147483423;
const double ModzRecip = 1.0/Modz;
ulong _wn = 1;
ulong _xn;
ulong _yn = 1;
ulong _zn = 1;
/// <summary>
/// Initializes a new instance of the <see cref="WH2006"/> class using
/// the current time as the seed.
/// a seed based on time and unique GUIDs.
/// </summary>
public WH2006() : this((int) DateTime.Now.Ticks)
public WH2006() : this(RandomSeed.Guid())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="WH2006"/> class using
/// the current time as the seed.
/// a seed based on time and unique GUIDs.
/// </summary>
/// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param>
public WH2006(bool threadSafe)
: this((int) DateTime.Now.Ticks, threadSafe)
public WH2006(bool threadSafe) : this(RandomSeed.Guid(), threadSafe)
{
}
@ -78,8 +75,13 @@ namespace MathNet.Numerics.Random
/// <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 WH2006(int seed) : this(seed, Control.ThreadSafeRandomNumberGenerators)
public WH2006(int seed)
{
if (seed == 0)
{
seed = 1;
}
_xn = (uint)seed%Modx;
}
/// <summary>
@ -88,14 +90,13 @@ namespace MathNet.Numerics.Random
/// <param name="seed">The seed value.</param>
/// <remarks>The seed is set to 1, if the zero is used as the seed.</remarks>
/// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param>
public WH2006(int seed, bool threadSafe)
: base(threadSafe)
public WH2006(int seed, bool threadSafe) : base(threadSafe)
{
if (seed == 0)
{
seed = 1;
}
_xn = (uint) seed%Modx;
_xn = (uint)seed%Modx;
}
/// <summary>
@ -112,8 +113,8 @@ namespace MathNet.Numerics.Random
_wn = 33000*_wn%Modw;
double u = _xn*ModxRecip + _yn*ModyRecip + _zn*ModzRecip + _wn*ModwRecip;
u -= (int) u;
u -= (int)u;
return u;
}
}
}
}

57
src/Numerics/Random/Xorshift.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2010 Math.NET
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -28,8 +28,8 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using MathNet.Numerics.Properties;
using System;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.Random
{
@ -38,61 +38,61 @@ namespace MathNet.Numerics.Random
/// <code>Xn = a * Xn−3 + c mod 2^32</code>
/// http://www.jstatsoft.org/v08/i14/paper
/// </summary>
public class Xorshift : AbstractRandomNumberGenerator
public class Xorshift : RandomSource
{
/// <summary>
/// The default value for X1.
/// </summary>
private const uint YSeed = 362436069;
const uint YSeed = 362436069;
/// <summary>
/// The default value for X2.
/// </summary>
private const uint ZSeed = 77465321;
const uint ZSeed = 77465321;
/// <summary>
/// The default value for the multiplier.
/// </summary>
private const uint ASeed = 916905990;
const uint ASeed = 916905990;
/// <summary>
/// The default value for the carry over.
/// </summary>
private const uint CSeed = 13579;
const uint CSeed = 13579;
/// <summary>
/// The multiplier to compute a double-precision floating point number [0, 1)
/// </summary>
private const double UlongToDoubleMultiplier = 1.0 / (uint.MaxValue + 1.0);
const double UlongToDoubleMultiplier = 1.0/(uint.MaxValue + 1.0);
/// <summary>
/// Seed or last but three unsigned random number.
/// </summary>
private ulong _x;
ulong _x;
/// <summary>
/// Last but two unsigned random number.
/// </summary>
private ulong _y;
ulong _y;
/// <summary>
/// Last but one unsigned random number.
/// </summary>
private ulong _z;
ulong _z;
/// <summary>
/// The value of the carry over.
/// </summary>
private ulong _c;
ulong _c;
/// <summary>
/// The multiplier.
/// </summary>
private readonly ulong _a;
readonly ulong _a;
/// <summary>
/// Initializes a new instance of the <see cref="Xorshift"/> class using
/// the current time as the seed.
/// a seed based on time and unique GUIDs.
/// </summary>
/// <remarks>If the seed value is zero, it is set to one. Uses the
/// value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to
@ -104,13 +104,13 @@ namespace MathNet.Numerics.Random
/// <item>X1 = 77465321</item>
/// <item>X2 = 362436069</item>
/// </list></remarks>
public Xorshift() : this((int)DateTime.Now.Ticks)
public Xorshift() : this(RandomSeed.Guid())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Xorshift"/> class using
/// the current time as the seed.
/// a seed based on time and unique GUIDs.
/// </summary>
/// <param name="a">The multiply value</param>
/// <param name="c">The initial carry value.</param>
@ -121,14 +121,13 @@ namespace MathNet.Numerics.Random
/// set whether the instance is thread safe.
/// Note: <paramref name="c"/> must be less than <paramref name="a"/>.
/// </remarks>
public Xorshift(long a, long c, long x1, long x2)
: this((int)DateTime.Now.Ticks, a, c, x1, x2)
public Xorshift(long a, long c, long x1, long x2) : this(RandomSeed.Guid(), a, c, x1, x2)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Xorshift"/> class using
/// the current time as the seed.
/// a seed based on time and unique GUIDs.
/// </summary>
/// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param>
/// <remarks>
@ -139,14 +138,13 @@ namespace MathNet.Numerics.Random
/// <item>X1 = 77465321</item>
/// <item>X2 = 362436069</item>
/// </list></remarks>
public Xorshift(bool threadSafe)
: this((int)DateTime.Now.Ticks, threadSafe)
public Xorshift(bool threadSafe) : this(RandomSeed.Guid(), threadSafe)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Xorshift"/> class using
/// the current time as the seed.
/// a seed based on time and unique GUIDs.
/// </summary>
/// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param>
/// <param name="a">The multiply value</param>
@ -154,11 +152,10 @@ namespace MathNet.Numerics.Random
/// <param name="x1">The initial value if X1.</param>
/// <param name="x2">The initial value if X2.</param>
/// <remarks><paramref name="c"/> must be less than <paramref name="a"/>.</remarks>
public Xorshift(bool threadSafe, long a, long c, long x1, long x2)
: this((int)DateTime.Now.Ticks, threadSafe, a, c, x1, x2)
public Xorshift(bool threadSafe, long a, long c, long x1, long x2) : this(RandomSeed.Guid(), threadSafe, a, c, x1, x2)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Xorshift"/> class.
/// </summary>
@ -189,8 +186,7 @@ namespace MathNet.Numerics.Random
/// <param name="x1">The initial value if X1.</param>
/// <param name="x2">The initial value if X2.</param>
/// <remarks><paramref name="c"/> must be less than <paramref name="a"/>.</remarks>
public Xorshift(int seed, long a, long c, long x1, long x2)
: this(seed, Control.ThreadSafeRandomNumberGenerators, a, c, x1, x2)
public Xorshift(int seed, long a, long c, long x1, long x2) : this(seed, Control.ThreadSafeRandomNumberGenerators, a, c, x1, x2)
{
}
@ -231,8 +227,7 @@ namespace MathNet.Numerics.Random
/// <param name="x1">The initial value if X1.</param>
/// <param name="x2">The initial value if X2.</param>
/// <remarks><paramref name="c"/> must be less than <paramref name="a"/>.</remarks>
public Xorshift(int seed, bool threadSafe, long a, long c, long x1, long x2)
: base(threadSafe)
public Xorshift(int seed, bool threadSafe, long a, long c, long x1, long x2) : base(threadSafe)
{
if (seed == 0)
{
@ -259,12 +254,12 @@ namespace MathNet.Numerics.Random
/// </returns>
protected override double DoSample()
{
var t = (_a * _x) + _c;
var t = (_a*_x) + _c;
_x = _y;
_y = _z;
_c = t >> 32;
_z = t & 0xffffffff;
return _z * UlongToDoubleMultiplier;
return _z*UlongToDoubleMultiplier;
}
}
}

6
src/UnitTests/Random/SystemCryptoTests.cs

@ -34,13 +34,13 @@ namespace MathNet.Numerics.UnitTests.Random
/// Tests for a random number generator based on the <see cref="System.Security.Cryptography.RandomNumberGenerator"/> class in the .NET library
/// </summary>
[TestFixture, Category("Random")]
public class SystemCryptoRandomNumberGeneratorTests : RandomTests
public class CryptoRandomSourceTests : RandomTests
{
/// <summary>
/// Initializes a new instance of the SystemCryptoRandomNumberGeneratorTests class.
/// </summary>
public SystemCryptoRandomNumberGeneratorTests()
: base(typeof(SystemCryptoRandomNumberGenerator))
public CryptoRandomSourceTests()
: base(typeof(CryptoRandomSource))
{
}
}

Loading…
Cancel
Save