From 5d9699eb0ac7b2f3d00ce82243b96846ec18df79 Mon Sep 17 00:00:00 2001 From: Christoph Ruegg Date: Sun, 15 Dec 2013 23:35:40 +0100 Subject: [PATCH] Generate: Map, RandomMap; prepare to phase out SignalGenerator --- src/Examples/Signals/Random.cs | 9 +- src/Numerics/Generate.cs | 131 +++++++++++++++--- .../Signals/SignalGenerator.Chebyshev.cs | 14 +- .../Signals/SignalGenerator.Equidistant.cs | 8 ++ .../Signals/SignalGenerator.Random.cs | 81 ++--------- .../IntegralTransformsTests/FourierTest.cs | 12 +- .../IntegralTransformsTests/HartleyTest.cs | 11 +- .../InverseTransformTest.cs | 20 ++- .../MatchingNaiveTransformTest.cs | 15 +- .../ParsevalTheoremTest.cs | 14 +- 10 files changed, 161 insertions(+), 154 deletions(-) diff --git a/src/Examples/Signals/Random.cs b/src/Examples/Signals/Random.cs index 257f73da..617cb297 100644 --- a/src/Examples/Signals/Random.cs +++ b/src/Examples/Signals/Random.cs @@ -25,6 +25,7 @@ // 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++) { diff --git a/src/Numerics/Generate.cs b/src/Numerics/Generate.cs index 2ac28e88..828a6cce 100644 --- a/src/Numerics/Generate.cs +++ b/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 { /// @@ -301,6 +306,95 @@ namespace MathNet.Numerics } } + /// + /// Generate samples by sampling a function at the provided points. + /// + public static TR[] Map(T[] points, Func map) + { + var res = new TR[points.Length]; + for (int i = 0; i < points.Length; i++) + { + res[i] = map(points[i]); + } + return res; + } + + /// + /// Generate a sample sequence by sampling a function at the provided point sequence. + /// + public static IEnumerable MapSequence(IEnumerable points, Func map) + { + return points.Select(map); + } + + /// + /// Generate samples by sampling a function at the provided points. + /// + public static TR[] Map2(TA[] pointsA, TB[] pointsB, Func 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; + } + + /// + /// Generate a sample sequence by sampling a function at the provided point sequence. + /// + public static IEnumerable Map2Sequence(IEnumerable pointsA, IEnumerable pointsB, Func map) + { + return pointsA.Zip(pointsB, map); + } + + /// + /// Generate samples by sampling a function at samples from a probability distribution. + /// + public static T[] RandomMap(int length, IContinuousDistribution distribution, Func map) + { + var res = new T[length]; + for (int i = 0; i < res.Length; i++) + { + res[i] = map(distribution.Sample()); + } + return res; + } + + /// + /// Generate a sample sequence by sampling a function at samples from a probability distribution. + /// + public static IEnumerable RandomMapSequence(IContinuousDistribution distribution, Func map) + { + return distribution.Samples().Select(map); + } + + /// + /// Generate samples by sampling a function at sample pairs from a probability distribution. + /// + public static T[] RandomMap2(int length, IContinuousDistribution distribution, Func map) + { + var res = new T[length]; + for (int i = 0; i < res.Length; i++) + { + res[i] = map(distribution.Sample(), distribution.Sample()); + } + return res; + } + + /// + /// Generate a sample sequence by sampling a function at sample pairs from a probability distribution. + /// + public static IEnumerable RandomMap2Sequence(IContinuousDistribution distribution, Func map) + { + return distribution.Samples().Zip(distribution.Samples(), map); + } + /// /// Create random samples. /// @@ -317,6 +411,22 @@ namespace MathNet.Numerics return distribution.Samples(); } + /// + /// Create random samples. + /// + public static Complex[] RandomComplex(int length, IContinuousDistribution distribution) + { + return RandomMap2(length, distribution, (r, i) => new Complex(r, i)); + } + + /// + /// Create an infinite random sample sequence. + /// + public static IEnumerable RandomComplex(IContinuousDistribution distribution) + { + return RandomMap2Sequence(distribution, (r, i) => new Complex(r, i)); + } + /// /// Create samples with independent amplitudes of normal distribution and a flat spectral density. /// @@ -357,26 +467,5 @@ namespace MathNet.Numerics { return Stable.Samples(MersenneTwister.Default, alpha, beta, scale, location); } - - /// - /// Generate sample by sampling a function at the provided points. - /// - public static TV[] Map(TU[] points, Func map) - { - var res = new TV[points.Length]; - for (int i = 0; i < points.Length; i++) - { - res[i] = map(points[i]); - } - return res; - } - - /// - /// Generate a sample sequence by sampling a function at the provided point sequence. - /// - public static IEnumerable MapSequence(IEnumerable points, Func map) - { - return points.Select(map); - } } } diff --git a/src/Numerics/Signals/SignalGenerator.Chebyshev.cs b/src/Numerics/Signals/SignalGenerator.Chebyshev.cs index 898aa7fb..e87e8a94 100644 --- a/src/Numerics/Signals/SignalGenerator.Chebyshev.cs +++ b/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); } /// @@ -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); } } } \ No newline at end of file diff --git a/src/Numerics/Signals/SignalGenerator.Equidistant.cs b/src/Numerics/Signals/SignalGenerator.Equidistant.cs index c86c4f94..fa9fa111 100644 --- a/src/Numerics/Signals/SignalGenerator.Equidistant.cs +++ b/src/Numerics/Signals/SignalGenerator.Equidistant.cs @@ -49,6 +49,7 @@ namespace MathNet.Numerics.Signals /// The generated sample vector. /// /// + [Obsolete] public static T[] EquidistantInterval( Func function, double intervalBegin, @@ -102,6 +103,7 @@ namespace MathNet.Numerics.Signals /// The generated sample vector. /// /// + [Obsolete] public static T[] EquidistantInterval( Func function, double intervalBegin, @@ -161,6 +163,7 @@ namespace MathNet.Numerics.Signals /// The generated sample vector. /// /// + [Obsolete] public static T[] EquidistantPeriodic( Func function, double periodLength, @@ -203,6 +206,7 @@ namespace MathNet.Numerics.Signals /// The generated sample vector. /// /// + [Obsolete] public static T[] EquidistantPeriodic( Func function, double periodLength, @@ -246,6 +250,7 @@ namespace MathNet.Numerics.Signals /// The generated sample vector. /// /// + [Obsolete] public static T[] EquidistantStartingAt( Func function, double start, @@ -286,6 +291,7 @@ namespace MathNet.Numerics.Signals /// The generated sample vector. /// /// + [Obsolete] public static T[] EquidistantStartingAt( Func function, double start, @@ -326,6 +332,7 @@ namespace MathNet.Numerics.Signals /// The value type of the function to sample. /// The generated sample enumerator. /// + [Obsolete] public static IEnumerable EquidistantContinuous( Func function, double start, @@ -354,6 +361,7 @@ namespace MathNet.Numerics.Signals /// The value type of the function to sample. /// The generated samples integer-domain function. /// + [Obsolete] public static Func EquidistantToFunction( Func function, double start, diff --git a/src/Numerics/Signals/SignalGenerator.Random.cs b/src/Numerics/Signals/SignalGenerator.Random.cs index ff36c6c4..eb40dfb8 100644 --- a/src/Numerics/Signals/SignalGenerator.Random.cs +++ b/src/Numerics/Signals/SignalGenerator.Random.cs @@ -48,34 +48,13 @@ namespace MathNet.Numerics.Signals /// The generated sample vector. /// /// + [Obsolete] public static T[] Random( Func 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); } /// @@ -89,38 +68,15 @@ namespace MathNet.Numerics.Signals /// The generated sample vector. /// /// + [Obsolete] public static T[] Random( Func 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); } /// @@ -133,34 +89,13 @@ namespace MathNet.Numerics.Signals /// The generated sample vector. /// /// + [Obsolete] public static T[] Random( Func 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); } } -} \ No newline at end of file +} diff --git a/src/UnitTests/IntegralTransformsTests/FourierTest.cs b/src/UnitTests/IntegralTransformsTests/FourierTest.cs index 3dc369d1..6921a0fc 100644 --- a/src/UnitTests/IntegralTransformsTests/FourierTest.cs +++ b/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 /// @@ -52,7 +49,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests /// IContinuousDistribution GetUniform(int seed) { - return new ContinuousUniform(-1, 1, new Random(seed)); + return new ContinuousUniform(-1, 1, new System.Random(seed)); } /// @@ -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)); diff --git a/src/UnitTests/IntegralTransformsTests/HartleyTest.cs b/src/UnitTests/IntegralTransformsTests/HartleyTest.cs index 62849c16..fe01a524 100644 --- a/src/UnitTests/IntegralTransformsTests/HartleyTest.cs +++ b/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 /// @@ -52,7 +49,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests /// IContinuousDistribution GetUniform(int seed) { - return new ContinuousUniform(-1, 1, new Random(seed)); + return new ContinuousUniform(-1, 1, new System.Random(seed)); } /// @@ -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, diff --git a/src/UnitTests/IntegralTransformsTests/InverseTransformTest.cs b/src/UnitTests/IntegralTransformsTests/InverseTransformTest.cs index 73183409..8b49c10e 100644 --- a/src/UnitTests/IntegralTransformsTests/InverseTransformTest.cs +++ b/src/UnitTests/IntegralTransformsTests/InverseTransformTest.cs @@ -24,6 +24,7 @@ // OTHER DEALINGS IN THE SOFTWARE. // +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 /// @@ -51,7 +49,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests /// IContinuousDistribution GetUniform(int seed) { - return new ContinuousUniform(-1, 1, new Random(seed)); + return new ContinuousUniform(-1, 1, new System.Random(seed)); } /// @@ -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); diff --git a/src/UnitTests/IntegralTransformsTests/MatchingNaiveTransformTest.cs b/src/UnitTests/IntegralTransformsTests/MatchingNaiveTransformTest.cs index 92a1d749..f85dfd1b 100644 --- a/src/UnitTests/IntegralTransformsTests/MatchingNaiveTransformTest.cs +++ b/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 /// @@ -52,7 +49,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests /// IContinuousDistribution GetUniform(int seed) { - return new ContinuousUniform(-1, 1, new Random(seed)); + return new ContinuousUniform(-1, 1, new System.Random(seed)); } /// @@ -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, diff --git a/src/UnitTests/IntegralTransformsTests/ParsevalTheoremTest.cs b/src/UnitTests/IntegralTransformsTests/ParsevalTheoremTest.cs index 472e3546..7d8d1c0c 100644 --- a/src/UnitTests/IntegralTransformsTests/ParsevalTheoremTest.cs +++ b/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 /// @@ -53,7 +49,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests /// IContinuousDistribution GetUniform(int seed) { - return new ContinuousUniform(-1, 1, new Random(seed)); + return new ContinuousUniform(-1, 1, new System.Random(seed)); } /// @@ -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();