diff --git a/src/Numerics/Random/Mcg31m1.cs b/src/Numerics/Random/Mcg31m1.cs index a37b9b5b..e9d9e402 100644 --- a/src/Numerics/Random/Mcg31m1.cs +++ b/src/Numerics/Random/Mcg31m1.cs @@ -99,5 +99,25 @@ namespace MathNet.Numerics.Random _xn = (_xn*Multiplier)%Modulus; return ret; } + + /// + /// Returns an array of random numbers greater than or equal to 0.0 and less than 1.0. + /// + public static double[] Samples(int length, int seed) + { + if (seed == 0) + { + seed = 1; + } + ulong xn = (uint)seed%Modulus; + + var data = new double[length]; + for (int i = 0; i < data.Length; i++) + { + data[i] = xn*Reciprocal; + xn = (xn*Multiplier)%Modulus; + } + return data; + } } } diff --git a/src/Numerics/Random/Mcg59.cs b/src/Numerics/Random/Mcg59.cs index 099c0c43..0e5d2f01 100644 --- a/src/Numerics/Random/Mcg59.cs +++ b/src/Numerics/Random/Mcg59.cs @@ -101,5 +101,25 @@ namespace MathNet.Numerics.Random _xn = (_xn*Multiplier)%Modulus; return ret; } + + /// + /// Returns an array of random numbers greater than or equal to 0.0 and less than 1.0. + /// + public static double[] Samples(int length, int seed) + { + if (seed == 0) + { + seed = 1; + } + ulong xn = (uint)seed%Modulus; + + var data = new double[length]; + for (int i = 0; i < data.Length; i++) + { + data[i] = xn*Reciprocal; + xn = (xn*Multiplier)%Modulus; + } + return data; + } } } diff --git a/src/Numerics/Random/MersenneTwister.cs b/src/Numerics/Random/MersenneTwister.cs index 1c8efc2c..2aeeab7f 100644 --- a/src/Numerics/Random/MersenneTwister.cs +++ b/src/Numerics/Random/MersenneTwister.cs @@ -66,6 +66,7 @@ email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) */ +using System; using System.Threading; namespace MathNet.Numerics.Random @@ -113,7 +114,7 @@ namespace MathNet.Numerics.Random /// /// Mersenne twister constant. /// - readonly uint[] _mt = new uint[624]; + readonly uint[] _mt = new uint[N]; /// /// Mersenne twister constant. @@ -329,5 +330,58 @@ namespace MathNet.Numerics.Random ulong a = genrand_int32() >> 5, b = genrand_int32() >> 6; return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0); }*/ + + /// + /// Returns an array of random numbers greater than or equal to 0.0 and less than 1.0. + /// + public static double[] Samples(int length, int seed) + { + uint[] t = new uint[624]; + int k; + uint s = (uint)seed; + + t[0] = s & 0xffffffff; + for (k = 1; k < N; k++) + { + t[k] = (1812433253*(t[k - 1] ^ (t[k - 1] >> 30)) + (uint)k); + t[k] &= 0xffffffff; + } + + var data = new double[length]; + for (int i = 0; i < data.Length; i++) + { + uint y; + + if (k >= N) + { + int kk; + for (kk = 0; kk < N - M; kk++) + { + y = (t[kk] & UpperMask) | (t[kk + 1] & LowerMask); + t[kk] = t[kk + M] ^ (y >> 1) ^ Mag01[y & 0x1]; + } + for (; kk < N - 1; kk++) + { + y = (t[kk] & UpperMask) | (t[kk + 1] & LowerMask); + t[kk] = t[kk + (M - N)] ^ (y >> 1) ^ Mag01[y & 0x1]; + } + y = (t[N - 1] & UpperMask) | (t[0] & LowerMask); + t[N - 1] = t[M - 1] ^ (y >> 1) ^ Mag01[y & 0x1]; + + k = 0; + } + + y = t[k++]; + + /* Tempering */ + y ^= (y >> 11); + y ^= (y << 7) & 0x9d2c5680; + y ^= (y << 15) & 0xefc60000; + y ^= (y >> 18); + + data[i] = y*Reciprocal; + } + return data; + } } } diff --git a/src/Numerics/Random/Mrg32k3a.cs b/src/Numerics/Random/Mrg32k3a.cs index a8cd9a44..cba2ad6f 100644 --- a/src/Numerics/Random/Mrg32k3a.cs +++ b/src/Numerics/Random/Mrg32k3a.cs @@ -28,8 +28,6 @@ // OTHER DEALINGS IN THE SOFTWARE. // -using System; - namespace MathNet.Numerics.Random { /// @@ -140,5 +138,47 @@ namespace MathNet.Numerics.Random } return (xn - yn)*Reciprocal; } + + /// + /// Returns an array of random numbers greater than or equal to 0.0 and less than 1.0. + /// + public static double[] Samples(int length, int seed) + { + double x1 = 1; + double x2 = 1; + double x3 = (uint)seed; + double y1 = 1; + double y2 = 1; + double y3 = 1; + + var data = new double[length]; + for (int i = 0; i < data.Length; i++) + { + double xn = A12*x2 - A13*x3; + double k = (long)(xn/Modulus1); + xn -= k*Modulus1; + if (xn < 0) + { + xn += Modulus1; + } + + double yn = A21*y1 - A23*y3; + k = (long)(yn/Modulus2); + yn -= k*Modulus2; + if (yn < 0) + { + yn += Modulus2; + } + x3 = x2; + x2 = x1; + x1 = xn; + y3 = y2; + y2 = y1; + y1 = yn; + + data[i] = xn <= yn ? (xn - yn + Modulus1)*Reciprocal : (xn - yn)*Reciprocal; + } + return data; + } } } diff --git a/src/Numerics/Random/Palf.cs b/src/Numerics/Random/Palf.cs index efa4e036..7a0e8921 100644 --- a/src/Numerics/Random/Palf.cs +++ b/src/Numerics/Random/Palf.cs @@ -30,7 +30,6 @@ using System; using MathNet.Numerics.Properties; -using MathNet.Numerics.Threading; namespace MathNet.Numerics.Random { @@ -38,9 +37,9 @@ namespace MathNet.Numerics.Random /// Represents a Parallel Additive Lagged Fibonacci pseudo-random number generator. /// /// - /// The type bases upon the implementation in the + /// The type bases upon the implementation in the /// Boost Random Number Library. - /// It uses the modulus 232 and by default the "lags" 418 and 1279. Some popular pairs are presented on + /// It uses the modulus 232 and by default the "lags" 418 and 1279. Some popular pairs are presented on /// Wikipedia - Lagged Fibonacci generator. /// public class Palf : RandomSource @@ -91,6 +90,15 @@ namespace MathNet.Numerics.Random { } + /// + /// Initializes a new instance of the class. + /// + /// The seed value. + /// if set to true , the class is thread safe. + public Palf(int seed, bool threadSafe) : this(seed, threadSafe, DefaultShortLag, DefaultLongLag) + { + } + /// /// Initializes a new instance of the class. /// @@ -115,26 +123,21 @@ namespace MathNet.Numerics.Random seed = 1; } + _threads = Control.NumberOfParallelWorkerThreads; ShortLag = shortLag; - // Align LongLag to number of worker threads. - if (longLag%Control.NumberOfParallelWorkerThreads == 0) + // Align LongLag to number of worker threads. + if (longLag%_threads == 0) { LongLag = longLag; } else { - LongLag = ((longLag/Control.NumberOfParallelWorkerThreads) + 1)*Control.NumberOfParallelWorkerThreads; - } - - _x = new uint[LongLag]; - var gen = new MersenneTwister(seed, threadSafe); - for (var j = 0; j < LongLag; ++j) - { - _x[j] = (uint)(gen.NextDouble()*uint.MaxValue); + LongLag = ((longLag/_threads) + 1)*_threads; } - _i = LongLag; + _x = Generate.Map(MersenneTwister.Samples(LongLag, seed), uniform => (uint)(uniform*uint.MaxValue)); + _k = LongLag; } /// @@ -152,10 +155,12 @@ namespace MathNet.Numerics.Random /// readonly uint[] _x; + readonly int _threads; + /// /// Stores an index for the random number array element that will be accessed next. /// - int _i; + int _k; /// /// Fills the array with new unsigned random numbers. @@ -166,23 +171,38 @@ namespace MathNet.Numerics.Random /// void Fill() { - CommonParallel.For(0, Control.NumberOfParallelWorkerThreads, (u, v) => + //CommonParallel.For(0, Control.NumberOfParallelWorkerThreads, (u, v) => + //{ + // 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) + // { + // _x[j] += _x[j - ShortLag - index]; + // } + // } + //}); + + for (int index = 0; index < _threads; index++) { - for (int index = u; index < v; index++) + // Two loops to avoid costly modulo operations + for (var j = index; j < ShortLag; j = j + _threads) { - // Two loops to avoid costly modulo operations - for (var j = index; j < ShortLag; j = j + Control.NumberOfParallelWorkerThreads) - { - _x[j] += _x[j + (LongLag - ShortLag)]; - } + _x[j] += _x[j + (LongLag - ShortLag)]; + } - for (var j = ShortLag + index; j < LongLag; j = j + Control.NumberOfParallelWorkerThreads) - { - _x[j] += _x[j - ShortLag - index]; - } + for (var j = ShortLag + index; j < LongLag; j = j + _threads) + { + _x[j] += _x[j - ShortLag - index]; } - }); - _i = 0; + } + + _k = 0; } /// @@ -193,13 +213,62 @@ namespace MathNet.Numerics.Random /// protected override double DoSample() { - if (_i >= LongLag) + if (_k >= LongLag) { Fill(); } - var x = _x[_i++]; + var x = _x[_k++]; return (int)(x >> 1)*IntToDoubleMultiplier; } + + /// + /// Returns an array of random numbers greater than or equal to 0.0 and less than 1.0. + /// + public static double[] Samples(int length, int seed) + { + if (seed == 0) + { + seed = 1; + } + + int threads = Control.NumberOfParallelWorkerThreads; + const int shortLag = DefaultShortLag; + var longLag = DefaultLongLag; + + // Align LongLag to number of worker threads. + if (longLag%threads != 0) + { + longLag = ((longLag/threads) + 1)*threads; + } + + var x = Generate.Map(MersenneTwister.Samples(longLag, seed), uniform => (uint)(uniform*uint.MaxValue)); + var k = longLag; + + var data = new double[length]; + for (int i = 0; i < data.Length; i++) + { + if (k >= longLag) + { + for (int index = 0; index < threads; index++) + { + // Two loops to avoid costly modulo operations + for (var j = index; j < shortLag; j = j + threads) + { + x[j] += x[j + (longLag - shortLag)]; + } + + for (var j = shortLag + index; j < longLag; j = j + threads) + { + x[j] += x[j - shortLag - index]; + } + } + k = 0; + } + + data[i] = (int)(x[k++] >> 1)*IntToDoubleMultiplier; + } + return data; + } } } diff --git a/src/Numerics/Random/RandomExtensions.cs b/src/Numerics/Random/RandomExtensions.cs index e7af4a92..7d75253e 100644 --- a/src/Numerics/Random/RandomExtensions.cs +++ b/src/Numerics/Random/RandomExtensions.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,9 +28,10 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using System; + namespace MathNet.Numerics.Random { - using System; /// /// This class implements extension methods for the System.Random class. The extension methods generate @@ -49,9 +50,9 @@ namespace MathNet.Numerics.Random /// the range of return values includes 0 but not . /// /// - public static long NextInt64(this Random rnd) + public static long NextInt64(this System.Random rnd) { - var buffer = new byte[sizeof(long)]; + var buffer = new byte[sizeof (long)]; rnd.NextBytes(buffer); var candidate = BitConverter.ToInt64(buffer, 0); @@ -75,9 +76,9 @@ namespace MathNet.Numerics.Random /// and . /// /// - public static int NextFullRangeInt32(this Random rnd) + public static int NextFullRangeInt32(this System.Random rnd) { - var buffer = new byte[sizeof(int)]; + var buffer = new byte[sizeof (int)]; rnd.NextBytes(buffer); return BitConverter.ToInt32(buffer, 0); } @@ -93,9 +94,9 @@ namespace MathNet.Numerics.Random /// and . /// /// - public static long NextFullRangeInt64(this Random rnd) + public static long NextFullRangeInt64(this System.Random rnd) { - var buffer = new byte[sizeof(long)]; + var buffer = new byte[sizeof (long)]; rnd.NextBytes(buffer); return BitConverter.ToInt64(buffer, 0); } @@ -110,7 +111,7 @@ namespace MathNet.Numerics.Random /// A decimal floating point number greater than or equal to 0.0, and less than 1.0; that is, /// the range of return values includes 0.0 but not 1.0. /// - public static decimal NextDecimal(this Random rnd) + public static decimal NextDecimal(this System.Random rnd) { decimal candidate; @@ -125,8 +126,7 @@ namespace MathNet.Numerics.Random rnd.NextFullRangeInt32(), false, 28); - } - while (candidate >= 1.0m); + } while (candidate >= 1.0m); return candidate; } diff --git a/src/Numerics/Random/WH1982.cs b/src/Numerics/Random/WH1982.cs index 5b64e386..476f3827 100644 --- a/src/Numerics/Random/WH1982.cs +++ b/src/Numerics/Random/WH1982.cs @@ -113,5 +113,31 @@ namespace MathNet.Numerics.Random w -= (int)w; return w; } + + /// + /// Returns an array of random numbers greater than or equal to 0.0 and less than 1.0. + /// + public static double[] Samples(int length, int seed) + { + if (seed == 0) + { + seed = 1; + } + uint xn = (uint)seed%Modx; + uint yn = 1; + uint zn = 1; + + var data = new double[length]; + for (int i = 0; i < data.Length; i++) + { + xn = (171*xn)%Modx; + yn = (172*yn)%Mody; + zn = (170*zn)%Modz; + + double w = xn*ModxRecip + yn*ModyRecip + zn*ModzRecip; + data[i] = w - (int)w; + } + return data; + } } } diff --git a/src/Numerics/Random/WH2006.cs b/src/Numerics/Random/WH2006.cs index e0bf71db..e1bfff60 100644 --- a/src/Numerics/Random/WH2006.cs +++ b/src/Numerics/Random/WH2006.cs @@ -116,5 +116,33 @@ namespace MathNet.Numerics.Random u -= (int)u; return u; } + + /// + /// Returns an array of random numbers greater than or equal to 0.0 and less than 1.0. + /// + public static double[] Samples(int length, int seed) + { + if (seed == 0) + { + seed = 1; + } + ulong wn = 1; + ulong xn = (uint)seed%Modx; + ulong yn = 1; + ulong zn = 1; + + var data = new double[length]; + for (int i = 0; i < data.Length; i++) + { + xn = 11600*xn%Modx; + yn = 47003*yn%Mody; + zn = 23000*zn%Modz; + wn = 33000*wn%Modw; + + double u = xn*ModxRecip + yn*ModyRecip + zn*ModzRecip + wn*ModwRecip; + data[i] = u - (int)u; + } + return data; + } } } diff --git a/src/Numerics/Random/Xorshift.cs b/src/Numerics/Random/Xorshift.cs index 65613703..f6df39b4 100644 --- a/src/Numerics/Random/Xorshift.cs +++ b/src/Numerics/Random/Xorshift.cs @@ -261,5 +261,34 @@ namespace MathNet.Numerics.Random _z = t & 0xffffffff; return _z*UlongToDoubleMultiplier; } + + /// + /// Returns an array of random numbers greater than or equal to 0.0 and less than 1.0. + /// + public static double[] Samples(int length, int seed, ulong a = ASeed, ulong c = CSeed, ulong x1 = YSeed, ulong x2 = ZSeed) + { + if (a <= c) + { + throw new ArgumentException(string.Format(Resources.ArgumentOutOfRangeGreater, "a", "c"), "a"); + } + + if (seed == 0) + { + seed = 1; + } + ulong x = (uint)seed; + + var data = new double[length]; + for (int i = 0; i < data.Length; i++) + { + var t = (a*x) + c; + x = x1; + x1 = x2; + c = t >> 32; + x2 = t & 0xffffffff; + data[i] = x2*UlongToDoubleMultiplier; + } + return data; + } } } diff --git a/src/UnitTests/Random/SystemCryptoTests.cs b/src/UnitTests/Random/CryptoRandomSourceTests.cs similarity index 91% rename from src/UnitTests/Random/SystemCryptoTests.cs rename to src/UnitTests/Random/CryptoRandomSourceTests.cs index c1bd2955..cd08ffee 100644 --- a/src/UnitTests/Random/SystemCryptoTests.cs +++ b/src/UnitTests/Random/CryptoRandomSourceTests.cs @@ -3,7 +3,9 @@ // http://numerics.mathdotnet.com // 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 // files (the "Software"), to deal in the Software without @@ -12,8 +14,10 @@ // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -25,11 +29,12 @@ // #if !PORTABLE + +using MathNet.Numerics.Random; +using NUnit.Framework; + namespace MathNet.Numerics.UnitTests.Random { - using Numerics.Random; - using NUnit.Framework; - /// /// Tests for a random number generator based on the class in the .NET library /// @@ -39,10 +44,10 @@ namespace MathNet.Numerics.UnitTests.Random /// /// Initializes a new instance of the SystemCryptoRandomNumberGeneratorTests class. /// - public CryptoRandomSourceTests() - : base(typeof(CryptoRandomSource)) + public CryptoRandomSourceTests() : base(typeof (CryptoRandomSource)) { } } } + #endif diff --git a/src/UnitTests/Random/Mcg31m1Tests.cs b/src/UnitTests/Random/Mcg31m1Tests.cs index a484e6ab..9302d041 100644 --- a/src/UnitTests/Random/Mcg31m1Tests.cs +++ b/src/UnitTests/Random/Mcg31m1Tests.cs @@ -3,7 +3,9 @@ // http://numerics.mathdotnet.com // 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 // files (the "Software"), to deal in the Software without @@ -12,8 +14,10 @@ // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -24,11 +28,11 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using MathNet.Numerics.Random; +using NUnit.Framework; + namespace MathNet.Numerics.UnitTests.Random { - using Numerics.Random; - using NUnit.Framework; - /// /// Tests for Multiplicative congruential generator using a modulus of 2^31-1 and a multiplier of 1132489760. /// @@ -38,8 +42,14 @@ namespace MathNet.Numerics.UnitTests.Random /// /// Initializes a new instance of the Mcg31M1Tests class. /// - public Mcg31M1Tests() : base(typeof(Mcg31m1)) + public Mcg31M1Tests() : base(typeof (Mcg31m1)) + { + } + + [Test] + public void StaticSamplesConsistent() { + Assert.That(Mcg31m1.Samples(1000, 1), Is.EqualTo(new Mcg31m1(1).NextDoubles(1000)).Within(1e-12).AsCollection); } } } diff --git a/src/UnitTests/Random/Mcg59Tests.cs b/src/UnitTests/Random/Mcg59Tests.cs index a9277b31..703958c4 100644 --- a/src/UnitTests/Random/Mcg59Tests.cs +++ b/src/UnitTests/Random/Mcg59Tests.cs @@ -3,7 +3,9 @@ // http://numerics.mathdotnet.com // 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 // files (the "Software"), to deal in the Software without @@ -12,8 +14,10 @@ // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -24,11 +28,11 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using MathNet.Numerics.Random; +using NUnit.Framework; + namespace MathNet.Numerics.UnitTests.Random { - using Numerics.Random; - using NUnit.Framework; - /// /// Tests for multiplicative congruential generator using a modulus of 2^59 and a multiplier of 13^13. /// @@ -38,8 +42,14 @@ namespace MathNet.Numerics.UnitTests.Random /// /// Initializes a new instance of the Mcg59Tests class. /// - public Mcg59Tests() : base(typeof(Mcg59)) + public Mcg59Tests() : base(typeof (Mcg59)) + { + } + + [Test] + public void StaticSamplesConsistent() { + Assert.That(Mcg59.Samples(1000, 1), Is.EqualTo(new Mcg59(1).NextDoubles(1000)).Within(1e-12).AsCollection); } } } diff --git a/src/UnitTests/Random/MersenneTwisterTests.cs b/src/UnitTests/Random/MersenneTwisterTests.cs index bbb6ed4a..4847df84 100644 --- a/src/UnitTests/Random/MersenneTwisterTests.cs +++ b/src/UnitTests/Random/MersenneTwisterTests.cs @@ -3,7 +3,9 @@ // http://numerics.mathdotnet.com // 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 // files (the "Software"), to deal in the Software without @@ -12,8 +14,10 @@ // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -24,11 +28,11 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using MathNet.Numerics.Random; +using NUnit.Framework; + namespace MathNet.Numerics.UnitTests.Random { - using Numerics.Random; - using NUnit.Framework; - /// /// Tests for random number generator using Mersenne Twister 19937 algorithm. /// @@ -38,7 +42,7 @@ namespace MathNet.Numerics.UnitTests.Random /// /// Initializes a new instance of the MersenneTwisterTests class. /// - public MersenneTwisterTests() : base(typeof(MersenneTwister)) + public MersenneTwisterTests() : base(typeof (MersenneTwister)) { } @@ -54,5 +58,11 @@ namespace MathNet.Numerics.UnitTests.Random Assert.AreEqual(mt.NextDouble(), 0.7151893649715930); Assert.AreEqual(mt.NextDouble(), 0.8442657440900803); } + + [Test] + public void StaticSamplesConsistent() + { + Assert.That(MersenneTwister.Samples(1000, 1), Is.EqualTo(new MersenneTwister(1).NextDoubles(1000)).Within(1e-12).AsCollection); + } } } diff --git a/src/UnitTests/Random/Mrg32k3aTests.cs b/src/UnitTests/Random/Mrg32k3aTests.cs index bf05bffb..0ec26f19 100644 --- a/src/UnitTests/Random/Mrg32k3aTests.cs +++ b/src/UnitTests/Random/Mrg32k3aTests.cs @@ -3,7 +3,9 @@ // http://numerics.mathdotnet.com // 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 // files (the "Software"), to deal in the Software without @@ -12,8 +14,10 @@ // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -24,11 +28,11 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using MathNet.Numerics.Random; +using NUnit.Framework; + namespace MathNet.Numerics.UnitTests.Random { - using Numerics.Random; - using NUnit.Framework; - /// /// Tests for a 32-bit combined multiple recursive generator with 2 components of order 3. /// @@ -38,9 +42,14 @@ namespace MathNet.Numerics.UnitTests.Random /// /// Initializes a new instance of the Mrg32K3ATests class. /// - public Mrg32K3ATests() - : base(typeof(Mrg32k3a)) + public Mrg32K3ATests() : base(typeof (Mrg32k3a)) + { + } + + [Test] + public void StaticSamplesConsistent() { + Assert.That(Mrg32k3a.Samples(1000, 1), Is.EqualTo(new Mrg32k3a(1).NextDoubles(1000)).Within(1e-12).AsCollection); } } } diff --git a/src/UnitTests/Random/PalfTests.cs b/src/UnitTests/Random/PalfTests.cs index 6eff47f4..2f8b9b0b 100644 --- a/src/UnitTests/Random/PalfTests.cs +++ b/src/UnitTests/Random/PalfTests.cs @@ -3,7 +3,9 @@ // http://numerics.mathdotnet.com // 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 // files (the "Software"), to deal in the Software without @@ -12,8 +14,10 @@ // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -24,12 +28,12 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using System; +using MathNet.Numerics.Random; +using NUnit.Framework; + namespace MathNet.Numerics.UnitTests.Random { - using System; - using Numerics.Random; - using NUnit.Framework; - /// /// Tests for a Parallel Additive Lagged Fibonacci pseudo-random number generator. /// @@ -39,8 +43,7 @@ namespace MathNet.Numerics.UnitTests.Random /// /// Initializes a new instance of the PalfTests class. /// - public PalfTests() - : base(typeof(Palf)) + public PalfTests() : base(typeof (Palf)) { } @@ -61,5 +64,11 @@ namespace MathNet.Numerics.UnitTests.Random { Assert.Throws(() => new Palf(1, true, 10, 10)); } + + [Test] + public void StaticSamplesConsistent() + { + Assert.That(Palf.Samples(1000, 1), Is.EqualTo(new Palf(1).NextDoubles(1000)).Within(1e-12).AsCollection); + } } } diff --git a/src/UnitTests/Random/SystemRandomExtensionTests.cs b/src/UnitTests/Random/RandomExtensionTests.cs similarity index 87% rename from src/UnitTests/Random/SystemRandomExtensionTests.cs rename to src/UnitTests/Random/RandomExtensionTests.cs index 7b321a58..ea00f1c9 100644 --- a/src/UnitTests/Random/SystemRandomExtensionTests.cs +++ b/src/UnitTests/Random/RandomExtensionTests.cs @@ -3,7 +3,9 @@ // http://numerics.mathdotnet.com // 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 // files (the "Software"), to deal in the Software without @@ -12,8 +14,10 @@ // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -24,17 +28,16 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using MathNet.Numerics.Random; +using NUnit.Framework; + namespace MathNet.Numerics.UnitTests.Random { - using System; - using Numerics.Random; - using NUnit.Framework; - /// /// Tests for extension methods of the System.Random. /// [TestFixture, Category("Random")] - public class SystemRandomExtensionTests + public class RandomExtensionTests { /// /// Can sample int64. @@ -42,7 +45,7 @@ namespace MathNet.Numerics.UnitTests.Random [Test] public void CanSampleInt64() { - var rnd = new Random(0); + var rnd = new System.Random(0); rnd.NextInt64(); } @@ -52,7 +55,7 @@ namespace MathNet.Numerics.UnitTests.Random [Test] public void CanSampleFullRangeInt32() { - var rnd = new Random(0); + var rnd = new System.Random(0); rnd.NextFullRangeInt32(); } @@ -62,7 +65,7 @@ namespace MathNet.Numerics.UnitTests.Random [Test] public void CanSampleFullRangeInt64() { - var rnd = new Random(0); + var rnd = new System.Random(0); rnd.NextFullRangeInt64(); } @@ -72,7 +75,7 @@ namespace MathNet.Numerics.UnitTests.Random [Test] public void CanSampleDecimal() { - var rnd = new Random(0); + var rnd = new System.Random(0); rnd.NextDecimal(); } } diff --git a/src/UnitTests/Random/RandomTests.cs b/src/UnitTests/Random/RandomTests.cs index 5740bfc7..4eeb98b5 100644 --- a/src/UnitTests/Random/RandomTests.cs +++ b/src/UnitTests/Random/RandomTests.cs @@ -3,7 +3,9 @@ // http://numerics.mathdotnet.com // 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 // files (the "Software"), to deal in the Software without @@ -12,8 +14,10 @@ // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -24,12 +28,13 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using System; +using System.Threading; +using MathNet.Numerics.Random; +using NUnit.Framework; + namespace MathNet.Numerics.UnitTests.Random { - using System; - using System.Threading; - using NUnit.Framework; - /// /// Abstract class fro RNG tests. /// @@ -38,12 +43,12 @@ namespace MathNet.Numerics.UnitTests.Random /// /// Number of samples. /// - private const int N = 10000; + const int N = 10000; /// /// Random generator type. /// - private readonly Type _randomType; + readonly Type _randomType; /// /// Initializes a new instance of the RandomTests class. @@ -60,7 +65,7 @@ namespace MathNet.Numerics.UnitTests.Random [Test] public void Sample() { - var random = (Random)Activator.CreateInstance(_randomType, new object[] { false }); + var random = (System.Random)Activator.CreateInstance(_randomType, new object[] { false }); double sum = 0; for (var i = 0; i < N; i++) { @@ -71,21 +76,34 @@ namespace MathNet.Numerics.UnitTests.Random } // make sure are within 10% of the expected sum. - Assert.IsTrue(sum >= (N / 2.0) - (.05 * N)); - Assert.IsTrue(sum <= (N / 2.0) + (.05 * N)); + Assert.IsTrue(sum >= (N/2.0) - (.05*N)); + Assert.IsTrue(sum <= (N/2.0) + (.05*N)); if (random is IDisposable) { ((IDisposable)random).Dispose(); } } + [Test] + public void Reproducible() + { + if (_randomType == typeof (CryptoRandomSource)) + { + Assert.Ignore("CryptoRandomSource does not support seeds and is not reproducible by design."); + } + + Assert.That( + ((RandomSource)Activator.CreateInstance(_randomType, new object[] { 5, false })).NextDoubles(1000), + Is.EqualTo(((RandomSource)Activator.CreateInstance(_randomType, new object[] { 5, false })).NextDoubles(1000)).Within(1e-12).AsCollection); + } + /// /// Can thread-safe sample /// [Test] public void ThreadSafeSample() { - var random = (Random)Activator.CreateInstance(_randomType, new object[] { true }); + var random = (System.Random)Activator.CreateInstance(_randomType, new object[] { true }); var t1 = new Thread(RunTest); var t2 = new Thread(RunTest); @@ -101,7 +119,7 @@ namespace MathNet.Numerics.UnitTests.Random /// RNG object. public void RunTest(object random) { - var rng = (Random)random; + var rng = (System.Random)random; for (var i = 0; i < N; i++) { var next = rng.NextDouble(); diff --git a/src/UnitTests/Random/WH1982Tests.cs b/src/UnitTests/Random/WH1982Tests.cs index eac492f3..d65537e1 100644 --- a/src/UnitTests/Random/WH1982Tests.cs +++ b/src/UnitTests/Random/WH1982Tests.cs @@ -3,7 +3,9 @@ // http://numerics.mathdotnet.com // 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 // files (the "Software"), to deal in the Software without @@ -12,8 +14,10 @@ // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -24,13 +28,13 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using MathNet.Numerics.Random; +using NUnit.Framework; + namespace MathNet.Numerics.UnitTests.Random { - using Numerics.Random; - using NUnit.Framework; - /// - /// Tests for a Wichmann-Hill’s 1982 combined multiplicative congruential generator. + /// Tests for a Wichmann-Hill’s 1982 combined multiplicative congruential generator. /// [TestFixture, Category("Random")] public class Wh1982Tests : RandomTests @@ -38,9 +42,14 @@ namespace MathNet.Numerics.UnitTests.Random /// /// Initializes a new instance of the Wh1982Tests class. /// - public Wh1982Tests() - : base(typeof(WH1982)) + public Wh1982Tests() : base(typeof (WH1982)) + { + } + + [Test] + public void StaticSamplesConsistent() { + Assert.That(WH1982.Samples(1000, 1), Is.EqualTo(new WH1982(1).NextDoubles(1000)).Within(1e-12).AsCollection); } } } diff --git a/src/UnitTests/Random/WH2006Tests.cs b/src/UnitTests/Random/WH2006Tests.cs index 58a34447..6c91d20a 100644 --- a/src/UnitTests/Random/WH2006Tests.cs +++ b/src/UnitTests/Random/WH2006Tests.cs @@ -3,7 +3,9 @@ // http://numerics.mathdotnet.com // 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 // files (the "Software"), to deal in the Software without @@ -12,8 +14,10 @@ // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -24,13 +28,13 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using MathNet.Numerics.Random; +using NUnit.Framework; + namespace MathNet.Numerics.UnitTests.Random { - using Numerics.Random; - using NUnit.Framework; - /// - /// Test for a Wichmann-Hill’s 2006 combined multiplicative congruential generator. + /// Test for a Wichmann-Hill’s 2006 combined multiplicative congruential generator. /// [TestFixture, Category("Random")] public class Wh2006Tests : RandomTests @@ -38,9 +42,14 @@ namespace MathNet.Numerics.UnitTests.Random /// /// Initializes a new instance of the Wh2006Tests class. /// - public Wh2006Tests() - : base(typeof(WH2006)) + public Wh2006Tests() : base(typeof (WH2006)) + { + } + + [Test] + public void StaticSamplesConsistent() { + Assert.That(WH2006.Samples(1000, 1), Is.EqualTo(new WH2006(1).NextDoubles(1000)).Within(1e-12).AsCollection); } } } diff --git a/src/UnitTests/Random/XorshiftTests.cs b/src/UnitTests/Random/XorshiftTests.cs index 09a48cc9..ed220177 100644 --- a/src/UnitTests/Random/XorshiftTests.cs +++ b/src/UnitTests/Random/XorshiftTests.cs @@ -3,7 +3,9 @@ // http://numerics.mathdotnet.com // 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 // files (the "Software"), to deal in the Software without @@ -12,8 +14,10 @@ // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -24,11 +28,11 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using MathNet.Numerics.Random; +using NUnit.Framework; + namespace MathNet.Numerics.UnitTests.Random { - using Numerics.Random; - using NUnit.Framework; - /// /// Tests for a multiply-with-carry Xorshift pseudo random number generator (RNG) specified in Marsaglia, George. (2003). Xorshift RNGs. /// @@ -38,9 +42,14 @@ namespace MathNet.Numerics.UnitTests.Random /// /// Initializes a new instance of the XorshiftTests class. /// - public XorshiftTests() - : base(typeof(Xorshift)) + public XorshiftTests() : base(typeof (Xorshift)) + { + } + + [Test] + public void StaticSamplesConsistent() { + Assert.That(Xorshift.Samples(1000, 1), Is.EqualTo(new Xorshift(1).NextDoubles(1000)).Within(1e-12).AsCollection); } } } diff --git a/src/UnitTests/UnitTests.csproj b/src/UnitTests/UnitTests.csproj index 52071b22..3e0859fe 100644 --- a/src/UnitTests/UnitTests.csproj +++ b/src/UnitTests/UnitTests.csproj @@ -368,8 +368,8 @@ - - + +