diff --git a/src/Numerics/Random/Mcg31m1.cs b/src/Numerics/Random/Mcg31m1.cs
index 2daffa3e..6e8de9e8 100644
--- a/src/Numerics/Random/Mcg31m1.cs
+++ b/src/Numerics/Random/Mcg31m1.cs
@@ -27,7 +27,9 @@
// OTHER DEALINGS IN THE SOFTWARE.
//
+using System;
using System.Collections.Generic;
+using System.Runtime.Serialization;
#if !PORTABLE
using System.Runtime;
@@ -38,11 +40,15 @@ namespace MathNet.Numerics.Random
///
/// Multiplicative congruential generator using a modulus of 2^31-1 and a multiplier of 1132489760.
///
+ [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;
///
diff --git a/src/Numerics/Random/Mcg59.cs b/src/Numerics/Random/Mcg59.cs
index 87611790..9968c8bc 100644
--- a/src/Numerics/Random/Mcg59.cs
+++ b/src/Numerics/Random/Mcg59.cs
@@ -27,7 +27,9 @@
// OTHER DEALINGS IN THE SOFTWARE.
//
+using System;
using System.Collections.Generic;
+using System.Runtime.Serialization;
#if !PORTABLE
using System.Runtime;
@@ -38,11 +40,15 @@ namespace MathNet.Numerics.Random
///
/// Multiplicative congruential generator using a modulus of 2^59 and a multiplier of 13^13.
///
+ [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;
///
diff --git a/src/Numerics/Random/MersenneTwister.cs b/src/Numerics/Random/MersenneTwister.cs
index 6cce7d08..345ea3ec 100644
--- a/src/Numerics/Random/MersenneTwister.cs
+++ b/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
///
/// Random number generator using Mersenne Twister 19937 algorithm.
///
+ [Serializable]
+ [DataContract(Namespace = "urn:MathNet/Numerics/Random")]
public class MersenneTwister : RandomSource
{
///
@@ -119,11 +123,13 @@ namespace MathNet.Numerics.Random
///
/// Mersenne twister constant.
///
+ [DataMember(Order = 1)]
readonly uint[] _mt = new uint[N];
///
/// Mersenne twister constant.
///
+ [DataMember(Order = 2)]
int _mti = N + 1;
///
diff --git a/src/Numerics/Random/Mrg32k3a.cs b/src/Numerics/Random/Mrg32k3a.cs
index d00618e0..5c27c8d8 100644
--- a/src/Numerics/Random/Mrg32k3a.cs
+++ b/src/Numerics/Random/Mrg32k3a.cs
@@ -27,7 +27,9 @@
// OTHER DEALINGS IN THE SOFTWARE.
//
+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.
///
/// Based off of P. L'Ecuyer, "Combined Multiple Recursive Random Number Generators," Operations Research, 44, 5 (1996), 816--822.
+ ///
+ [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;
///
diff --git a/src/Numerics/Random/Palf.cs b/src/Numerics/Random/Palf.cs
index e899d8a2..d10e2481 100644
--- a/src/Numerics/Random/Palf.cs
+++ b/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 232 and by default the "lags" 418 and 1279. Some popular pairs are presented on
/// Wikipedia - Lagged Fibonacci generator.
///
+ [Serializable]
+ [DataContract(Namespace = "urn:MathNet/Numerics/Random")]
public class Palf : RandomSource
{
///
@@ -147,23 +150,28 @@ namespace MathNet.Numerics.Random
///
/// Gets the short lag of the Lagged Fibonacci pseudo-random number generator.
///
+ [DataMember(Order = 1)]
public int ShortLag { get; private set; }
///
/// Gets the long lag of the Lagged Fibonacci pseudo-random number generator.
///
+ [DataMember(Order = 2)]
public int LongLag { get; private set; }
///
/// Stores an array of random numbers
///
+ [DataMember(Order = 3)]
readonly uint[] _x;
+ [DataMember(Order = 4)]
readonly int _threads;
///
/// Stores an index for the random number array element that will be accessed next.
///
+ [DataMember(Order = 5)]
int _k;
///
diff --git a/src/Numerics/Random/RandomSource.cs b/src/Numerics/Random/RandomSource.cs
index cce5a1f8..6a2211f4 100644
--- a/src/Numerics/Random/RandomSource.cs
+++ b/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.
///
+ [Serializable]
+ [DataContract(Namespace = "urn:MathNet/Numerics/Random")]
public abstract class RandomSource : System.Random
{
readonly bool _threadSafe;
diff --git a/src/Numerics/Random/SystemRandomSource.cs b/src/Numerics/Random/SystemRandomSource.cs
index e7554c3c..06a64c6a 100644
--- a/src/Numerics/Random/SystemRandomSource.cs
+++ b/src/Numerics/Random/SystemRandomSource.cs
@@ -27,7 +27,9 @@
// OTHER DEALINGS IN THE SOFTWARE.
//
+using System;
using System.Collections.Generic;
+using System.Runtime.Serialization;
using MathNet.Numerics.Threading;
#if PORTABLE
@@ -42,8 +44,11 @@ namespace MathNet.Numerics.Random
///
/// A random number generator based on the class in the .NET library.
///
+ [Serializable]
+ [DataContract(Namespace = "urn:MathNet/Numerics/Random")]
public class SystemRandomSource : RandomSource
{
+ [DataMember(Order = 1)]
readonly System.Random _random;
///
diff --git a/src/Numerics/Random/WH1982.cs b/src/Numerics/Random/WH1982.cs
index 4d4309d9..9dde71e4 100644
--- a/src/Numerics/Random/WH1982.cs
+++ b/src/Numerics/Random/WH1982.cs
@@ -27,7 +27,9 @@
// OTHER DEALINGS IN THE SOFTWARE.
//
+using System;
using System.Collections.Generic;
+using System.Runtime.Serialization;
#if !PORTABLE
using System.Runtime;
@@ -41,6 +43,8 @@ namespace MathNet.Numerics.Random
/// See: Wichmann, B. A. & Hill, I. D. (1982), "Algorithm AS 183:
/// An efficient and portable pseudo-random number generator". Applied Statistics 31 (1982) 188-190
///
+ [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;
///
diff --git a/src/Numerics/Random/WH2006.cs b/src/Numerics/Random/WH2006.cs
index 4ec45db0..a0034748 100644
--- a/src/Numerics/Random/WH2006.cs
+++ b/src/Numerics/Random/WH2006.cs
@@ -27,7 +27,9 @@
// OTHER DEALINGS IN THE SOFTWARE.
//
+using System;
using System.Collections.Generic;
+using System.Runtime.Serialization;
#if !PORTABLE
using System.Runtime;
@@ -41,6 +43,8 @@ namespace MathNet.Numerics.Random
/// See: Wichmann, B. A. & Hill, I. D. (2006), "Generating good pseudo-random numbers".
/// Computational Statistics & Data Analysis 51:3 (2006) 1614-1622
///
+ [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;
///
diff --git a/src/Numerics/Random/Xorshift.cs b/src/Numerics/Random/Xorshift.cs
index 1c64226f..3553ce84 100644
--- a/src/Numerics/Random/Xorshift.cs
+++ b/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
/// Xn = a * Xn−3 + c mod 2^32
/// http://www.jstatsoft.org/v08/i14/paper
///
+ [Serializable]
+ [DataContract(Namespace = "urn:MathNet/Numerics/Random")]
public class Xorshift : RandomSource
{
///
@@ -72,26 +75,31 @@ namespace MathNet.Numerics.Random
///
/// Seed or last but three unsigned random number.
///
+ [DataMember(Order = 1)]
ulong _x;
///
/// Last but two unsigned random number.
///
+ [DataMember(Order = 2)]
ulong _y;
///
/// Last but one unsigned random number.
///
+ [DataMember(Order = 3)]
ulong _z;
///
/// The value of the carry over.
///
+ [DataMember(Order = 4)]
ulong _c;
///
/// The multiplier.
///
+ [DataMember(Order = 5)]
readonly ulong _a;
///
diff --git a/src/UnitTests/Random/RandomSerializationTests.cs b/src/UnitTests/Random/RandomSerializationTests.cs
new file mode 100644
index 00000000..f455cb20
--- /dev/null
+++ b/src/UnitTests/Random/RandomSerializationTests.cs
@@ -0,0 +1,97 @@
+//
+// 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.
+//
+
+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);
+ }
+ }
+}
diff --git a/src/UnitTests/UnitTests.csproj b/src/UnitTests/UnitTests.csproj
index 77a3231b..25595c6b 100644
--- a/src/UnitTests/UnitTests.csproj
+++ b/src/UnitTests/UnitTests.csproj
@@ -365,6 +365,7 @@
+