Browse Source

Generate: Map, RandomMap; prepare to phase out SignalGenerator

pull/184/head
Christoph Ruegg 13 years ago
parent
commit
5d9699eb0a
  1. 9
      src/Examples/Signals/Random.cs
  2. 131
      src/Numerics/Generate.cs
  3. 14
      src/Numerics/Signals/SignalGenerator.Chebyshev.cs
  4. 8
      src/Numerics/Signals/SignalGenerator.Equidistant.cs
  5. 81
      src/Numerics/Signals/SignalGenerator.Random.cs
  6. 12
      src/UnitTests/IntegralTransformsTests/FourierTest.cs
  7. 11
      src/UnitTests/IntegralTransformsTests/HartleyTest.cs
  8. 20
      src/UnitTests/IntegralTransformsTests/InverseTransformTest.cs
  9. 15
      src/UnitTests/IntegralTransformsTests/MatchingNaiveTransformTest.cs
  10. 14
      src/UnitTests/IntegralTransformsTests/ParsevalTheoremTest.cs

9
src/Examples/Signals/Random.cs

@ -25,6 +25,7 @@
// </copyright>
using System;
using MathNet.Numerics;
using MathNet.Numerics.Distributions;
using MathNet.Numerics.Signals;
@ -64,7 +65,7 @@ namespace Examples.SignalsExamples
{
// 1. Get 10 random samples of f(x) = (x * x) / 2 using continuous uniform distribution on [-10, 10]
var uniform = new ContinuousUniform(-10, 10);
var result = SignalGenerator.Random(Function, uniform, 10);
var result = Generate.RandomMap(10, uniform, Function);
Console.WriteLine(@" 1. Get 10 random samples of f(x) = (x * x) / 2 using continuous uniform distribution on [-10, 10]");
for (var i = 0; i < result.Length; i++)
{
@ -76,8 +77,8 @@ namespace Examples.SignalsExamples
// 2. Get 10 random samples of f(x) = (x * x) / 2 using Exponential(1) distribution and retrieve sample points
var exponential = new Exponential(1);
double[] samplePoints;
result = SignalGenerator.Random(Function, exponential, 10, out samplePoints);
double[] samplePoints = Generate.Random(10, exponential);
result = Generate.Map(samplePoints, Function);
Console.WriteLine(@"2. Get 10 random samples of f(x) = (x * x) / 2 using Exponential(1) distribution and retrieve sample points");
Console.Write(@"Points: ");
for (var i = 0; i < samplePoints.Length; i++)
@ -97,7 +98,7 @@ namespace Examples.SignalsExamples
// 3. Get 10 random samples of f(x, y) = (x * y) / 2 using ChiSquare(10) distribution
var chiSquare = new ChiSquared(10);
result = SignalGenerator.Random(TwoDomainFunction, chiSquare, 10);
result = Generate.RandomMap2(10, chiSquare, TwoDomainFunction);
Console.WriteLine(@" 3. Get 10 random samples of f(x, y) = (x * y) / 2 using ChiSquare(10) distribution");
for (var i = 0; i < result.Length; i++)
{

131
src/Numerics/Generate.cs

@ -32,10 +32,15 @@ using System;
using System.Collections.Generic;
using System.Linq;
using MathNet.Numerics.Distributions;
using MathNet.Numerics.Properties;
using MathNet.Numerics.Random;
namespace MathNet.Numerics
{
#if !NOSYSNUMERICS
using System.Numerics;
#endif
public static class Generate
{
/// <summary>
@ -301,6 +306,95 @@ namespace MathNet.Numerics
}
}
/// <summary>
/// Generate samples by sampling a function at the provided points.
/// </summary>
public static TR[] Map<T, TR>(T[] points, Func<T, TR> map)
{
var res = new TR[points.Length];
for (int i = 0; i < points.Length; i++)
{
res[i] = map(points[i]);
}
return res;
}
/// <summary>
/// Generate a sample sequence by sampling a function at the provided point sequence.
/// </summary>
public static IEnumerable<TR> MapSequence<T, TR>(IEnumerable<T> points, Func<T, TR> map)
{
return points.Select(map);
}
/// <summary>
/// Generate samples by sampling a function at the provided points.
/// </summary>
public static TR[] Map2<TA, TB, TR>(TA[] pointsA, TB[] pointsB, Func<TA, TB, TR> map)
{
if (pointsA.Length != pointsB.Length)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "pointsB");
}
var res = new TR[pointsA.Length];
for (int i = 0; i < res.Length; i++)
{
res[i] = map(pointsA[i], pointsB[i]);
}
return res;
}
/// <summary>
/// Generate a sample sequence by sampling a function at the provided point sequence.
/// </summary>
public static IEnumerable<TR> Map2Sequence<TA, TB, TR>(IEnumerable<TA> pointsA, IEnumerable<TB> pointsB, Func<TA, TB, TR> map)
{
return pointsA.Zip(pointsB, map);
}
/// <summary>
/// Generate samples by sampling a function at samples from a probability distribution.
/// </summary>
public static T[] RandomMap<T>(int length, IContinuousDistribution distribution, Func<double, T> map)
{
var res = new T[length];
for (int i = 0; i < res.Length; i++)
{
res[i] = map(distribution.Sample());
}
return res;
}
/// <summary>
/// Generate a sample sequence by sampling a function at samples from a probability distribution.
/// </summary>
public static IEnumerable<T> RandomMapSequence<T>(IContinuousDistribution distribution, Func<double, T> map)
{
return distribution.Samples().Select(map);
}
/// <summary>
/// Generate samples by sampling a function at sample pairs from a probability distribution.
/// </summary>
public static T[] RandomMap2<T>(int length, IContinuousDistribution distribution, Func<double, double, T> map)
{
var res = new T[length];
for (int i = 0; i < res.Length; i++)
{
res[i] = map(distribution.Sample(), distribution.Sample());
}
return res;
}
/// <summary>
/// Generate a sample sequence by sampling a function at sample pairs from a probability distribution.
/// </summary>
public static IEnumerable<T> RandomMap2Sequence<T>(IContinuousDistribution distribution, Func<double, double, T> map)
{
return distribution.Samples().Zip(distribution.Samples(), map);
}
/// <summary>
/// Create random samples.
/// </summary>
@ -317,6 +411,22 @@ namespace MathNet.Numerics
return distribution.Samples();
}
/// <summary>
/// Create random samples.
/// </summary>
public static Complex[] RandomComplex(int length, IContinuousDistribution distribution)
{
return RandomMap2(length, distribution, (r, i) => new Complex(r, i));
}
/// <summary>
/// Create an infinite random sample sequence.
/// </summary>
public static IEnumerable<Complex> RandomComplex(IContinuousDistribution distribution)
{
return RandomMap2Sequence(distribution, (r, i) => new Complex(r, i));
}
/// <summary>
/// Create samples with independent amplitudes of normal distribution and a flat spectral density.
/// </summary>
@ -357,26 +467,5 @@ namespace MathNet.Numerics
{
return Stable.Samples(MersenneTwister.Default, alpha, beta, scale, location);
}
/// <summary>
/// Generate sample by sampling a function at the provided points.
/// </summary>
public static TV[] Map<TU, TV>(TU[] points, Func<TU, TV> map)
{
var res = new TV[points.Length];
for (int i = 0; i < points.Length; i++)
{
res[i] = map(points[i]);
}
return res;
}
/// <summary>
/// Generate a sample sequence by sampling a function at the provided point sequence.
/// </summary>
public static IEnumerable<TV> MapSequence<TU, TV>(IEnumerable<TU> points, Func<TU, TV> map)
{
return points.Select(map);
}
}
}

