forked from tsai/mathnet-numerics
5 changed files with 276 additions and 0 deletions
@ -0,0 +1,213 @@ |
|||
// <copyright file="Palf.cs" company="Math.NET">
|
|||
// 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.
|
|||
// </copyright>
|
|||
|
|||
namespace MathNet.Numerics.Random |
|||
{ |
|||
using System; |
|||
using Properties; |
|||
using Threading; |
|||
|
|||
/// <summary>
|
|||
/// Represents a Parallel Additive Lagged Fibonacci pseudo-random number generator.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// The <see cref="Palf"/> type bases upon the implementation in the
|
|||
/// <a href="http://www.boost.org/libs/random/index.html">Boost Random Number Library</a>.
|
|||
/// 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>
|
|||
public class Palf : AbstractRandomNumberGenerator |
|||
{ |
|||
/// <summary>
|
|||
/// Dafult value for the ShortLag
|
|||
/// </summary>
|
|||
private const int DefaultShortLag = 418; |
|||
|
|||
/// <summary>
|
|||
/// Default value for the LongLag
|
|||
/// </summary>
|
|||
private const int DefaultLongLag = 1279; |
|||
|
|||
/// <summary>
|
|||
/// The multiplier to compute a double-precision floating point number [0, 1)
|
|||
/// </summary>
|
|||
private const double IntToDoubleMultiplier = 1.0 / (int.MaxValue + 1.0); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Palf"/> class using
|
|||
/// the current time as the seed.
|
|||
/// </summary>
|
|||
/// <remarks>If the seed value is zero, it is set to one. Uses the
|
|||
/// value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to
|
|||
/// set whether the instance is thread safe.</remarks>
|
|||
public Palf() : this((int)DateTime.Now.Ticks) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Palf"/> class using
|
|||
/// the current time as the seed.
|
|||
/// </summary>
|
|||
/// <param name="threadSafe">if set to <c>true</c> , the class is thread safe.</param>
|
|||
public Palf(bool threadSafe) : this((int)DateTime.Now.Ticks, threadSafe, DefaultShortLag, DefaultLongLag) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Palf"/> class.
|
|||
/// </summary>
|
|||
/// <param name="seed">The seed value.</param>
|
|||
/// <remarks>If the seed value is zero, it is set to one. Uses the
|
|||
/// value of <see cref="Control.ThreadSafeRandomNumberGenerators"/> to
|
|||
/// set whether the instance is thread safe.</remarks>
|
|||
public Palf(int seed) : this(seed, Control.ThreadSafeRandomNumberGenerators, DefaultShortLag, DefaultLongLag) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Palf"/> class.
|
|||
/// </summary>
|
|||
/// <param name="seed">The seed value.</param>
|
|||
/// <param name="threadSafe">if set to <c>true</c>, the class is thread safe.</param>
|
|||
/// <param name="shortLag">The ShortLag value</param>
|
|||
/// <param name="longLag">TheLongLag value</param>
|
|||
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; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the short lag of the Lagged Fibonacci pseudo-random number generator.
|
|||
/// </summary>
|
|||
public int ShortLag |
|||
{ |
|||
get; |
|||
private set; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the long lag of the Lagged Fibonacci pseudo-random number generator.
|
|||
/// </summary>
|
|||
public int LongLag |
|||
{ |
|||
get; |
|||
private set; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Stores an array of <see cref="LongLag"/> random numbers
|
|||
/// </summary>
|
|||
private readonly uint[] _x; |
|||
|
|||
/// <summary>
|
|||
/// Stores an index for the random number array element that will be accessed next.
|
|||
/// </summary>
|
|||
private int _i; |
|||
|
|||
/// <summary>
|
|||
/// Fills the array <see cref="_x"/> with <see cref="LongLag"/> new unsigned random numbers.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// Generated random numbers are 32-bit unsigned integers greater than or equal to 0
|
|||
/// and less than or equal to <see cref="Int32.MaxValue"/>.
|
|||
/// </remarks>
|
|||
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; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns a random number between 0.0 and 1.0.
|
|||
/// </summary>
|
|||
/// <returns>
|
|||
/// A double-precision floating point number greater than or equal to 0.0, and less than 1.0.
|
|||
/// </returns>
|
|||
protected override double DoSample() |
|||
{ |
|||
if (_i >= LongLag) |
|||
{ |
|||
Fill(); |
|||
} |
|||
|
|||
var x = _x[_i++]; |
|||
return (int)(x >> 1) * IntToDoubleMultiplier; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,58 @@ |
|||
// <copyright file="PalfTests.cs" company="Math.NET">
|
|||
// 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.
|
|||
// </copyright>
|
|||
|
|||
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); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue