Browse Source

Random: api cleanup

pull/184/head
Christoph Ruegg 13 years ago
parent
commit
40bad6b301
  1. 111
      src/FSharp/Random.fs
  2. 6
      src/Numerics/Random/CryptoRandomSource.cs
  3. 6
      src/Numerics/Random/Mcg31m1.cs
  4. 8
      src/Numerics/Random/Mcg59.cs
  5. 11
      src/Numerics/Random/MersenneTwister.cs
  6. 6
      src/Numerics/Random/Mrg32k3a.cs
  7. 12
      src/Numerics/Random/Palf.cs
  8. 116
      src/Numerics/Random/RandomExtensions.cs
  9. 27
      src/Numerics/Random/RandomSource.cs
  10. 59
      src/Numerics/Random/SystemRandomSource.cs
  11. 6
      src/Numerics/Random/WH1982.cs
  12. 6
      src/Numerics/Random/WH2006.cs
  13. 6
      src/Numerics/Random/Xorshift.cs
  14. 2
      src/UnitTests/Random/Mcg31m1Tests.cs
  15. 2
      src/UnitTests/Random/Mcg59Tests.cs
  16. 2
      src/UnitTests/Random/MersenneTwisterTests.cs
  17. 2
      src/UnitTests/Random/Mrg32k3aTests.cs
  18. 2
      src/UnitTests/Random/PalfTests.cs
  19. 2
      src/UnitTests/Random/SystemRandomSourceTests.cs
  20. 2
      src/UnitTests/Random/WH1982Tests.cs
  21. 2
      src/UnitTests/Random/WH2006Tests.cs
  22. 2
      src/UnitTests/Random/XorshiftTests.cs

111
src/FSharp/Random.fs