14
src/Numerics/Signals/SignalGenerator.Chebyshev.cs

@ -56,12 +56,7 @@ namespace MathNet.Numerics.Signals
int sampleCount)
{
var roots = FindRoots.ChebychevPolynomialFirstKind(sampleCount, intervalBegin, intervalEnd);
var samples = new T[roots.Length];
for (int i = 0; i < samples.Length; i++)
{
samples[i] = function(roots[i]);
}
return samples;
return Generate.Map(roots, function);
}
/// <summary>
@ -83,12 +78,7 @@ namespace MathNet.Numerics.Signals
int sampleCount)
{
var roots = FindRoots.ChebychevPolynomialSecondKind(sampleCount, intervalBegin, intervalEnd);
var samples = new T[roots.Length];
for (int i = 0; i < samples.Length; i++)
{
samples[i] = function(roots[i]);
}
return samples;
return Generate.Map(roots, function);
}
}
}

8
src/Numerics/Signals/SignalGenerator.Equidistant.cs

@ -49,6 +49,7 @@ namespace MathNet.Numerics.Signals
/// <returns>The generated sample vector.</returns>
/// <exception cref="ArgumentNullException" />
/// <exception cref="ArgumentOutOfRangeException" />
[Obsolete]
public static T[] EquidistantInterval<T>(
Func<double, T> function,
double intervalBegin,
@ -102,6 +103,7 @@ namespace MathNet.Numerics.Signals
/// <returns>The generated sample vector.</returns>
/// <exception cref="ArgumentNullException" />
/// <exception cref="ArgumentOutOfRangeException" />
[Obsolete]
public static T[] EquidistantInterval<T>(
Func<double, T> function,
double intervalBegin,
@ -161,6 +163,7 @@ namespace MathNet.Numerics.Signals
/// <returns>The generated sample vector.</returns>
/// <exception cref="ArgumentNullException" />
/// <exception cref="ArgumentOutOfRangeException"/>
[Obsolete]
public static T[] EquidistantPeriodic<T>(
Func<double, T> function,
double periodLength,
@ -203,6 +206,7 @@ namespace MathNet.Numerics.Signals
/// <returns>The generated sample vector.</returns>
/// <exception cref="ArgumentNullException" />
/// <exception cref="ArgumentOutOfRangeException"/>
[Obsolete]
public static T[] EquidistantPeriodic<T>(
Func<double, T> function,
double periodLength,
@ -246,6 +250,7 @@ namespace MathNet.Numerics.Signals
/// <returns>The generated sample vector.</returns>
/// <exception cref="ArgumentNullException" />
/// <exception cref="ArgumentOutOfRangeException"/>
[Obsolete]
public static T[] EquidistantStartingAt<T>(
Func<double, T> function,
double start,
@ -286,6 +291,7 @@ namespace MathNet.Numerics.Signals
/// <returns>The generated sample vector.</returns>
/// <exception cref="ArgumentNullException" />
/// <exception cref="ArgumentOutOfRangeException"/>
[Obsolete]
public static T[] EquidistantStartingAt<T>(
Func<double, T> function,
double start,
@ -326,6 +332,7 @@ namespace MathNet.Numerics.Signals
/// <typeparam name="T">The value type of the function to sample.</typeparam>
/// <returns>The generated sample enumerator.</returns>
/// <exception cref="ArgumentNullException" />
[Obsolete]
public static IEnumerable<T> EquidistantContinuous<T>(
Func<double, T> function,
double start,
@ -354,6 +361,7 @@ namespace MathNet.Numerics.Signals
/// <typeparam name="T">The value type of the function to sample.</typeparam>
/// <returns>The generated samples integer-domain function.</returns>
/// <exception cref="ArgumentNullException" />
[Obsolete]
public static Func<int, T> EquidistantToFunction<T>(
Func<double, T> function,
double start,

81
src/Numerics/Signals/SignalGenerator.Random.cs

@ -48,34 +48,13 @@ namespace MathNet.Numerics.Signals
/// <returns>The generated sample vector.</returns>
/// <exception cref="ArgumentNullException" />
/// <exception cref="ArgumentOutOfRangeException" />
[Obsolete]
public static T[] Random<T>(
Func<double, T> function,
IContinuousDistribution distribution,
int sampleCount)
{
if (ReferenceEquals(function, null))
{
throw new ArgumentNullException("function");
}
if (ReferenceEquals(distribution, null))
{
throw new ArgumentNullException("distribution");
}
if (sampleCount < 0)
{
throw new ArgumentOutOfRangeException("sampleCount");
}
var samples = new T[sampleCount];
for (int i = 0; i < samples.Length; i++)
{
samples[i] = function(distribution.Sample());
}
return samples;
return Generate.RandomMap(sampleCount, distribution, function);
}
/// <summary>
@ -89,38 +68,15 @@ namespace MathNet.Numerics.Signals
/// <returns>The generated sample vector.</returns>
/// <exception cref="ArgumentNullException" />
/// <exception cref="ArgumentOutOfRangeException" />
[Obsolete]
public static T[] Random<T>(
Func<double, T> function,
IContinuousDistribution distribution,
int sampleCount,
out double[] samplePoints)
{
if (ReferenceEquals(function, null))
{
throw new ArgumentNullException("function");
}
if (ReferenceEquals(distribution, null))
{
throw new ArgumentNullException("distribution");
}
if (sampleCount < 0)
{
throw new ArgumentOutOfRangeException("sampleCount");
}
var samples = new T[sampleCount];
samplePoints = new double[sampleCount];
for (int i = 0; i < samples.Length; i++)
{
double current = distribution.Sample();
samplePoints[i] = current;
samples[i] = function(current);
}
return samples;
samplePoints = Generate.Random(sampleCount, distribution);
return Generate.Map(samplePoints, function);
}
/// <summary>
@ -133,34 +89,13 @@ namespace MathNet.Numerics.Signals
/// <returns>The generated sample vector.</returns>
/// <exception cref="ArgumentNullException" />
/// <exception cref="ArgumentOutOfRangeException" />
[Obsolete]
public static T[] Random<T>(
Func<double, double, T> function,
IContinuousDistribution distribution,
int sampleCount)
{
if (ReferenceEquals(function, null))
{
throw new ArgumentNullException("function");
}
if (ReferenceEquals(distribution, null))
{
throw new ArgumentNullException("distribution");
}
if (sampleCount < 0)
{
throw new ArgumentOutOfRangeException("sampleCount");
}
var samples = new T[sampleCount];
for (int i = 0; i < samples.Length; i++)
{
samples[i] = function(distribution.Sample(), distribution.Sample());
}
return samples;
return Generate.RandomMap2(sampleCount, distribution, function);
}
}
}
}

12
src/UnitTests/IntegralTransformsTests/FourierTest.cs

@ -33,12 +33,9 @@ using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
{
using Random = System.Random;
#if NOSYSNUMERICS
using Complex = Numerics.Complex;
#else
using Complex = System.Numerics.Complex;
#if !NOSYSNUMERICS
using System.Numerics;
#endif
/// <summary>
@ -52,7 +49,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
/// </summary>
IContinuousDistribution GetUniform(int seed)
{
return new ContinuousUniform(-1, 1, new Random(seed));
return new ContinuousUniform(-1, 1, new System.Random(seed));
}
/// <summary>
@ -97,8 +94,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
[Test]
public void Radix2ThrowsWhenNotPowerOfTwo()
{
var samples = SignalGenerator.Random((u, v) => new Complex(u, v), GetUniform(1), 0x7F);
var samples = Generate.RandomComplex(0x7F, GetUniform(1));
var dft = new DiscreteFourierTransform();
Assert.Throws(typeof (ArgumentException), () => dft.Radix2Forward(samples, FourierOptions.Default));

11
src/UnitTests/IntegralTransformsTests/HartleyTest.cs

@ -33,12 +33,9 @@ using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
{
using Random = System.Random;
#if NOSYSNUMERICS
using Complex = Numerics.Complex;
#else
using Complex = System.Numerics.Complex;
#if !NOSYSNUMERICS
using System.Numerics;
#endif
/// <summary>
@ -52,7 +49,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
/// </summary>
IContinuousDistribution GetUniform(int seed)
{
return new ContinuousUniform(-1, 1, new Random(seed));
return new ContinuousUniform(-1, 1, new System.Random(seed));
}
/// <summary>
@ -85,7 +82,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
public void NaiveMatchesDft(HartleyOptions hartleyOptions, FourierOptions fourierOptions)
{
var dht = new DiscreteHartleyTransform();
var samples = SignalGenerator.Random(x => x, GetUniform(1), 0x80);
var samples = Generate.Random(0x80, GetUniform(1));
VerifyMatchesDft(
samples,

20
src/UnitTests/IntegralTransformsTests/InverseTransformTest.cs

@ -24,6 +24,7 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using MathNet.Numerics.Distributions;
using MathNet.Numerics.IntegralTransforms;
using MathNet.Numerics.IntegralTransforms.Algorithms;
@ -32,12 +33,9 @@ using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
{
using Random = System.Random;
#if NOSYSNUMERICS
using Complex = Numerics.Complex;
#else
using Complex = System.Numerics.Complex;
#if !NOSYSNUMERICS
using System.Numerics;
#endif
/// <summary>
@ -51,7 +49,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
/// </summary>
IContinuousDistribution GetUniform(int seed)
{
return new ContinuousUniform(-1, 1, new Random(seed));
return new ContinuousUniform(-1, 1, new System.Random(seed));
}
/// <summary>
@ -64,7 +62,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
{
var dft = new DiscreteFourierTransform();
var samples = SignalGenerator.Random((u, v) => new Complex(u, v), GetUniform(1), 0x80);
var samples = Generate.RandomComplex(0x80, GetUniform(1));
var work = new Complex[samples.Length];
samples.CopyTo(work, 0);
@ -85,7 +83,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
{
var dft = new DiscreteFourierTransform();
var samples = SignalGenerator.Random((u, v) => new Complex(u, v), GetUniform(1), 0x8000);
var samples = Generate.RandomComplex(0x8000, GetUniform(1));
var work = new Complex[samples.Length];
samples.CopyTo(work, 0);
@ -106,7 +104,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
{
var dft = new DiscreteFourierTransform();
var samples = SignalGenerator.Random((u, v) => new Complex(u, v), GetUniform(1), 0x7FFF);
var samples = Generate.RandomComplex(0x7FFF, GetUniform(1));
var work = new Complex[samples.Length];
samples.CopyTo(work, 0);
@ -127,7 +125,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
{
var dht = new DiscreteHartleyTransform();
var samples = SignalGenerator.Random(x => x, GetUniform(1), 0x80);
var samples = Generate.Random(0x80, GetUniform(1));
var work = new double[samples.Length];
samples.CopyTo(work, 0);
@ -144,7 +142,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
[Test]
public void FourierDefaultTransformIsReversible()
{
var samples = SignalGenerator.Random((u, v) => new Complex(u, v), GetUniform(1), 0x7FFF);
var samples = Generate.RandomComplex(0x7FFF, GetUniform(1));
var work = new Complex[samples.Length];
samples.CopyTo(work, 0);

15
src/UnitTests/IntegralTransformsTests/MatchingNaiveTransformTest.cs

@ -33,12 +33,9 @@ using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
{
using Random = System.Random;
#if NOSYSNUMERICS
using Complex = Numerics.Complex;
#else
using Complex = System.Numerics.Complex;
#if !NOSYSNUMERICS
using System.Numerics;
#endif
/// <summary>
@ -52,7 +49,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
/// </summary>
IContinuousDistribution GetUniform(int seed)
{
return new ContinuousUniform(-1, 1, new Random(seed));
return new ContinuousUniform(-1, 1, new System.Random(seed));
}
/// <summary>
@ -108,7 +105,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
public void FourierRadix2MatchesNaiveOnRandom(FourierOptions options)
{
var dft = new DiscreteFourierTransform();
var samples = SignalGenerator.Random((u, v) => new Complex(u, v), GetUniform(1), 0x80);
var samples = Generate.RandomComplex(0x80, GetUniform(1));
VerifyMatchesNaiveComplex(
samples,
@ -158,7 +155,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
public void FourierBluesteinMatchesNaiveOnRandomPowerOfTwo(FourierOptions options)
{
var dft = new DiscreteFourierTransform();
var samples = SignalGenerator.Random((u, v) => new Complex(u, v), GetUniform(1), 0x80);
var samples = Generate.RandomComplex(0x80, GetUniform(1));
VerifyMatchesNaiveComplex(
samples,
@ -183,7 +180,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
public void FourierBluesteinMatchesNaiveOnRandomNonPowerOfTwo(FourierOptions options)
{
var dft = new DiscreteFourierTransform();
var samples = SignalGenerator.Random((u, v) => new Complex(u, v), GetUniform(1), 0x7F);
var samples = Generate.RandomComplex(0x7F, GetUniform(1));
VerifyMatchesNaiveComplex(
samples,

14
src/UnitTests/IntegralTransformsTests/ParsevalTheoremTest.cs

@ -28,18 +28,14 @@ using System.Linq;
using MathNet.Numerics.Distributions;
using MathNet.Numerics.IntegralTransforms;
using MathNet.Numerics.IntegralTransforms.Algorithms;
using MathNet.Numerics.Signals;
using MathNet.Numerics.Statistics;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
{
using Random = System.Random;
#if NOSYSNUMERICS
using Complex = Numerics.Complex;
#else
using Complex = System.Numerics.Complex;
#if !NOSYSNUMERICS
using System.Numerics;
#endif
/// <summary>
@ -53,7 +49,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
/// </summary>
IContinuousDistribution GetUniform(int seed)
{
return new ContinuousUniform(-1, 1, new Random(seed));
return new ContinuousUniform(-1, 1, new System.Random(seed));
}
/// <summary>
@ -64,7 +60,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
[TestCase(0x7FF)]
public void FourierDefaultTransformSatisfiesParsevalsTheorem(int count)
{
var samples = SignalGenerator.Random((u, v) => new Complex(u, v), GetUniform(1), count);
var samples = Generate.RandomComplex(count, GetUniform(1));
var timeSpaceEnergy = (from s in samples select s.MagnitudeSquared()).Mean();
@ -87,7 +83,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
[TestCase(0x1F)]
public void HartleyDefaultNaiveSatisfiesParsevalsTheorem(int count)
{
var samples = SignalGenerator.Random(x => x, GetUniform(1), count);
var samples = Generate.Random(count, GetUniform(1));
var timeSpaceEnergy = (from s in samples select s*s).Mean();

Loading…
Cancel
Save