Browse Source

Random: rework

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

4
src/FSharp/Random.fs

@ -43,8 +43,8 @@ module Random =
#if PORTABLE #if PORTABLE
#else #else
/// Creates a default .Net cryptographic system pRNG /// Creates a default .Net cryptographic system pRNG
let crypto () = new SystemCryptoRandomNumberGenerator() :> System.Random let crypto () = new CryptoRandomSource() :> System.Random
let cryptoWith (threadSafe:bool) = new SystemCryptoRandomNumberGenerator(threadSafe) :> System.Random let cryptoWith (threadSafe:bool) = new CryptoRandomSource(threadSafe) :> System.Random
#endif #endif
/// Creates a Mersenne Twister 19937 pRNG with a custom seed based on uinque GUIDs /// 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> <DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon> <DependentUpon>Resources.resx</DependentUpon>
</Compile> </Compile>
<Compile Include="Random\AbstractRandomNumberGenerator.cs" /> <Compile Include="Random\RandomSource.cs" />
<Compile Include="Random\Mcg31m1.cs" /> <Compile Include="Random\Mcg31m1.cs" />
<Compile Include="Random\Mcg59.cs" /> <Compile Include="Random\Mcg59.cs" />
<Compile Include="Random\MersenneTwister.cs" /> <Compile Include="Random\MersenneTwister.cs" />
<Compile Include="Random\Mrg32k3a.cs" /> <Compile Include="Random\Mrg32k3a.cs" />
<Compile Include="Random\Palf.cs" /> <Compile Include="Random\Palf.cs" />
<Compile Include="Random\SystemCrypto.cs" /> <Compile Include="Random\CryptoRandomSource.cs" />
<Compile Include="Random\SystemRandomExtensions.cs" /> <Compile Include="Random\RandomExtensions.cs" />
<Compile Include="Random\WH1982.cs" /> <Compile Include="Random\WH1982.cs" />
<Compile Include="Random\WH2006.cs" /> <Compile Include="Random\WH2006.cs" />
<Compile Include="Random\Xorshift.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://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -38,19 +38,19 @@ namespace MathNet.Numerics.Random
/// <summary> /// <summary>
/// A random number generator based on the <see cref="System.Security.Cryptography.RandomNumberGenerator"/> class in the .NET library. /// A random number generator based on the <see cref="System.Security.Cryptography.RandomNumberGenerator"/> class in the .NET library.
/// </summary> /// </summary>
public class SystemCryptoRandomNumberGenerator : AbstractRandomNumberGenerator, IDisposable public class CryptoRandomSource : RandomSource, IDisposable
{ {
private const double Reciprocal = 1.0 / uint.MaxValue; const double Reciprocal = 1.0/uint.MaxValue;
private readonly RandomNumberGenerator _random; readonly RandomNumberGenerator _crypto;
/// <summary> /// <summary>
/// Construct a new random number generator with a random seed. /// Construct a new random number generator with a random seed.
/// </summary> /// </summary>
/// <remarks>Uses <see cref="System.Security.Cryptography.RNGCryptoServiceProvider"/> and uses the value of /// <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> /// <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> /// <summary>
@ -58,8 +58,9 @@ namespace MathNet.Numerics.Random
/// </summary> /// </summary>
/// <param name="rng">The <see cref="RandomNumberGenerator"/> to use.</param> /// <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> /// <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> /// <summary>
@ -67,8 +68,9 @@ namespace MathNet.Numerics.Random
/// </summary> /// </summary>
/// <remarks>Uses <see cref="System.Security.Cryptography.RNGCryptoServiceProvider"/></remarks> /// <remarks>Uses <see cref="System.Security.Cryptography.RNGCryptoServiceProvider"/></remarks>
/// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param> /// <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> /// <summary>
@ -76,13 +78,9 @@ namespace MathNet.Numerics.Random
/// </summary> /// </summary>
/// <param name="rng">The <see cref="RandomNumberGenerator"/> to use.</param> /// <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> /// <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) _crypto = rng;
{
throw new ArgumentNullException("rng");
}
_random = rng;
} }
@ -95,14 +93,14 @@ namespace MathNet.Numerics.Random
protected override double DoSample() protected override double DoSample()
{ {
var bytes = new byte[4]; var bytes = new byte[4];
_random.GetBytes(bytes); _crypto.GetBytes(bytes);
return BitConverter.ToUInt32(bytes, 0) * Reciprocal; return BitConverter.ToUInt32(bytes, 0)*Reciprocal;
} }
public void Dispose() public void Dispose()
{ {
#if !NET35 #if !NET35
_random.Dispose(); _crypto.Dispose();
#endif #endif
} }
} }