@ -37,78 +37,67 @@ module Random =
let shared = SystemRandomSource.Default :> System.Random
/// Default sampling, efficient but without custom seed (uses robust seeds internally)
let samples length = SystemRandomSource.Samples(length)
let sampleSeq () = SystemRandomSource.SampleSequence()
let inline doubles (length:int) = SystemRandomSource.Doubles(length)
let inline doubleSeq () = SystemRandomSource.DoubleSequence()
let inline doubleFill (values:double[]) = SystemRandomSource.Doubles(values)
/// Creates a default .Net system pRNG with a custom seed based on uinque GUIDs
let system () = new SystemRandomSource() :> System.Random
let systemSeed (seed:int) = new SystemRandomSource(seed) :> System.Random
let systemSamples (seed:int) length = SystemRandomSource.Samples(length, seed)
let systemSampleSeq (seed:int) = SystemRandomSource.SampleSequence(seed)
let inline doublesSeed (seed:int) (length:int) = SystemRandomSource.Doubles(length, seed)
let inline doubleSeqSeed (seed:int) = SystemRandomSource.DoubleSequence(seed)
let inline doubleFillSeed (seed:int) (values:double[]) = SystemRandomSource.Doubles(values, seed)
/// Creates a default .Net system pRNG with a robust seed
let systemShared = shared
let inline system () = SystemRandomSource() :> System.Random
let inline systemSeed (seed:int) = SystemRandomSource(seed) :> System.Random
#if PORTABLE
#else
/// Creates a default .Net cryptographic system pRNG
let crypto () = new CryptoRandomSource() :> System.Random
let cryptoWith (threadSafe:bool) = new CryptoRandomSource(threadSafe) :> System.Random
let cryptoSamples length = CryptoRandomSource.Samples(length)
let cryptoSampleSeq () = CryptoRandomSource.SampleSequence()
let inline crypto () = new CryptoRandomSource() :> System.Random
let inline cryptoWith (threadSafe:bool) = new CryptoRandomSource(threadSafe) :> System.Random
let inline cryptoDoubles length = CryptoRandomSource.Doubles(length)
let inline cryptoDoubleSeq () = CryptoRandomSource.DoubleSequence()
#endif
/// Creates a Mersenne Twister 19937 pRNG with a custom seed based on uinque GUIDs
let mersenneTwister () = new MersenneTwister() :> System.Random
let mersenneTwisterSeed (seed:int) = new MersenneTwister(seed) :> System.Random
let mersenneTwisterWith seed threadSafe = new MersenneTwister(seed, threadSafe) :> System.Random
let mersenneTwisterSamples (seed:int) length = MersenneTwister.Samples(length, seed)
let mersenneTwisterSampleSeq (seed:int) = MersenneTwister.SampleSequence(seed)
/// Creates a Mersenne Twister 19937 pRNG with a robust seed
let mersenneTwisterShared = MersenneTwister.Default :> System.Random
let inline mersenneTwister () = MersenneTwister() :> System.Random
let inline mersenneTwisterSeed (seed:int) = MersenneTwister(seed) :> System.Random
let inline mersenneTwisterWith (seed:int) threadSafe = MersenneTwister(seed, threadSafe) :> System.Random
/// Creates a multiply-with-carry Xorshift (Xn = a * Xn−3 + c mod 2^32) pRNG with a custom seed based on uinque GUIDs
let xorshift () = new Xorshift() :> System.Random
let xorshiftSeed (seed:int) = new Xorshift(seed) :> System.Random
let xorshiftWith seed threadSafe = new Xorshift(seed, threadSafe) :> System.Random
let xorshiftCustom seed threadSafe a c x1 x2 = new Xorshift(seed, threadSafe, a, c, x1, x2) :> System.Random
let xorshiftSamples (seed:int) length = Xorshift.Samples(length, seed)
let xorshiftSampleSeq (seed:int) = Xorshift.SampleSequence(seed)
/// Creates a multiply-with-carry Xorshift (Xn = a * Xn−3 + c mod 2^32) pRNG with a robust seed
let inline xorshift () = Xorshift() :> System.Random
let inline xorshiftSeed (seed:int) = Xorshift(seed) :> System.Random
let inline xorshiftWith (seed:int) threadSafe = Xorshift(seed, threadSafe) :> System.Random
let inline xorshiftCustom (seed:int) threadSafe a c x1 x2 = Xorshift(seed, threadSafe, a, c, x1, x2) :> System.Random
/// Creates a Wichmann-Hill’s 1982 combined multiplicative congruential pRNG with a custom seed based on uinque GUIDs
let wh1982 () = new WH1982() :> System.Random
let wh1982Seed (seed:int) = new WH1982(seed) :> System.Random
let wh1982With seed threadSafe = new WH1982(seed, threadSafe) :> System.Random
let wh1982Samples (seed:int) length = WH1982.Samples(length, seed)
let wh1982SampleSeq (seed:int) = WH1982.SampleSequence(seed)
/// Creates a Wichmann-Hill’s 1982 combined multiplicative congruential pRNG with a robust seed
let inline wh1982 () = WH1982() :> System.Random
let inline wh1982Seed (seed:int) = WH1982(seed) :> System.Random
let inline wh1982With (seed:int) threadSafe = WH1982(seed, threadSafe) :> System.Random
/// Creates a Wichmann-Hill’s 2006 combined multiplicative congruential pRNG with a custom seed based on uinque GUIDs
let wh2006 () = new WH2006() :> System.Random
let wh2006Seed (seed:int) = new WH2006(seed) :> System.Random
let wh2006With seed threadSafe = new WH2006(seed, threadSafe) :> System.Random
let wh2006Samples (seed:int) length = WH2006.Samples(length, seed)
let wh2006SampleSeq (seed:int) = WH2006.SampleSequence(seed)
/// Creates a Wichmann-Hill’s 2006 combined multiplicative congruential pRNG with a robust seed
let inline wh2006 () = WH2006() :> System.Random
let inline wh2006Seed (seed:int) = WH2006(seed) :> System.Random
let inline wh2006With (seed:int) threadSafe = WH2006(seed, threadSafe) :> System.Random
/// Creates a Parallel Additive Lagged Fibonacci pRNG with a custom seed based on uinque GUIDs
let palf () = new Palf() :> System.Random
let palfSeed (seed:int) = new Palf(seed) :> System.Random
let palfWith seed threadSafe = new Palf(seed, threadSafe, 418, 1279) :> System.Random
let palfCustom seed threadSafe shortLag longLag = new Palf(seed, threadSafe, shortLag, longLag) :> System.Random
let palfSamples (seed:int) length = Palf.Samples(length, seed)
let palfSampleSeq (seed:int) = Palf.SampleSequence(seed)
/// Creates a Parallel Additive Lagged Fibonacci pRNG with a robust seed
let inline palf () = Palf() :> System.Random
let inline palfSeed (seed:int) = Palf(seed) :> System.Random
let inline palfWith (seed:int) threadSafe = Palf(seed, threadSafe, 418, 1279) :> System.Random
let inline palfCustom (seed:int) threadSafe shortLag longLag = Palf(seed, threadSafe, shortLag, longLag) :> System.Random
/// Creates a Multiplicative congruential generator using a modulus of 2^59 and a multiplier of 13^13 pRNG with a custom seed based on uinque GUIDs
let mcg59 () = new Mcg59() :> System.Random
let mcg59Seed (seed:int) = new Mcg59(seed) :> System.Random
let mcg59With seed threadSafe = new Mcg59(seed, threadSafe) :> System.Random
let mcg59Samples (seed:int) length = Mcg59.Samples(length, seed)
let mcg59SampleSeq (seed:int) = Mcg59.SampleSequence(seed)
/// Creates a Multiplicative congruential generator using a modulus of 2^59 and a multiplier of 13^13 pRNG with a robust seed
let inline mcg59 () = Mcg59() :> System.Random
let inline mcg59Seed (seed:int) = Mcg59(seed) :> System.Random
let inline mcg59With (seed:int) threadSafe = Mcg59(seed, threadSafe) :> System.Random
/// Creates a Multiplicative congruential generator using a modulus of 2^31-1 and a multiplier of 1132489760 pRNG with a custom seed based on uinque GUIDs
let mcg31m1 () = new Mcg31m1() :> System.Random
let mcg31m1Seed (seed:int) = new Mcg31m1(seed) :> System.Random
let mcg31m1With seed threadSafe = new Mcg31m1(seed, threadSafe) :> System.Random
let mcg31m1Samples (seed:int) length = Mcg31m1.Samples(length, seed)
let mcg31m1SampleSeq (seed:int) = Mcg31m1.SampleSequence(seed)
/// Creates a Multiplicative congruential generator using a modulus of 2^31-1 and a multiplier of 1132489760 pRNG with a robust seed
let inline mcg31m1 () = Mcg31m1() :> System.Random
let inline mcg31m1Seed (seed:int) = Mcg31m1(seed) :> System.Random
let inline mcg31m1With (seed:int) threadSafe = Mcg31m1(seed, threadSafe) :> System.Random
/// Creates a 32-bit combined multiple recursive generator with 2 components of order 3 pRNG with a custom seed based on uinque GUIDs
let mrg32k3a () = new Mrg32k3a() :> System.Random
let mrg32k3aSeed (seed:int) = new Mrg32k3a(seed) :> System.Random
let mrg32k3aWith seed threadSafe = new Mrg32k3a(seed, threadSafe) :> System.Random
let mrg32k3aSamples (seed:int) length = Mrg32k3a.Samples(length, seed)
let mrg32k3aSampleSeq (seed:int) = Mrg32k3a.SampleSequence(seed)
/// Creates a 32-bit combined multiple recursive generator with 2 components of order 3 pRNG with a robust seed
let inline mrg32k3a () = Mrg32k3a() :> System.Random
let inline mrg32k3aSeed (seed:int) = Mrg32k3a(seed) :> System.Random
let inline mrg32k3aWith (seed:int) threadSafe = Mrg32k3a(seed, threadSafe) :> System.Random

