Browse Source

Random: ephemeral serialization support for random sources #462

v3
Christoph Ruegg 10 years ago
parent
commit
d9f8929067
  1. 6
      src/Numerics/Random/Mcg31m1.cs
  2. 6
      src/Numerics/Random/Mcg59.cs
  3. 6
      src/Numerics/Random/MersenneTwister.cs
  4. 12
      src/Numerics/Random/Mrg32k3a.cs
  5. 8
      src/Numerics/Random/Palf.cs
  6. 3
      src/Numerics/Random/RandomSource.cs
  7. 5
      src/Numerics/Random/SystemRandomSource.cs
  8. 8
      src/Numerics/Random/WH1982.cs
  9. 9
      src/Numerics/Random/WH2006.cs
  10. 8
      src/Numerics/Random/Xorshift.cs
  11. 97
      src/UnitTests/Random/RandomSerializationTests.cs
  12. 1
      src/UnitTests/UnitTests.csproj

6
src/Numerics/Random/Mcg31m1.cs

@ -27,7 +27,9 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
#if !PORTABLE
using System.Runtime;
@ -38,11 +40,15 @@ namespace MathNet.Numerics.Random
/// <summary>
/// Multiplicative congruential generator using a modulus of 2^31-1 and a multiplier of 1132489760.
/// </summary>
[Serializable]
[DataContract(Namespace = "urn:MathNet/Numerics/Random")]
public class Mcg31m1 : RandomSource
{
const ulong Modulus = 2147483647;
const ulong Multiplier = 1132489760;
const double Reciprocal = 1.0/Modulus;
[DataMember(Order = 1)]
ulong _xn;
/// <summary>

6
src/Numerics/Random/Mcg59.cs

@ -27,7 +27,9 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
#if !PORTABLE
using System.Runtime;
@ -38,11 +40,15 @@ namespace MathNet.Numerics.Random
/// <summary>
/// Multiplicative congruential generator using a modulus of 2^59 and a multiplier of 13^13.
/// </summary>
[Serializable]
[DataContract(Namespace = "urn:MathNet/Numerics/Random")]
public class Mcg59 : RandomSource
{
const ulong Modulus = 576460752303423488;
const ulong Multiplier = 302875106592253;
const double Reciprocal = 1.0/Modulus;
[DataMember(Order = 1)]
ulong _xn;
/// <summary>

6
src/Numerics/Random/MersenneTwister.cs

@ -65,7 +65,9 @@
email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
*/
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
#if PORTABLE
using System;
@ -79,6 +81,8 @@ namespace MathNet.Numerics.Random
/// <summary>
/// Random number generator using Mersenne Twister 19937 algorithm.
/// </summary>
[Serializable]
[DataContract(Namespace = "urn:MathNet/Numerics/Random")]
public class MersenneTwister : RandomSource
{
/// <summary>
@ -119,11 +123,13 @@ namespace MathNet.Numerics.Random
/// <summary>
/// Mersenne twister constant.
/// </summary>
[DataMember(Order = 1)]
readonly uint[] _mt = new uint[N];
/// <summary>
/// Mersenne twister constant.
/// </summary>
[DataMember(Order = 2)]
int _mti = N + 1;
/// <summary>

12
src/Numerics/Random/Mrg32k3a.cs

@ -27,7 +27,9 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
#if !PORTABLE
using System.Runtime;
@ -39,6 +41,9 @@ namespace MathNet.Numerics.Random
/// A 32-bit combined multiple recursive generator with 2 components of order 3.
/// </summary>
/// <remarks>Based off of P. L'Ecuyer, "Combined Multiple Recursive Random Number Generators," Operations Research, 44, 5 (1996), 816--822. </remarks>
///
[Serializable]
[DataContract(Namespace = "urn:MathNet/Numerics/Random")]
public class Mrg32k3a : RandomSource
{
const double A12 = 1403580;
@ -49,11 +54,18 @@ namespace MathNet.Numerics.Random
const double Modulus2 = 4294944443;
const double Reciprocal = 1.0/Modulus1;
[DataMember(Order = 1)]
double _xn1 = 1;
[DataMember(Order = 2)]
double _xn2 = 1;
[DataMember(Order = 3)]
double _xn3;
[DataMember(Order = 4)]
double _yn1 = 1;
[DataMember(Order = 5)]
double _yn2 = 1;
[DataMember(Order = 6)]
double _yn3 = 1;
/// <summary>

8
src/Numerics/Random/Palf.cs

@ -29,6 +29,7 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using MathNet.Numerics.Properties;
#if !PORTABLE
@ -46,6 +47,8 @@ namespace MathNet.Numerics.Random
/// It uses the modulus 2<sup>32</sup> and by default the "lags" 418 and 1279. Some popular pairs are presented on
/// <a href="http://en.wikipedia.org/wiki/Lagged_Fibonacci_generator">Wikipedia - Lagged Fibonacci generator</a>.
/// </remarks>
[Serializable]
[DataContract(Namespace = "urn:MathNet/Numerics/Random")]
public class Palf : RandomSource
{
/// <summary>
@ -147,23 +150,28 @@ namespace MathNet.Numerics.Random
/// <summary>
/// Gets the short lag of the Lagged Fibonacci pseudo-random number generator.
/// </summary>
[DataMember(Order = 1)]
public int ShortLag { get; private set; }
/// <summary>
/// Gets the long lag of the Lagged Fibonacci pseudo-random number generator.
/// </summary>
[DataMember(Order = 2)]
public int LongLag { get; private set; }
/// <summary>
/// Stores an array of <see cref="LongLag"/> random numbers
/// </summary>
[DataMember(Order = 3)]
readonly uint[] _x;
[DataMember(Order = 4)]
readonly int _threads;
/// <summary>
/// Stores an index for the random number array element that will be accessed next.
/// </summary>
[DataMember(Order = 5)]
int _k;
/// <summary>

3
src/Numerics/Random/RandomSource.cs

@ -29,6 +29,7 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.Random
@ -38,6 +39,8 @@ 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.
/// </summary>
[Serializable]
[DataContract(Namespace = "urn:MathNet/Numerics/Random")]
public abstract class RandomSource : System.Random
{
readonly bool _threadSafe;

5
src/Numerics/Random/SystemRandomSource.cs

@ -27,7 +27,9 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using MathNet.Numerics.Threading;
#if PORTABLE
@ -42,8 +44,11 @@ namespace MathNet.Numerics.Random
/// <summary>
/// A random number generator based on the <see cref="System.Random"/> class in the .NET library.
/// </summary>
[Serializable]
[DataContract(Namespace = "urn:MathNet/Numerics/Random")]
public class SystemRandomSource : RandomSource
{
[DataMember(Order = 1)]
readonly System.Random _random;
/// <summary>

8
src/Numerics/Random/WH1982.cs

@ -27,7 +27,9 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
#if !PORTABLE
using System.Runtime;
@ -41,6 +43,8 @@ namespace MathNet.Numerics.Random
/// <remarks>See: Wichmann, B. A. &amp; Hill, I. D. (1982), "Algorithm AS 183:
/// An efficient and portable pseudo-random number generator". Applied Statistics 31 (1982) 188-190
/// </remarks>
[Serializable]
[DataContract(Namespace = "urn:MathNet/Numerics/Random")]
public class WH1982 : RandomSource
{
const uint Modx = 30269;
@ -49,8 +53,12 @@ namespace MathNet.Numerics.Random
const double ModyRecip = 1.0/Mody;
const uint Modz = 30323;
const double ModzRecip = 1.0/Modz;
[DataMember(Order = 1)]
uint _xn;
[DataMember(Order = 2)]
uint _yn = 1;
[DataMember(Order = 3)]
uint _zn = 1;
/// <summary>

9
src/Numerics/Random/WH2006.cs

@ -27,7 +27,9 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
#if !PORTABLE
using System.Runtime;
@ -41,6 +43,8 @@ namespace MathNet.Numerics.Random
/// <remarks>See: Wichmann, B. A. &amp; Hill, I. D. (2006), "Generating good pseudo-random numbers".
/// Computational Statistics &amp; Data Analysis 51:3 (2006) 1614-1622
/// </remarks>
[Serializable]
[DataContract(Namespace = "urn:MathNet/Numerics/Random")]
public class WH2006 : RandomSource
{
const uint Modw = 2147483123;
@ -51,9 +55,14 @@ namespace MathNet.Numerics.Random
const double ModyRecip = 1.0/Mody;
const uint Modz = 2147483423;
const double ModzRecip = 1.0/Modz;
[DataMember(Order = 1)]
ulong _wn = 1;
[DataMember(Order = 2)]
ulong _xn;
[DataMember(Order = 3)]
ulong _yn = 1;
[DataMember(Order = 4)]
ulong _zn = 1;
/// <summary>

8
src/Numerics/Random/Xorshift.cs

@ -29,6 +29,7 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using MathNet.Numerics.Properties;
#if !PORTABLE
@ -42,6 +43,8 @@ namespace MathNet.Numerics.Random
/// <code>Xn = a * Xn−3 + c mod 2^32</code>
/// http://www.jstatsoft.org/v08/i14/paper
/// </summary>
[Serializable]
[DataContract(Namespace = "urn:MathNet/Numerics/Random")]
public class Xorshift : RandomSource
{
/// <summary>
@ -72,26 +75,31 @@ namespace MathNet.Numerics.Random
/// <summary>
/// Seed or last but three unsigned random number.
/// </summary>
[DataMember(Order = 1)]
ulong _x;
/// <summary>
/// Last but two unsigned random number.
/// </summary>
[DataMember(Order = 2)]
ulong _y;
/// <summary>
/// Last but one unsigned random number.
/// </summary>
[DataMember(Order = 3)]
ulong _z;
/// <summary>
/// The value of the carry over.
/// </summary>
[DataMember(Order = 4)]
ulong _c;
/// <summary>
/// The multiplier.
/// </summary>
[DataMember(Order = 5)]
readonly ulong _a;
/// <summary>

97
src/UnitTests/Random/RandomSerializationTests.cs

@ -0,0 +1,97 @@
// <copyright file="RandomSerializationTests.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
//
// Copyright (c) 2009-2017 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.
// </copyright>
using System;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using MathNet.Numerics.Random;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.Random
{
[TestFixture]
public class RandomSerializationTests
{
[Test]
[TestCase(typeof(MersenneTwister))]
[TestCase(typeof(Mcg59))]
[TestCase(typeof(Mcg31m1))]
[TestCase(typeof(Mrg32k3a))]
[TestCase(typeof(Palf))]
[TestCase(typeof(WH1982))]
[TestCase(typeof(WH2006))]
[TestCase(typeof(Xorshift))]
[TestCase(typeof(SystemRandomSource))]
public void DataContractSerializationTest(Type randomType)
{
var expected = (RandomSource)Activator.CreateInstance(randomType);
expected.NextDouble();
expected.NextBoolean();
var serializer = new DataContractSerializer(randomType);
var stream = new MemoryStream();
serializer.WriteObject(stream, expected);
stream.Position = 0;
var actual = (RandomSource)serializer.ReadObject(stream);
Assert.That(actual.GetType(), Is.EqualTo(randomType));
Assert.That(actual.NextDoubleSequence().Take(10).ToArray(), Is.EqualTo(expected.NextDoubleSequence().Take(10).ToArray()).AsCollection);
}
[Test]
[TestCase(typeof(MersenneTwister))]
[TestCase(typeof(Mcg59))]
[TestCase(typeof(Mcg31m1))]
[TestCase(typeof(Mrg32k3a))]
[TestCase(typeof(Palf))]
[TestCase(typeof(WH1982))]
[TestCase(typeof(WH2006))]
[TestCase(typeof(Xorshift))]
[TestCase(typeof(SystemRandomSource))]
public void BinaryFormatterSerializationTest(Type randomType)
{
var expected = (RandomSource)Activator.CreateInstance(randomType);
expected.NextDouble();
expected.NextBoolean();
var serializer = new BinaryFormatter();
var stream = new MemoryStream();
serializer.Serialize(stream, expected);
stream.Position = 0;
var actual = (RandomSource)serializer.Deserialize(stream);
Assert.That(actual.GetType(), Is.EqualTo(randomType));
Assert.That(actual.NextDoubleSequence().Take(10).ToArray(), Is.EqualTo(expected.NextDoubleSequence().Take(10).ToArray()).AsCollection);
}
}
}

1
src/UnitTests/UnitTests.csproj

@ -365,6 +365,7 @@
<Compile Include="LinearAlgebraTests\VectorStorageCombinatorsTests.cs" />
<Compile Include="LinearAlgebraTests\VectorToStringTests.cs" />
<Compile Include="OdeSolvers\OdeSolverTest.cs" />
<Compile Include="Random\RandomSerializationTests.cs" />
<Compile Include="Random\SystemRandomSourceTests.cs" />
<Compile Include="RootFindingTests\BisectionTest.cs" />
<Compile Include="PermutationTest.cs" />

Loading…
Cancel
Save