34
src/Numerics/Random/Mcg31m1.cs

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

41
src/Numerics/Random/Mcg59.cs

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

62
src/Numerics/Random/MersenneTwister.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -66,7 +66,6 @@
email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
*/ */
using System;
using System.Threading; using System.Threading;
namespace MathNet.Numerics.Random namespace MathNet.Numerics.Random
@ -74,70 +73,70 @@ namespace MathNet.Numerics.Random
/// <summary> /// <summary>
/// Random number generator using Mersenne Twister 19937 algorithm. /// Random number generator using Mersenne Twister 19937 algorithm.
/// </summary> /// </summary>
public class MersenneTwister : AbstractRandomNumberGenerator, IDisposable public class MersenneTwister : RandomSource
{ {
/// <summary> /// <summary>
/// Mersenne twister constant. /// Mersenne twister constant.
/// </summary> /// </summary>
private const uint LowerMask = 0x7fffffff; const uint LowerMask = 0x7fffffff;
/// <summary> /// <summary>
/// Mersenne twister constant. /// Mersenne twister constant.
/// </summary> /// </summary>
private const int M = 397; const int M = 397;
/// <summary> /// <summary>
/// Mersenne twister constant. /// Mersenne twister constant.
/// </summary> /// </summary>
private const uint MatrixA = 0x9908b0df; const uint MatrixA = 0x9908b0df;
/// <summary> /// <summary>
/// Mersenne twister constant. /// Mersenne twister constant.
/// </summary> /// </summary>
private const int N = 624; const int N = 624;
/// <summary> /// <summary>
/// Mersenne twister constant. /// Mersenne twister constant.
/// </summary> /// </summary>
private const double Reciprocal = 1.0/4294967296.0; const double Reciprocal = 1.0/4294967296.0;
/// <summary> /// <summary>
/// Mersenne twister constant. /// Mersenne twister constant.
/// </summary> /// </summary>
private const uint UpperMask = 0x80000000; const uint UpperMask = 0x80000000;
/// <summary> /// <summary>
/// Mersenne twister constant. /// Mersenne twister constant.
/// </summary> /// </summary>
private static readonly uint[] Mag01 = {0x0U, MatrixA}; static readonly uint[] Mag01 = { 0x0U, MatrixA };
/// <summary> /// <summary>
/// Mersenne twister constant. /// Mersenne twister constant.
/// </summary> /// </summary>
private readonly uint[] _mt = new uint[624]; readonly uint[] _mt = new uint[624];
/// <summary> /// <summary>
/// Mersenne twister constant. /// Mersenne twister constant.
/// </summary> /// </summary>
private int _mti = N + 1; int _mti = N + 1;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="MersenneTwister"/> class using /// 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> /// </summary>
/// <remarks>If the seed value is zero, it is set to one. Uses the /// <remarks>If the seed value is zero, it is set to one. Uses the
/// value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to /// value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to
/// set whether the instance is thread safe.</remarks> /// set whether the instance is thread safe.</remarks>
public MersenneTwister() : this((int) DateTime.Now.Ticks) public MersenneTwister() : this(RandomSeed.Guid())
{ {
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="MersenneTwister"/> class using /// 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> /// </summary>
/// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param> /// <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> /// <param name="seed">The seed value.</param>
/// <remarks>Uses the value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to /// <remarks>Uses the value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to
/// set whether the instance is thread safe.</remarks> /// 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> /// <summary>
@ -190,7 +190,7 @@ namespace MathNet.Numerics.Random
get { return DefaultInstance.Value; } get { return DefaultInstance.Value; }
} }
#endif #endif
/*/// <summary> /*/// <summary>
/// Initializes a new instance of the <see cref="MersenneTwister"/> class. /// Initializes a new instance of the <see cref="MersenneTwister"/> class.
/// </summary> /// </summary>
@ -211,12 +211,12 @@ namespace MathNet.Numerics.Random
*/ */
/* initializes _mt[_n] with a seed */ /* initializes _mt[_n] with a seed */
private void init_genrand(uint s) void init_genrand(uint s)
{ {
_mt[0] = s & 0xffffffff; _mt[0] = s & 0xffffffff;
for (_mti = 1; _mti < N; _mti++) 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. */ /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
/* In the previous versions, MSBs of the seed affect */ /* In the previous versions, MSBs of the seed affect */
/* only MSBs of the array _mt[]. */ /* only MSBs of the array _mt[]. */
@ -231,7 +231,7 @@ namespace MathNet.Numerics.Random
/* init_key is the array for initializing keys */ /* init_key is the array for initializing keys */
/* slight change for C++, 2004/2/26 */ /* 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; uint key_length = (uint) init_key.Length;
init_genrand(19650218); init_genrand(19650218);
@ -268,7 +268,7 @@ namespace MathNet.Numerics.Random
/* generates a random number on [0,0xffffffff]-interval */ /* generates a random number on [0,0xffffffff]-interval */
private uint genrand_int32() uint genrand_int32()
{ {
uint y; uint y;
@ -317,10 +317,10 @@ namespace MathNet.Numerics.Random
/// </returns> /// </returns>
protected override double DoSample() 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. /// Generates a random number on [0,1) with 53-bit resolution.
/// </summary> /// </summary>
/// <returns>A random number on [0,1) with 53-bit resolution.</returns> /// <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; ulong a = genrand_int32() >> 5, b = genrand_int32() >> 6;
return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0); 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://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // 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. /// A 32-bit combined multiple recursive generator with 2 components of order 3.
/// </summary> /// </summary>
///<remarks>Based off of P. L'Ecuyer, "Combined Multiple Recursive Random Number Generators," Operations Research, 44, 5 (1996), 816--822. </remarks> ///<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; const double A12 = 1403580;
private const double A13 = 810728; const double A13 = 810728;
private const double A21 = 527612; const double A21 = 527612;
private const double A23 = 1370589; const double A23 = 1370589;
private const double Modulus1 = 4294967087; const double Modulus1 = 4294967087;
private const double Modulus2 = 4294944443; const double Modulus2 = 4294944443;
private const double Reciprocal = 1.0 / Modulus1; const double Reciprocal = 1.0/Modulus1;
private double _xn1 = 1; double _xn1 = 1;
private double _xn2 = 1; double _xn2 = 1;
private double _xn3; double _xn3;
private double _yn1 = 1; double _yn1 = 1;
private double _yn2 = 1; double _yn2 = 1;
private double _yn3 = 1; double _yn3 = 1;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Mcg31m1"/> class using /// 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> /// </summary>
/// <remarks>If the seed value is zero, it is set to one. Uses the /// <remarks>If the seed value is zero, it is set to one. Uses the
/// value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to /// value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to
/// set whether the instance is thread safe.</remarks> /// set whether the instance is thread safe.</remarks>
public Mrg32k3a() : this((int)DateTime.Now.Ticks) public Mrg32k3a() : this(RandomSeed.Guid())
{ {
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Mcg31m1"/> class using /// 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> /// </summary>
/// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param> /// <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 /// <remarks>If the seed value is zero, it is set to one. Uses the
/// value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to /// value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to
/// set whether the instance is thread safe.</remarks> /// 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> /// <summary>
@ -108,7 +113,7 @@ namespace MathNet.Numerics.Random
protected override double DoSample() protected override double DoSample()
{ {
double xn = A12*_xn2 - A13*_xn3; double xn = A12*_xn2 - A13*_xn3;
double k = (long) (xn/Modulus1); double k = (long)(xn/Modulus1);
xn -= k*Modulus1; xn -= k*Modulus1;
if (xn < 0) if (xn < 0)
{ {
@ -116,7 +121,7 @@ namespace MathNet.Numerics.Random
} }
double yn = A21*_yn1 - A23*_yn3; double yn = A21*_yn1 - A23*_yn3;
k = (long) (yn/Modulus2); k = (long)(yn/Modulus2);
yn -= k*Modulus2; yn -= k*Modulus2;
if (yn < 0) if (yn < 0)
{ {
@ -136,4 +141,4 @@ namespace MathNet.Numerics.Random
return (xn - yn)*Reciprocal; 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 /// 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>. /// <a href="http://en.wikipedia.org/wiki/Lagged_Fibonacci_generator">Wikipedia - Lagged Fibonacci generator</a>.
/// </remarks> /// </remarks>
public class Palf : AbstractRandomNumberGenerator public class Palf : RandomSource
{ {
/// <summary> /// <summary>
/// Default value for the ShortLag /// Default value for the ShortLag
@ -62,23 +62,21 @@ namespace MathNet.Numerics.Random
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Palf"/> class using /// 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> /// </summary>
/// <remarks>If the seed value is zero, it is set to one. Uses the /// <remarks>If the seed value is zero, it is set to one. Uses the
/// value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to /// value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to
/// set whether the instance is thread safe.</remarks> /// set whether the instance is thread safe.</remarks>
public Palf() public Palf() : this(RandomSeed.Guid(), Control.ThreadSafeRandomNumberGenerators, DefaultShortLag, DefaultLongLag)
: this((int) DateTime.Now.Ticks)
{ {
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Palf"/> class using /// 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> /// </summary>
/// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param> /// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param>
public Palf(bool threadSafe) public Palf(bool threadSafe) : this(RandomSeed.Guid(), threadSafe, DefaultShortLag, DefaultLongLag)
: this((int) DateTime.Now.Ticks, 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 /// <remarks>If the seed value is zero, it is set to one. Uses the
/// value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to /// value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to
/// set whether the instance is thread safe.</remarks> /// set whether the instance is thread safe.</remarks>
public Palf(int seed) public Palf(int seed) : this(seed, Control.ThreadSafeRandomNumberGenerators, DefaultShortLag, DefaultLongLag)
: 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="threadSafe">if set to <c>true</c>, the class is thread safe.</param>
/// <param name="shortLag">The ShortLag value</param> /// <param name="shortLag">The ShortLag value</param>
/// <param name="longLag">TheLongLag value</param> /// <param name="longLag">TheLongLag value</param>
public Palf(int seed, bool threadSafe, int shortLag, int longLag) public Palf(int seed, bool threadSafe, int shortLag, int longLag) : base(threadSafe)
: base(threadSafe)
{ {
if (shortLag < 1) if (shortLag < 1)
{ {
@ -135,7 +131,7 @@ namespace MathNet.Numerics.Random
var gen = new MersenneTwister(seed, threadSafe); var gen = new MersenneTwister(seed, threadSafe);
for (var j = 0; j < LongLag; ++j) for (var j = 0; j < LongLag; ++j)
{ {
_x[j] = (uint) (gen.NextDouble()*uint.MaxValue); _x[j] = (uint)(gen.NextDouble()*uint.MaxValue);
} }
_i = LongLag; _i = LongLag;
@ -171,21 +167,21 @@ namespace MathNet.Numerics.Random
void Fill() void Fill()
{ {
CommonParallel.For(0, Control.NumberOfParallelWorkerThreads, (u, v) => 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 _x[j] += _x[j - ShortLag - index];
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];
}
} }
}); }
});
_i = 0; _i = 0;
} }
@ -203,7 +199,7 @@ namespace MathNet.Numerics.Random
} }
var x = _x[_i++]; 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 /// 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. /// pseudo-random distributed numbers for types other than double and int32.
/// </summary> /// </summary>
public static class SystemRandomExtensions public static class RandomExtensions
{ {
/// <summary> /// <summary>
/// Returns a nonnegative random number less than <see cref="Int64.MaxValue"/>. /// 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://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -28,52 +28,63 @@
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
// </copyright> // </copyright>
using System;
using MathNet.Numerics.Properties; using MathNet.Numerics.Properties;
namespace MathNet.Numerics.Random namespace MathNet.Numerics.Random
{ {
using System;
/// <summary> /// <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. /// 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> /// </summary>
public abstract class AbstractRandomNumberGenerator : Random public class RandomSource : System.Random
{ {
/// <summary> readonly bool _threadSafe;
/// A delegate type that represents a method that generates random numbers. readonly object _lock = new object();
/// </summary>
/// <returns>Randomly distributed numbers.</returns>
private delegate double SampleMethod();
/// <summary> /// <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> /// </summary>
private readonly SampleMethod _sampleMethod; public RandomSource() : base(RandomSeed.Guid())
{
_threadSafe = Control.ThreadSafeRandomNumberGenerators;
}
/// <summary> /// <summary>
/// The object that will be locked for thread safety. /// Initializes a new instance of the <see cref="RandomSource"/> class.
/// </summary> /// </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> /// <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 value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to set whether
/// the instance is thread safe or not. /// the instance is thread safe or not.
/// </summary> /// </summary>
protected AbstractRandomNumberGenerator() : this(Control.ThreadSafeRandomNumberGenerators) /// <param name="systemRandomSeed">The seed value.</param>
public RandomSource(int systemRandomSeed) : base(systemRandomSeed)
{ {
_threadSafe = Control.ThreadSafeRandomNumberGenerators;
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="AbstractRandomNumberGenerator"/> class. /// Initializes a new instance of the <see cref="RandomSource"/> class.
/// </summary> /// </summary>
/// <param name="systemRandomSeed">The seed value.</param>
/// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</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 /// <remarks>Thread safe instances are two and half times slower than non-thread
/// safe classes.</remarks> /// safe classes.</remarks>
protected AbstractRandomNumberGenerator(bool threadSafe) public RandomSource(int systemRandomSeed, bool threadSafe) : base(systemRandomSeed)
{ {
_sampleMethod = threadSafe ? (SampleMethod)ThreadSafeSample : DoSample; _threadSafe = threadSafe;
} }
/// <summary> /// <summary>
@ -84,7 +95,7 @@ namespace MathNet.Numerics.Random
/// An array of uniformly distributed random doubles in the interval [0.0,1.0]. /// An array of uniformly distributed random doubles in the interval [0.0,1.0].
/// </returns> /// </returns>
/// <exception cref="ArgumentException">if n is not greater than 0.</exception> /// <exception cref="ArgumentException">if n is not greater than 0.</exception>
public double[] NextDouble(int n) public double[] NextDoubles(int n)
{ {
if (n < 1) if (n < 1)
{ {
@ -92,11 +103,23 @@ namespace MathNet.Numerics.Random
} }
var ret = new double[n]; 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; return ret;
} }
@ -106,9 +129,17 @@ namespace MathNet.Numerics.Random
/// <returns> /// <returns>
/// A 32-bit signed integer greater than or equal to zero and less than <see cref="F:System.Int32.MaxValue"/>. /// A 32-bit signed integer greater than or equal to zero and less than <see cref="F:System.Int32.MaxValue"/>.
/// </returns> /// </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> /// <summary>
@ -117,14 +148,22 @@ namespace MathNet.Numerics.Random
/// <param name="maxValue">The exclusive upper bound of the random number returned.</param> /// <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> /// <returns>A 32-bit signed integer less than <paramref name="maxValue"/>.</returns>
/// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="maxValue"/> is negative. </exception> /// <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) if (maxValue <= 0)
{ {
throw new ArgumentOutOfRangeException(Resources.ArgumentMustBePositive); throw new ArgumentOutOfRangeException(Resources.ArgumentMustBePositive);
} }
return (int)(Sample() * maxValue); if (_threadSafe)
{
lock (_lock)
{
return (int)(DoSample()*maxValue);
}
}
return (int)(DoSample()*maxValue);
} }
/// <summary> /// <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. /// 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> /// </returns>
/// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="minValue"/> is greater than <paramref name="maxValue"/>. </exception> /// <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) if (minValue > maxValue)
{ {
throw new ArgumentOutOfRangeException(Resources.ArgumentMinValueGreaterThanMaxValue); 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> /// <summary>
@ -158,9 +205,21 @@ namespace MathNet.Numerics.Random
throw new ArgumentNullException("buffer"); 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++) 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> /// <returns>A double-precision floating point number greater than or equal to 0.0, and less than 1.0.</returns>
protected override double Sample() protected override double Sample()
{ {
return _sampleMethod(); if (_threadSafe)
{
lock (_lock)
{
return DoSample();
}
}
return DoSample();
} }
/// <summary> /// <summary>
/// Thread safe version of <seealso cref="DoSample"/> which returns a random number between 0.0 and 1.0. /// Thread safe version of <seealso cref="DoSample"/> which returns a random number between 0.0 and 1.0.
/// </summary> /// </summary>
/// <returns>A double-precision floating point number greater than or equal to 0.0, and less than 1.0</returns> /// <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) lock (_lock)
{ {
@ -191,6 +258,9 @@ namespace MathNet.Numerics.Random
/// <returns> /// <returns>
/// A double-precision floating point number greater than or equal to 0.0, and less than 1.0. /// A double-precision floating point number greater than or equal to 0.0, and less than 1.0.
/// </returns> /// </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://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -28,8 +28,6 @@
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
// </copyright> // </copyright>
using System;
namespace MathNet.Numerics.Random namespace MathNet.Numerics.Random
{ {
/// <summary> /// <summary>
@ -38,33 +36,32 @@ namespace MathNet.Numerics.Random
/// <remarks>See: Wichmann, B. A. &amp; Hill, I. D. (1982), "Algorithm AS 183: /// <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 /// An efficient and portable pseudo-random number generator". Applied Statistics 31 (1982) 188-190
///</remarks> ///</remarks>
public class WH1982 : AbstractRandomNumberGenerator public class WH1982 : RandomSource
{ {
private const uint Modx = 30269; const uint Modx = 30269;
private const double ModxRecip = 1.0/Modx; const double ModxRecip = 1.0/Modx;
private const uint Mody = 30307; const uint Mody = 30307;
private const double ModyRecip = 1.0/Mody; const double ModyRecip = 1.0/Mody;
private const uint Modz = 30323; const uint Modz = 30323;
private const double ModzRecip = 1.0/Modz; const double ModzRecip = 1.0/Modz;
private uint _xn; uint _xn;
private uint _yn = 1; uint _yn = 1;
private uint _zn = 1; uint _zn = 1;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="WH1982"/> class using /// 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> /// </summary>
public WH1982() : this((int) DateTime.Now.Ticks) public WH1982() : this(RandomSeed.Guid())
{ {
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="WH1982"/> class using /// 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> /// </summary>
/// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param> /// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param>
public WH1982(bool threadSafe) public WH1982(bool threadSafe) : this(RandomSeed.Guid(), threadSafe)
: this((int) DateTime.Now.Ticks, threadSafe)
{ {
} }
@ -75,8 +72,13 @@ namespace MathNet.Numerics.Random
/// <remarks>If the seed value is zero, it is set to one. Uses the /// <remarks>If the seed value is zero, it is set to one. Uses the
/// value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to /// value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to
/// set whether the instance is thread safe.</remarks> /// 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> /// <summary>
@ -92,7 +94,7 @@ namespace MathNet.Numerics.Random
{ {
seed = 1; seed = 1;
} }
_xn = (uint) seed%Modx; _xn = (uint)seed%Modx;
} }
/// <summary> /// <summary>
@ -108,8 +110,8 @@ namespace MathNet.Numerics.Random
_zn = (170*_zn)%Modz; _zn = (170*_zn)%Modz;
double w = _xn*ModxRecip + _yn*ModyRecip + _zn*ModzRecip; double w = _xn*ModxRecip + _yn*ModyRecip + _zn*ModzRecip;
w -= (int) w; w -= (int)w;
return w; return w;
} }
} }
} }

55
src/Numerics/Random/WH2006.cs

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

57
src/Numerics/Random/Xorshift.cs

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

Loading…
Cancel
Save