6
src/Numerics/Random/CryptoRandomSource.cs

@ -92,7 +92,7 @@ namespace MathNet.Numerics.Random
/// <returns>
/// A double-precision floating point number greater than or equal to 0.0, and less than 1.0.
/// </returns>
protected override double DoSample()
protected override sealed double DoSample()
{
var bytes = new byte[4];
_crypto.GetBytes(bytes);
@ -109,7 +109,7 @@ namespace MathNet.Numerics.Random
/// <summary>
/// Returns an array of random numbers greater than or equal to 0.0 and less than 1.0.
/// </summary>
public static double[] Samples(int length)
public static double[] Doubles(int length)
{
var rnd = new RNGCryptoServiceProvider();
var bytes = new byte[length*4];
@ -125,7 +125,7 @@ namespace MathNet.Numerics.Random
/// <summary>
/// Returns an infinite sequence of random numbers greater than or equal to 0.0 and less than 1.0.
/// </summary>
public static IEnumerable<double> SampleSequence()
public static IEnumerable<double> DoubleSequence()
{
var rnd = new RNGCryptoServiceProvider();
var buffer = new byte[1024*4];

6
src/Numerics/Random/Mcg31m1.cs

@ -95,7 +95,7 @@ namespace MathNet.Numerics.Random
/// <returns>
/// A double-precision floating point number greater than or equal to 0.0, and less than 1.0.
/// </returns>
protected override double DoSample()
protected override sealed double DoSample()
{
double ret = _xn*Reciprocal;
_xn = (_xn*Multiplier)%Modulus;
@ -106,7 +106,7 @@ namespace MathNet.Numerics.Random
/// Returns an array of random numbers greater than or equal to 0.0 and less than 1.0.
/// </summary>
/// <remarks>Supports being called in parallel from multiple threads.</remarks>
public static double[] Samples(int length, int seed)
public static double[] Doubles(int length, int seed)
{
if (seed == 0)
{
@ -127,7 +127,7 @@ namespace MathNet.Numerics.Random
/// Returns an infinite sequence of random numbers greater than or equal to 0.0 and less than 1.0.
/// </summary>
/// <remarks>Supports being called in parallel from multiple threads, but the result must be enumerated from a single thread each.</remarks>
public static IEnumerable<double> SampleSequence(int seed)
public static IEnumerable<double> DoubleSequence(int seed)
{
if (seed == 0)
{

8
src/Numerics/Random/Mcg59.cs

@ -37,9 +37,9 @@ namespace MathNet.Numerics.Random
/// </summary>
public class Mcg59 : RandomSource
{
const double Reciprocal = 1.0/Modulus;
const ulong Modulus = 576460752303423488;
const ulong Multiplier = 302875106592253;
const double Reciprocal = 1.0/Modulus;
ulong _xn;
/// <summary>
@ -97,7 +97,7 @@ namespace MathNet.Numerics.Random
/// <returns>
/// A double-precision floating point number greater than or equal to 0.0, and less than 1.0.
/// </returns>
protected override double DoSample()
protected override sealed double DoSample()
{
double ret = _xn*Reciprocal;
_xn = (_xn*Multiplier)%Modulus;
@ -108,7 +108,7 @@ namespace MathNet.Numerics.Random
/// Returns an array of random numbers greater than or equal to 0.0 and less than 1.0.
/// </summary>
/// <remarks>Supports being called in parallel from multiple threads.</remarks>
public static double[] Samples(int length, int seed)
public static double[] Doubles(int length, int seed)
{
if (seed == 0)
{
@ -129,7 +129,7 @@ namespace MathNet.Numerics.Random
/// Returns an infinite sequence of random numbers greater than or equal to 0.0 and less than 1.0.
/// </summary>
/// <remarks>Supports being called in parallel from multiple threads, but the result must be enumerated from a single thread each.</remarks>
public static IEnumerable<double> SampleSequence(int seed)
public static IEnumerable<double> DoubleSequence(int seed)
{
if (seed == 0)
{

11
src/Numerics/Random/MersenneTwister.cs

@ -67,7 +67,12 @@
*/
using System.Collections.Generic;
#if PORTABLE
using System;
#else
using System.Threading;
#endif
namespace MathNet.Numerics.Random
{
@ -316,7 +321,7 @@ namespace MathNet.Numerics.Random
/// <returns>
/// A double-precision floating point number greater than or equal to 0.0, and less than 1.0.
/// </returns>
protected override double DoSample()
protected override sealed double DoSample()
{
return genrand_int32()*Reciprocal;
}
@ -335,7 +340,7 @@ namespace MathNet.Numerics.Random
/// Returns an array of random numbers greater than or equal to 0.0 and less than 1.0.
/// </summary>
/// <remarks>Supports being called in parallel from multiple threads.</remarks>
public static double[] Samples(int length, int seed)
public static double[] Doubles(int length, int seed)
{
uint[] t = new uint[624];
int k;
@ -389,7 +394,7 @@ namespace MathNet.Numerics.Random
/// Returns an infinite sequence of random numbers greater than or equal to 0.0 and less than 1.0.
/// </summary>
/// <remarks>Supports being called in parallel from multiple threads, but the result must be enumerated from a single thread each.</remarks>
public static IEnumerable<double> SampleSequence(int seed)
public static IEnumerable<double> DoubleSequence(int seed)
{
uint[] t = new uint[624];
int k;

6
src/Numerics/Random/Mrg32k3a.cs

@ -110,7 +110,7 @@ namespace MathNet.Numerics.Random
/// <returns>
/// A double-precision floating point number greater than or equal to 0.0, and less than 1.0.
/// </returns>
protected override double DoSample()
protected override sealed double DoSample()
{
double xn = A12*_xn2 - A13*_xn3;
double k = (long)(xn/Modulus1);
@ -145,7 +145,7 @@ namespace MathNet.Numerics.Random
/// Returns an array of random numbers greater than or equal to 0.0 and less than 1.0.
/// </summary>
/// <remarks>Supports being called in parallel from multiple threads.</remarks>
public static double[] Samples(int length, int seed)
public static double[] Doubles(int length, int seed)
{
double x1 = 1;
double x2 = 1;
@ -188,7 +188,7 @@ namespace MathNet.Numerics.Random
/// Returns an infinite sequence of random numbers greater than or equal to 0.0 and less than 1.0.
/// </summary>
/// <remarks>Supports being called in parallel from multiple threads, but the result must be enumerated from a single thread each.</remarks>
public static IEnumerable<double> SampleSequence(int seed)
public static IEnumerable<double> DoubleSequence(int seed)
{
double x1 = 1;
double x2 = 1;

12
src/Numerics/Random/Palf.cs

@ -137,7 +137,7 @@ namespace MathNet.Numerics.Random
LongLag = ((longLag/_threads) + 1)*_threads;
}
_x = Generate.Map(MersenneTwister.Samples(LongLag, seed), uniform => (uint)(uniform*uint.MaxValue));
_x = Generate.Map(MersenneTwister.Doubles(LongLag, seed), uniform => (uint)(uniform*uint.MaxValue));
_k = LongLag;
}
@ -212,7 +212,7 @@ namespace MathNet.Numerics.Random
/// <returns>
/// A double-precision floating point number greater than or equal to 0.0, and less than 1.0.
/// </returns>
protected override double DoSample()
protected override sealed double DoSample()
{
if (_k >= LongLag)
{
@ -227,7 +227,7 @@ namespace MathNet.Numerics.Random
/// Returns an array of random numbers greater than or equal to 0.0 and less than 1.0.
/// </summary>
/// <remarks>Supports being called in parallel from multiple threads.</remarks>
public static double[] Samples(int length, int seed)
public static double[] Doubles(int length, int seed)
{
if (seed == 0)
{
@ -244,7 +244,7 @@ namespace MathNet.Numerics.Random
longLag = ((longLag/threads) + 1)*threads;
}
var x = Generate.Map(MersenneTwister.Samples(longLag, seed), uniform => (uint)(uniform*uint.MaxValue));
var x = Generate.Map(MersenneTwister.Doubles(longLag, seed), uniform => (uint)(uniform*uint.MaxValue));
var k = longLag;
var data = new double[length];
@ -277,7 +277,7 @@ namespace MathNet.Numerics.Random
/// Returns an infinite sequence of random numbers greater than or equal to 0.0 and less than 1.0.
/// </summary>
/// <remarks>Supports being called in parallel from multiple threads, but the result must be enumerated from a single thread each.</remarks>
public static IEnumerable<double> SampleSequence(int seed)
public static IEnumerable<double> DoubleSequence(int seed)
{
if (seed == 0)
{
@ -294,7 +294,7 @@ namespace MathNet.Numerics.Random
longLag = ((longLag/threads) + 1)*threads;
}
var x = Generate.Map(MersenneTwister.Samples(longLag, seed), uniform => (uint)(uniform*uint.MaxValue));
var x = Generate.Map(MersenneTwister.Doubles(longLag, seed), uniform => (uint)(uniform*uint.MaxValue));
var k = longLag;
while (true)

116
src/Numerics/Random/RandomExtensions.cs

@ -29,27 +29,111 @@
// </copyright>
using System;
using System.Collections.Generic;
namespace MathNet.Numerics.Random
{
/// <summary>
/// This class implements extension methods for the System.Random class. The extension methods generate
/// pseudo-random distributed numbers for types other than double and int32.
/// </summary>
public static class RandomExtensions
{
/// <summary>
/// Fills an array with uniform random numbers greater than or equal to 0.0 and less than 1.0.
/// </summary>
/// <param name="rnd">The random number generator.</param>
/// <param name="values">The array to fill with random values.</param>
/// <remarks>
/// This extension is thread-safe if and only if called on an random number
/// generator provided by Math.NET Nummerics or derived from the RandomSource class.
/// </remarks>
public static void NextDoubles(this System.Random rnd, double[] values)
{
var rs = rnd as RandomSource;
if (rs != null)
{
rs.NextDoubles(values);
return;
}
for (var i = 0; i < values.Length; i++)
{
values[i] = rnd.NextDouble();
}
}
/// <summary>
/// Returns an array of uniform random numbers greater than or equal to 0.0 and less than 1.0.
/// </summary>
/// <param name="rnd">The random number generator.</param>
/// <param name="count">The size of the array to fill.</param>
/// <remarks>
/// This extension is thread-safe if and only if called on an random number
/// generator provided by Math.NET Nummerics or derived from the RandomSource class.
/// </remarks>
public static double[] NextDoubles(this System.Random rnd, int count)
{
var values = new double[count];
NextDoubles(rnd, values);
return values;
}
/// <summary>
/// Returns an infinite sequence of uniform random numbers greater than or equal to 0.0 and less than 1.0.
/// </summary>
/// <remarks>
/// This extension is thread-safe if and only if called on an random number
/// generator provided by Math.NET Nummerics or derived from the RandomSource class.
/// </remarks>
public static IEnumerable<double> NextDoubleSequence(this System.Random rnd)
{
var rs = rnd as RandomSource;
if (rs != null)
{
return rs.NextDoubleSequence();
}
return NextDoubleSequenceEnumerable(rnd);
}
static IEnumerable<double> NextDoubleSequenceEnumerable(System.Random rnd)
{
while (true)
{
yield return rnd.NextDouble();
}
}
/// <summary>
/// Returns an array of uniform random bytes.
/// </summary>
/// <param name="rnd">The random number generator.</param>
/// <param name="count">The size of the array to fill.</param>
/// <remarks>
/// This extension is thread-safe if and only if called on an random number
/// generator provided by Math.NET Nummerics or derived from the RandomSource class.
/// </remarks>
public static byte[] NextBytes(this System.Random rnd, int count)
{
var values = new byte[count];
rnd.NextBytes(values);
return values;
}
/// <summary>
/// Returns a nonnegative random number less than <see cref="Int64.MaxValue"/>.
/// </summary>
/// <param name="rnd">
/// The random object to extend.
/// </param>
/// <param name="rnd">The random number generator.</param>
/// <returns>
/// A 64-bit signed integer greater than or equal to 0, and less than <see cref="Int64.MaxValue"/>; that is,
/// the range of return values includes 0 but not <see cref="Int64.MaxValue"/>.
/// </returns>
/// <seealso cref="NextFullRangeInt64"/>
/// <remarks>
/// This extension is thread-safe if and only if called on an random number
/// generator provided by Math.NET Nummerics or derived from the RandomSource class.
/// </remarks>
public static long NextInt64(this System.Random rnd)
{
var buffer = new byte[sizeof (long)];
@ -68,14 +152,16 @@ namespace MathNet.Numerics.Random
/// <summary>
/// Returns a random number of the full Int32 range.
/// </summary>
/// <param name="rnd">
/// The random object to extend.
/// </param>
/// <param name="rnd">The random number generator.</param>
/// <returns>
/// A 32-bit signed integer of the full range, including 0, negative numbers,
/// <see cref="Int32.MaxValue"/> and <see cref="Int32.MinValue"/>.
/// </returns>
/// <seealso cref="System.Random.Next()"/>
/// <remarks>
/// This extension is thread-safe if and only if called on an random number
/// generator provided by Math.NET Nummerics or derived from the RandomSource class.
/// </remarks>
public static int NextFullRangeInt32(this System.Random rnd)
{
var buffer = new byte[sizeof (int)];
@ -86,14 +172,16 @@ namespace MathNet.Numerics.Random
/// <summary>
/// Returns a random number of the full Int64 range.
/// </summary>
/// <param name="rnd">
/// The random object to extend.
/// </param>
/// <param name="rnd">The random number generator.</param>
/// <returns>
/// A 64-bit signed integer of the full range, including 0, negative numbers,
/// <see cref="Int64.MaxValue"/> and <see cref="Int64.MinValue"/>.
/// </returns>
/// <seealso cref="NextInt64"/>
/// <remarks>
/// This extension is thread-safe if and only if called on an random number
/// generator provided by Math.NET Nummerics or derived from the RandomSource class.
/// </remarks>
public static long NextFullRangeInt64(this System.Random rnd)
{
var buffer = new byte[sizeof (long)];
@ -104,13 +192,15 @@ namespace MathNet.Numerics.Random
/// <summary>
/// Returns a nonnegative decimal floating point random number less than 1.0.
/// </summary>
/// <param name="rnd">
/// The random object to extend.
/// </param>
/// <param name="rnd">The random number generator.</param>
/// <returns>
/// A decimal floating point number greater than or equal to 0.0, and less than 1.0; that is,
/// the range of return values includes 0.0 but not 1.0.
/// </returns>
/// <remarks>
/// This extension is thread-safe if and only if called on an random number
/// generator provided by Math.NET Nummerics or derived from the RandomSource class.
/// </remarks>
public static decimal NextDecimal(this System.Random rnd)
{
decimal candidate;

27
src/Numerics/Random/RandomSource.cs

@ -66,36 +66,28 @@ namespace MathNet.Numerics.Random
}
/// <summary>
/// Returns an array of uniform random numbers greater than or equal to 0.0 and less than 1.0.
/// Fills an array with uniform random numbers greater than or equal to 0.0 and less than 1.0.
/// </summary>
/// <param name="n">The size of the array.</param>
/// <exception cref="ArgumentException">if n is not greater than 0.</exception>
public double[] NextDoubles(int n)
/// <param name="values">The array to fill with random values.</param>
public void NextDoubles(double[] values)
{
if (n < 1)
{
throw new ArgumentException(Resources.ArgumentMustBePositive);
}
var ret = new double[n];
if (_threadSafe)
{
lock (_lock)
{
for (var i = 0; i < ret.Length; i++)
for (var i = 0; i < values.Length; i++)
{
ret[i] = DoSample();
values[i] = DoSample();
}
}
}
else
{
for (var i = 0; i < ret.Length; i++)
for (var i = 0; i < values.Length; i++)
{
ret[i] = DoSample();
values[i] = DoSample();
}
}
return ret;
}
/// <summary>
@ -108,9 +100,10 @@ namespace MathNet.Numerics.Random
yield return NextDouble();
}
var buffer = new double[64];
while (true)
{
var buffer = NextDoubles(64);
NextDoubles(buffer);
for (int i = 0; i < buffer.Length; i++)
{
yield return buffer[i];
@ -222,7 +215,7 @@ namespace MathNet.Numerics.Random
/// 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 Sample()
protected override sealed double Sample()
{
if (_threadSafe)
{

59
src/Numerics/Random/SystemRandomSource.cs

@ -29,9 +29,15 @@
// </copyright>
using System.Collections.Generic;
using System.Threading;
using MathNet.Numerics.Threading;
#if PORTABLE
using System;
#else
using System.Runtime;
using System.Threading;
#endif
namespace MathNet.Numerics.Random
{
/// <summary>
@ -111,31 +117,42 @@ namespace MathNet.Numerics.Random
/// <returns>
/// A double-precision floating point number greater than or equal to 0.0, and less than 1.0.
/// </returns>
protected override double DoSample()
protected override sealed double DoSample()
{
return _random.NextDouble();
}
/// <summary>
/// Returns an array of uniform random numbers greater than or equal to 0.0 and less than 1.0.
/// Fill an array with uniform random numbers greater than or equal to 0.0 and less than 1.0.
/// </summary>
/// <remarks>Parallelized on large length, but also supports being called in parallel from multiple threads</remarks>
public static double[] Samples(int length)
public static void Doubles(double[] values)
{
if (length < 2048)
if (values.Length < 2048)
{
return Default.NextDoubles(length);
Default.NextDoubles(values);
return;
}
var data = new double[length];
CommonParallel.For(0, length, length >= 65536 ? 8192 : length >= 16384 ? 2048 : 1024, (a, b) =>
CommonParallel.For(0, values.Length, values.Length >= 65536 ? 8192 : values.Length >= 16384 ? 2048 : 1024, (a, b) =>
{
var rnd = new System.Random(RandomSeed.Robust());
for (int i = a; i < b; i++)
{
data[i] = rnd.NextDouble();
values[i] = rnd.NextDouble();
}
});
}
/// <summary>
/// Returns an array of uniform random numbers greater than or equal to 0.0 and less than 1.0.
/// </summary>
/// <remarks>Parallelized on large length, but also supports being called in parallel from multiple threads</remarks>
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public static double[] Doubles(int length)
{
var data = new double[length];
Doubles(data);
return data;
}
@ -143,7 +160,7 @@ namespace MathNet.Numerics.Random
/// Returns an infinite sequence of uniform random numbers greater than or equal to 0.0 and less than 1.0.
/// </summary>
/// <remarks>Supports being called in parallel from multiple threads, but the result must be enumerated from a single thread each.</remarks>
public static IEnumerable<double> SampleSequence()
public static IEnumerable<double> DoubleSequence()
{
var rnd1 = Default;
for (int i = 0; i < 128; i++)
@ -159,18 +176,28 @@ namespace MathNet.Numerics.Random
}
/// <summary>
/// Returns an array of random numbers greater than or equal to 0.0 and less than 1.0.
/// Fills an array with random numbers greater than or equal to 0.0 and less than 1.0.
/// </summary>
/// <remarks>Supports being called in parallel from multiple threads.</remarks>
public static double[] Samples(int length, int seed)
public static void Doubles(double[] values, int seed)
{
var rnd = new System.Random(seed);
var data = new double[length];
for (int i = 0; i < data.Length; i++)
for (int i = 0; i < values.Length; i++)
{
data[i] = rnd.NextDouble();
values[i] = rnd.NextDouble();
}
}
/// <summary>
/// Returns an array of random numbers greater than or equal to 0.0 and less than 1.0.
/// </summary>
/// <remarks>Supports being called in parallel from multiple threads.</remarks>
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public static double[] Doubles(int length, int seed)
{
var data = new double[length];
Doubles(data, seed);
return data;
}
@ -178,7 +205,7 @@ namespace MathNet.Numerics.Random
/// Returns an infinite sequence of random numbers greater than or equal to 0.0 and less than 1.0.
/// </summary>
/// <remarks>Supports being called in parallel from multiple threads, but the result must be enumerated from a single thread each.</remarks>
public static IEnumerable<double> SampleSequence(int seed)
public static IEnumerable<double> DoubleSequence(int seed)
{
var rnd = new System.Random(seed);

6
src/Numerics/Random/WH1982.cs

@ -105,7 +105,7 @@ namespace MathNet.Numerics.Random
/// <returns>
/// A double-precision floating point number greater than or equal to 0.0, and less than 1.0.
/// </returns>
protected override double DoSample()
protected override sealed double DoSample()
{
_xn = (171*_xn)%Modx;
_yn = (172*_yn)%Mody;
@ -120,7 +120,7 @@ namespace MathNet.Numerics.Random
/// Returns an array of random numbers greater than or equal to 0.0 and less than 1.0.
/// </summary>
/// <remarks>Supports being called in parallel from multiple threads.</remarks>
public static double[] Samples(int length, int seed)
public static double[] Doubles(int length, int seed)
{
if (seed == 0)
{
@ -147,7 +147,7 @@ namespace MathNet.Numerics.Random
/// Returns an infinite sequence of random numbers greater than or equal to 0.0 and less than 1.0.
/// </summary>
/// <remarks>Supports being called in parallel from multiple threads, but the result must be enumerated from a single thread each.</remarks>
public static IEnumerable<double> SampleSequence(int seed)
public static IEnumerable<double> DoubleSequence(int seed)
{
if (seed == 0)
{

6
src/Numerics/Random/WH2006.cs

@ -107,7 +107,7 @@ namespace MathNet.Numerics.Random
/// <returns>
/// A double-precision floating point number greater than or equal to 0.0, and less than 1.0.
/// </returns>
protected override double DoSample()
protected override sealed double DoSample()
{
_xn = 11600*_xn%Modx;
_yn = 47003*_yn%Mody;
@ -123,7 +123,7 @@ namespace MathNet.Numerics.Random
/// Returns an array of random numbers greater than or equal to 0.0 and less than 1.0.
/// </summary>
/// <remarks>Supports being called in parallel from multiple threads.</remarks>
public static double[] Samples(int length, int seed)
public static double[] Doubles(int length, int seed)
{
if (seed == 0)
{
@ -152,7 +152,7 @@ namespace MathNet.Numerics.Random
/// Returns an infinite sequence of random numbers greater than or equal to 0.0 and less than 1.0.
/// </summary>
/// <remarks>Supports being called in parallel from multiple threads, but the result must be enumerated from a single thread each.</remarks>
public static IEnumerable<double> SampleSequence(int seed)
public static IEnumerable<double> DoubleSequence(int seed)
{
if (seed == 0)
{

6
src/Numerics/Random/Xorshift.cs

@ -253,7 +253,7 @@ namespace MathNet.Numerics.Random
/// <returns>
/// A double-precision floating point number greater than or equal to 0.0, and less than 1.0.
/// </returns>
protected override double DoSample()
protected override sealed double DoSample()
{
var t = (_a*_x) + _c;
_x = _y;
@ -268,7 +268,7 @@ namespace MathNet.Numerics.Random
/// </summary>
/// <remarks>Supports being called in parallel from multiple threads.</remarks>
[CLSCompliant(false)]
public static double[] Samples(int length, int seed, ulong a = ASeed, ulong c = CSeed, ulong x1 = YSeed, ulong x2 = ZSeed)
public static double[] Doubles(int length, int seed, ulong a = ASeed, ulong c = CSeed, ulong x1 = YSeed, ulong x2 = ZSeed)
{
if (a <= c)
{
@ -299,7 +299,7 @@ namespace MathNet.Numerics.Random
/// </summary>
/// <remarks>Supports being called in parallel from multiple threads, but the result must be enumerated from a single thread each.</remarks>
[CLSCompliant(false)]
public static IEnumerable<double> SampleSequence(int seed, ulong a = ASeed, ulong c = CSeed, ulong x1 = YSeed, ulong x2 = ZSeed)
public static IEnumerable<double> DoubleSequence(int seed, ulong a = ASeed, ulong c = CSeed, ulong x1 = YSeed, ulong x2 = ZSeed)
{
if (a <= c)
{

2
src/UnitTests/Random/Mcg31m1Tests.cs

@ -49,7 +49,7 @@ namespace MathNet.Numerics.UnitTests.Random
[Test]
public void StaticSamplesConsistent()
{
Assert.That(Mcg31m1.Samples(1000, 1), Is.EqualTo(new Mcg31m1(1).NextDoubles(1000)).Within(1e-12).AsCollection);
Assert.That(Mcg31m1.Doubles(1000, 1), Is.EqualTo(new Mcg31m1(1).NextDoubles(1000)).Within(1e-12).AsCollection);
}
}
}

2
src/UnitTests/Random/Mcg59Tests.cs

@ -49,7 +49,7 @@ namespace MathNet.Numerics.UnitTests.Random
[Test]
public void StaticSamplesConsistent()
{
Assert.That(Mcg59.Samples(1000, 1), Is.EqualTo(new Mcg59(1).NextDoubles(1000)).Within(1e-12).AsCollection);
Assert.That(Mcg59.Doubles(1000, 1), Is.EqualTo(new Mcg59(1).NextDoubles(1000)).Within(1e-12).AsCollection);
}
}
}

2
src/UnitTests/Random/MersenneTwisterTests.cs

@ -62,7 +62,7 @@ namespace MathNet.Numerics.UnitTests.Random
[Test]
public void StaticSamplesConsistent()
{
Assert.That(MersenneTwister.Samples(1000, 1), Is.EqualTo(new MersenneTwister(1).NextDoubles(1000)).Within(1e-12).AsCollection);
Assert.That(MersenneTwister.Doubles(1000, 1), Is.EqualTo(new MersenneTwister(1).NextDoubles(1000)).Within(1e-12).AsCollection);
}
}
}

2
src/UnitTests/Random/Mrg32k3aTests.cs

@ -49,7 +49,7 @@ namespace MathNet.Numerics.UnitTests.Random
[Test]
public void StaticSamplesConsistent()
{
Assert.That(Mrg32k3a.Samples(1000, 1), Is.EqualTo(new Mrg32k3a(1).NextDoubles(1000)).Within(1e-12).AsCollection);
Assert.That(Mrg32k3a.Doubles(1000, 1), Is.EqualTo(new Mrg32k3a(1).NextDoubles(1000)).Within(1e-12).AsCollection);
}
}
}

2
src/UnitTests/Random/PalfTests.cs

@ -68,7 +68,7 @@ namespace MathNet.Numerics.UnitTests.Random
[Test]
public void StaticSamplesConsistent()
{
Assert.That(Palf.Samples(1000, 1), Is.EqualTo(new Palf(1).NextDoubles(1000)).Within(1e-12).AsCollection);
Assert.That(Palf.Doubles(1000, 1), Is.EqualTo(new Palf(1).NextDoubles(1000)).Within(1e-12).AsCollection);
}
}
}

2
src/UnitTests/Random/SystemRandomSourceTests.cs

@ -46,7 +46,7 @@ namespace MathNet.Numerics.UnitTests.Random
[Test]
public void StaticSamplesConsistent()
{
Assert.That(SystemRandomSource.Samples(1000, 1), Is.EqualTo(new SystemRandomSource(1).NextDoubles(1000)).Within(1e-12).AsCollection);
Assert.That(SystemRandomSource.Doubles(1000, 1), Is.EqualTo(new SystemRandomSource(1).NextDoubles(1000)).Within(1e-12).AsCollection);
}
}
}

2
src/UnitTests/Random/WH1982Tests.cs

@ -49,7 +49,7 @@ namespace MathNet.Numerics.UnitTests.Random
[Test]
public void StaticSamplesConsistent()
{
Assert.That(WH1982.Samples(1000, 1), Is.EqualTo(new WH1982(1).NextDoubles(1000)).Within(1e-12).AsCollection);
Assert.That(WH1982.Doubles(1000, 1), Is.EqualTo(new WH1982(1).NextDoubles(1000)).Within(1e-12).AsCollection);
}
}
}

2
src/UnitTests/Random/WH2006Tests.cs

@ -49,7 +49,7 @@ namespace MathNet.Numerics.UnitTests.Random
[Test]
public void StaticSamplesConsistent()
{
Assert.That(WH2006.Samples(1000, 1), Is.EqualTo(new WH2006(1).NextDoubles(1000)).Within(1e-12).AsCollection);
Assert.That(WH2006.Doubles(1000, 1), Is.EqualTo(new WH2006(1).NextDoubles(1000)).Within(1e-12).AsCollection);
}
}
}

2
src/UnitTests/Random/XorshiftTests.cs

@ -49,7 +49,7 @@ namespace MathNet.Numerics.UnitTests.Random
[Test]
public void StaticSamplesConsistent()
{
Assert.That(Xorshift.Samples(1000, 1), Is.EqualTo(new Xorshift(1).NextDoubles(1000)).Within(1e-12).AsCollection);
Assert.That(Xorshift.Doubles(1000, 1), Is.EqualTo(new Xorshift(1).NextDoubles(1000)).Within(1e-12).AsCollection);
}
}
}

Loading…
Cancel
Save