diff --git a/src/FSharp/Random.fs b/src/FSharp/Random.fs index 3a05bad4..6b802b4c 100644 --- a/src/FSharp/Random.fs +++ b/src/FSharp/Random.fs @@ -37,8 +37,8 @@ module Random = let shared = MersenneTwister.Default :> System.Random /// Creates a default .Net system pRNG with a custom seed based on uinque GUIDs - let system () = new System.Random(RandomSeed.Guid()) - let systemSeed seed = new System.Random(seed) + let system () = new SystemRandomSource() :> System.Random + let systemSeed (seed:int) = new SystemRandomSource(seed) :> System.Random #if PORTABLE #else diff --git a/src/Numerics/Numerics.csproj b/src/Numerics/Numerics.csproj index c77fb776..b338bde0 100644 --- a/src/Numerics/Numerics.csproj +++ b/src/Numerics/Numerics.csproj @@ -182,6 +182,7 @@ + diff --git a/src/Numerics/Random/RandomSource.cs b/src/Numerics/Random/RandomSource.cs index 569fc310..cf9998e8 100644 --- a/src/Numerics/Random/RandomSource.cs +++ b/src/Numerics/Random/RandomSource.cs @@ -29,7 +29,6 @@ // using System; -using System.Collections.Generic; using MathNet.Numerics.Properties; namespace MathNet.Numerics.Random @@ -39,7 +38,7 @@ namespace MathNet.Numerics.Random /// and the Math.Net Numerics random number generators to provide thread safety. /// When used directly it use the System.Random as random number source. /// - public class RandomSource : System.Random + public abstract class RandomSource : System.Random { readonly bool _threadSafe; readonly object _lock = new object(); @@ -49,7 +48,7 @@ namespace MathNet.Numerics.Random /// the value of to set whether /// the instance is thread safe or not. /// - public RandomSource() : base(RandomSeed.Guid()) + protected RandomSource() : base(RandomSeed.Guid()) { _threadSafe = Control.ThreadSafeRandomNumberGenerators; } @@ -60,30 +59,7 @@ namespace MathNet.Numerics.Random /// if set to true , the class is thread safe. /// Thread safe instances are two and half times slower than non-thread /// safe classes. - public RandomSource(bool threadSafe) : base(RandomSeed.Guid()) - { - _threadSafe = threadSafe; - } - - /// - /// Initializes a new instance of the class using - /// the value of to set whether - /// the instance is thread safe or not. - /// - /// The seed value. - public RandomSource(int systemRandomSeed) : base(systemRandomSeed) - { - _threadSafe = Control.ThreadSafeRandomNumberGenerators; - } - - /// - /// Initializes a new instance of the class. - /// - /// The seed value. - /// if set to true , the class is thread safe. - /// Thread safe instances are two and half times slower than non-thread - /// safe classes. - public RandomSource(int systemRandomSeed, bool threadSafe) : base(systemRandomSeed) + protected RandomSource(bool threadSafe) : base(RandomSeed.Guid()) { _threadSafe = threadSafe; } @@ -241,55 +217,12 @@ namespace MathNet.Numerics.Random return DoSample(); } - /// - /// Thread safe version of which returns a random number between 0.0 and 1.0. - /// - /// A double-precision floating point number greater than or equal to 0.0, and less than 1.0 - double ThreadSafeSample() - { - lock (_lock) - { - return DoSample(); - } - } - /// /// Returns a random number between 0.0 and 1.0. /// /// /// A double-precision floating point number greater than or equal to 0.0, and less than 1.0. /// - protected virtual double DoSample() - { - return base.Sample(); - } - - /// - /// 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 systemRandomSeed) - { - var rnd = new System.Random(systemRandomSeed); - - var data = new double[length]; - for (int i = 0; i < data.Length; i++) - { - data[i] = rnd.NextDouble(); - } - return data; - } - - /// - /// Returns an infinite sequence of random numbers greater than or equal to 0.0 and less than 1.0. - /// - public static IEnumerable SampleSequence(int systemRandomSeed) - { - var rnd = new System.Random(systemRandomSeed); - - while (true) - { - yield return rnd.NextDouble(); - } - } + protected abstract double DoSample(); } } diff --git a/src/Numerics/Random/SystemRandomSource.cs b/src/Numerics/Random/SystemRandomSource.cs new file mode 100644 index 00000000..8dae51dd --- /dev/null +++ b/src/Numerics/Random/SystemRandomSource.cs @@ -0,0 +1,115 @@ +// +// Math.NET Numerics, part of the Math.NET Project +// http://numerics.mathdotnet.com +// http://github.com/mathnet/mathnet-numerics +// http://mathnetnumerics.codeplex.com +// +// 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 +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// 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 +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +using System.Collections.Generic; + +namespace MathNet.Numerics.Random +{ + /// + /// A random number generator based on the class in the .NET library. + /// + public class SystemRandomSource : RandomSource + { + readonly System.Random _random; + + /// + /// Construct a new random number generator with a random seed. + /// + public SystemRandomSource() : this(RandomSeed.Guid()) + { + } + + /// + /// Construct a new random number generator with random seed. + /// + /// if set to true , the class is thread safe. + public SystemRandomSource(bool threadSafe) : this(RandomSeed.Guid(), threadSafe) + { + } + + /// + /// Construct a new random number generator with random seed. + /// + /// The seed value. + public SystemRandomSource(int seed) + { + _random = new System.Random(seed); + } + + /// + /// Construct a new random number generator with random seed. + /// + /// The seed value. + /// if set to true , the class is thread safe. + public SystemRandomSource(int seed, bool threadSafe) : base(threadSafe) + { + _random = new System.Random(seed); + } + + /// + /// Returns a random number between 0.0 and 1.0. + /// + /// + /// A double-precision floating point number greater than or equal to 0.0, and less than 1.0. + /// + protected override double DoSample() + { + return _random.NextDouble(); + } + + /// + /// 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) + { + var rnd = new System.Random(seed); + + var data = new double[length]; + for (int i = 0; i < data.Length; i++) + { + data[i] = rnd.NextDouble(); + } + return data; + } + + /// + /// Returns an infinite sequence of random numbers greater than or equal to 0.0 and less than 1.0. + /// + public static IEnumerable SampleSequence(int seed) + { + var rnd = new System.Random(seed); + + while (true) + { + yield return rnd.NextDouble(); + } + } + } +} diff --git a/src/UnitTests/Random/RandomTests.cs b/src/UnitTests/Random/RandomTests.cs index 7030cd56..51ccd7a7 100644 --- a/src/UnitTests/Random/RandomTests.cs +++ b/src/UnitTests/Random/RandomTests.cs @@ -89,10 +89,12 @@ namespace MathNet.Numerics.UnitTests.Random [Test] public void Reproducible() { +#if !PORTABLE if (_randomType == typeof (CryptoRandomSource)) { Assert.Ignore("CryptoRandomSource does not support seeds and is not reproducible by design."); } +#endif Assert.That( ((RandomSource)Activator.CreateInstance(_randomType, new object[] { 5, false })).NextDoubles(1000), diff --git a/src/UnitTests/Random/SystemRandomSourceTests.cs b/src/UnitTests/Random/SystemRandomSourceTests.cs new file mode 100644 index 00000000..f0ca3ee5 --- /dev/null +++ b/src/UnitTests/Random/SystemRandomSourceTests.cs @@ -0,0 +1,52 @@ +// +// Math.NET Numerics, part of the Math.NET Project +// http://numerics.mathdotnet.com +// http://github.com/mathnet/mathnet-numerics +// http://mathnetnumerics.codeplex.com +// +// 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 +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// 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 +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +using MathNet.Numerics.Random; +using NUnit.Framework; + +namespace MathNet.Numerics.UnitTests.Random +{ + /// + /// Tests for System.Random. + /// + [TestFixture, Category("Random")] + public class SystemRandomSourceTests : RandomTests + { + public SystemRandomSourceTests() : base(typeof(SystemRandomSource)) + { + } + + [Test] + public void StaticSamplesConsistent() + { + Assert.That(SystemRandomSource.Samples(1000, 1), Is.EqualTo(new SystemRandomSource(1).NextDoubles(1000)).Within(1e-12).AsCollection); + } + } +} diff --git a/src/UnitTests/UnitTests.csproj b/src/UnitTests/UnitTests.csproj index 3e0859fe..73a8e7d8 100644 --- a/src/UnitTests/UnitTests.csproj +++ b/src/UnitTests/UnitTests.csproj @@ -358,6 +358,7 @@ +