From 4b039858052aba7eabdd0034fc995f846447745e Mon Sep 17 00:00:00 2001 From: Marcus Cuda Date: Sun, 19 Sep 2010 19:41:16 +0800 Subject: [PATCH] merged Andriy's Parallel additive lagged Fibonacci RNG --- src/Numerics/Numerics.csproj | 1 + src/Numerics/Random/Palf.cs | 213 +++++++++++++++++++++++++++++ src/Silverlight/Silverlight.csproj | 3 + src/UnitTests/Random/PalfTests.cs | 58 ++++++++ src/UnitTests/UnitTests.csproj | 1 + 5 files changed, 276 insertions(+) create mode 100644 src/Numerics/Random/Palf.cs create mode 100644 src/UnitTests/Random/PalfTests.cs diff --git a/src/Numerics/Numerics.csproj b/src/Numerics/Numerics.csproj index 6dc74557..16cc424a 100644 --- a/src/Numerics/Numerics.csproj +++ b/src/Numerics/Numerics.csproj @@ -349,6 +349,7 @@ + diff --git a/src/Numerics/Random/Palf.cs b/src/Numerics/Random/Palf.cs new file mode 100644 index 00000000..42c3c28a --- /dev/null +++ b/src/Numerics/Random/Palf.cs @@ -0,0 +1,213 @@ +// +// 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-2010 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. +// + +namespace MathNet.Numerics.Random +{ + using System; + using Properties; + using Threading; + + /// + /// Represents a Parallel Additive Lagged Fibonacci pseudo-random number generator. + /// + /// + /// 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 + /// Wikipedia - Lagged Fibonacci generator. + /// + public class Palf : AbstractRandomNumberGenerator + { + /// + /// Dafult value for the ShortLag + /// + private const int DefaultShortLag = 418; + + /// + /// Default value for the LongLag + /// + private const int DefaultLongLag = 1279; + + /// + /// The multiplier to compute a double-precision floating point number [0, 1) + /// + private const double IntToDoubleMultiplier = 1.0 / (int.MaxValue + 1.0); + + /// + /// Initializes a new instance of the class using + /// the current time as the seed. + /// + /// If the seed value is zero, it is set to one. Uses the + /// value of to + /// set whether the instance is thread safe. + public Palf() : this((int)DateTime.Now.Ticks) + { + } + + /// + /// Initializes a new instance of the class using + /// the current time as the seed. + /// + /// if set to true , the class is thread safe. + public Palf(bool threadSafe) : this((int)DateTime.Now.Ticks, threadSafe, DefaultShortLag, DefaultLongLag) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The seed value. + /// If the seed value is zero, it is set to one. Uses the + /// value of to + /// set whether the instance is thread safe. + public Palf(int seed) : this(seed, Control.ThreadSafeRandomNumberGenerators, DefaultShortLag, DefaultLongLag) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The seed value. + /// if set to true, the class is thread safe. + /// The ShortLag value + /// TheLongLag value + public Palf(int seed, bool threadSafe, int shortLag, int longLag) : base(threadSafe) + { + if (shortLag < 1) + { + throw new ArgumentException(Resources.ArgumentMustBePositive, "shortLag"); + } + + if (longLag <= shortLag) + { + throw new ArgumentException("longLag"); + } + + if (seed == 0) + { + seed = 1; + } + + ShortLag = shortLag; + + // Align LongLag to number of worker threads. + if (longLag % Control.NumberOfParallelWorkerThreads == 0) + { + LongLag = longLag; + } + else + { + LongLag = ((longLag / Control.NumberOfParallelWorkerThreads) + 1) * Control.NumberOfParallelWorkerThreads; + } + + _x = new uint[LongLag]; + var gen = new MersenneTwister(seed); + for (var j = 0; j < LongLag; ++j) + { + _x[j] = (uint)(gen.NextDouble() * uint.MaxValue); + } + + _i = LongLag; + } + + /// + /// Gets the short lag of the Lagged Fibonacci pseudo-random number generator. + /// + public int ShortLag + { + get; + private set; + } + + /// + /// Gets the long lag of the Lagged Fibonacci pseudo-random number generator. + /// + public int LongLag + { + get; + private set; + } + + /// + /// Stores an array of random numbers + /// + private readonly uint[] _x; + + /// + /// Stores an index for the random number array element that will be accessed next. + /// + private int _i; + + /// + /// Fills the array with new unsigned random numbers. + /// + /// + /// Generated random numbers are 32-bit unsigned integers greater than or equal to 0 + /// and less than or equal to . + /// + private void Fill() + { + CommonParallel.For( + 0, + Control.NumberOfParallelWorkerThreads, + 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]; + } + }); + _i = 0; + } + + /// + /// 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() + { + if (_i >= LongLag) + { + Fill(); + } + + var x = _x[_i++]; + return (int)(x >> 1) * IntToDoubleMultiplier; + } + } +} diff --git a/src/Silverlight/Silverlight.csproj b/src/Silverlight/Silverlight.csproj index edc39828..f6a2c9a7 100644 --- a/src/Silverlight/Silverlight.csproj +++ b/src/Silverlight/Silverlight.csproj @@ -758,6 +758,9 @@ Random\Mrg32k3a.cs + + Random\Palf.cs + Random\SystemCrypto.cs diff --git a/src/UnitTests/Random/PalfTests.cs b/src/UnitTests/Random/PalfTests.cs new file mode 100644 index 00000000..7545eb47 --- /dev/null +++ b/src/UnitTests/Random/PalfTests.cs @@ -0,0 +1,58 @@ +// +// 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-2010 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. +// + +namespace MathNet.Numerics.UnitTests.Random +{ + using MbUnit.Framework; + using Numerics.Random; + + [TestFixture] + public class PalfTests : RandomTests + { + public PalfTests() + : base(typeof(Palf)) + { + } + + [Test] + [ExpectedArgumentException] + public void ThrowsArgumentExceptionWhenShortLagIsNonPositive() + { + var random = new Palf(1, true, 0, 10); + } + + [Test] + [ExpectedArgumentException] + public void ThrowsArgumentExceptionWhenLongLagIsNotGreaterThanShortLag() + { + var random = new Palf(1, true, 10, 10); + } + } +} \ No newline at end of file diff --git a/src/UnitTests/UnitTests.csproj b/src/UnitTests/UnitTests.csproj index ca2bb1a2..27aee4ab 100644 --- a/src/UnitTests/UnitTests.csproj +++ b/src/UnitTests/UnitTests.csproj @@ -321,6 +321,7 @@ +