diff --git a/src/Examples/Interpolation/AkimaSpline.cs b/src/Examples/Interpolation/AkimaSpline.cs
index 196bf33a..ac7d3f35 100644
--- a/src/Examples/Interpolation/AkimaSpline.cs
+++ b/src/Examples/Interpolation/AkimaSpline.cs
@@ -25,6 +25,7 @@
//
using System;
+using MathNet.Numerics;
using MathNet.Numerics.Interpolation;
using MathNet.Numerics.Random;
using MathNet.Numerics.Signals;
@@ -67,8 +68,8 @@ namespace Examples.InterpolationExamples
{
// 1. Generate 10 samples of the function x*x-2*x on interval [0, 10]
Console.WriteLine(@"1. Generate 10 samples of the function x*x-2*x on interval [0, 10]");
- double[] points;
- var values = SignalGenerator.EquidistantInterval(TargetFunction, 0, 10, 10, out points);
+ double[] points = Generate.LinearSpaced(10, 0, 10);
+ var values = Generate.Map(points, TargetFunction);
Console.WriteLine();
// 2. Create akima spline interpolation
diff --git a/src/Examples/Interpolation/LinearBetweenPoints.cs b/src/Examples/Interpolation/LinearBetweenPoints.cs
index ef92badc..1d8c9a6a 100644
--- a/src/Examples/Interpolation/LinearBetweenPoints.cs
+++ b/src/Examples/Interpolation/LinearBetweenPoints.cs
@@ -67,8 +67,8 @@ namespace Examples.InterpolationExamples
{
// 1. Generate 20 samples of the function x*x-2*x on interval [0, 10]
Console.WriteLine(@"1. Generate 20 samples of the function x*x-2*x on interval [0, 10]");
- double[] points;
- var values = SignalGenerator.EquidistantInterval(TargetFunction, 0, 10, 20, out points);
+ double[] points = Generate.LinearSpaced(20, 0, 10);
+ var values = Generate.Map(points, TargetFunction);
Console.WriteLine();
// 2. Create a linear spline interpolation based on arbitrary points
diff --git a/src/Examples/Interpolation/RationalWithPoles.cs b/src/Examples/Interpolation/RationalWithPoles.cs
index 01f378ba..d1438b93 100644
--- a/src/Examples/Interpolation/RationalWithPoles.cs
+++ b/src/Examples/Interpolation/RationalWithPoles.cs
@@ -66,8 +66,8 @@ namespace Examples.InterpolationExamples
{
// 1. Generate 20 samples of the function f(x) = x on interval [-5, 5]
Console.WriteLine(@"1. Generate 20 samples of the function f(x) = x on interval [-5, 5]");
- double[] points;
- var values = SignalGenerator.EquidistantInterval(TargetFunction, -5, 5, 20, out points);
+ double[] points = Generate.LinearSpaced(20, -5, 5);
+ var values = Generate.Map(points, TargetFunction);
Console.WriteLine();
// 2. Create a burlish stoer rational interpolation based on arbitrary points
diff --git a/src/Examples/Interpolation/RationalWithoutPoles.cs b/src/Examples/Interpolation/RationalWithoutPoles.cs
index 9a042861..961fb299 100644
--- a/src/Examples/Interpolation/RationalWithoutPoles.cs
+++ b/src/Examples/Interpolation/RationalWithoutPoles.cs
@@ -67,8 +67,8 @@ namespace Examples.InterpolationExamples
{
// 1. Generate 10 samples of the function 1/(1+x*x) on interval [-5, 5]
Console.WriteLine(@"1. Generate 10 samples of the function 1/(1+x*x) on interval [-5, 5]");
- double[] points;
- var values = SignalGenerator.EquidistantInterval(TargetFunction, -5, 5, 10, out points);
+ double[] points = Generate.LinearSpaced(10, -5, 5);
+ var values = Generate.Map(points, TargetFunction);
Console.WriteLine();
// 2. Create a floater hormann rational pole-free interpolation based on arbitrary points
diff --git a/src/Examples/Signals/Equidistant.cs b/src/Examples/Signals/Equidistant.cs
index 39075e61..7c738f37 100644
--- a/src/Examples/Signals/Equidistant.cs
+++ b/src/Examples/Signals/Equidistant.cs
@@ -25,6 +25,7 @@
//
using System;
+using MathNet.Numerics;
using MathNet.Numerics.Signals;
namespace Examples.SignalsExamples
@@ -62,7 +63,7 @@ namespace Examples.SignalsExamples
public void Run()
{
// 1. Get 11 samples of f(x) = (x * x) / 2 equidistant within interval [-5, 5]
- var result = SignalGenerator.EquidistantInterval(Function, -5, 5, 11);
+ var result = Generate.LinearSpacedMap(11, -5, 5, Function);
Console.WriteLine(@"1. Get 11 samples of f(x) = (x * x) / 2 equidistant within interval [-5, 5]");
for (var i = 0; i < result.Length; i++)
{
@@ -73,8 +74,8 @@ namespace Examples.SignalsExamples
Console.WriteLine();
// 2. Get 10 samples of f(x) = (x * x) / 2 equidistant starting at x=1 with step = 0.5 and retrieve sample points
- double[] samplePoints;
- result = SignalGenerator.EquidistantStartingAt(Function, 1, 0.5, 10, out samplePoints);
+ double[] samplePoints = Generate.LinearSpaced(10, 1.0, 5.5);
+ result = Generate.Map(samplePoints, Function);
Console.WriteLine(@"2. Get 10 samples of f(x) = (x * x) / 2 equidistant starting at x=1 with step = 0.5 and retrieve sample points");
Console.Write(@"Points: ");
for (var i = 0; i < samplePoints.Length; i++)
@@ -93,24 +94,13 @@ namespace Examples.SignalsExamples
Console.WriteLine();
// 3. Get 10 samples of f(x) = (x * x) / 2 equidistant within period = 10 and period offset = 5
- result = SignalGenerator.EquidistantPeriodic(Function, 10, 5, 10);
+ result = Generate.PeriodicMap(10, Function, 10, 1.0, 10, 5);
Console.WriteLine(@"3. Get 10 samples of f(x) = (x * x) / 2 equidistant within period = 10 and period offset = 5");
for (var i = 0; i < result.Length; i++)
{
Console.Write(result[i].ToString("N") + @" ");
}
- Console.WriteLine();
- Console.WriteLine();
-
- // 4. Sample f(x) = (x * x) / 2 equidistant to an integer-domain function starting at x = 0 and step = 2
- var equidistant = SignalGenerator.EquidistantToFunction(Function, 0, 2);
- Console.WriteLine(@" 4. Sample f(x) = (x * x) / 2 equidistant to an integer-domain function starting at x = 0 and step = 2");
- for (var i = 0; i < 10; i++)
- {
- Console.Write(equidistant(i).ToString("N") + @" ");
- }
-
Console.WriteLine();
}
diff --git a/src/Examples/SpecialFunctions/ErrorFunction.cs b/src/Examples/SpecialFunctions/ErrorFunction.cs
index d5393733..039e839c 100644
--- a/src/Examples/SpecialFunctions/ErrorFunction.cs
+++ b/src/Examples/SpecialFunctions/ErrorFunction.cs
@@ -26,7 +26,6 @@
using System;
using MathNet.Numerics;
-using MathNet.Numerics.Signals;
namespace Examples.SpecialFunctionsExamples
{
@@ -70,7 +69,7 @@ namespace Examples.SpecialFunctionsExamples
// 2. Sample 10 values of the error function in [-1.0; 1.0]
Console.WriteLine(@"2. Sample 10 values of the error function in [-1.0; 1.0]");
- var data = SignalGenerator.EquidistantInterval(SpecialFunctions.Erf, -1.0, 1.0, 10);
+ var data = Generate.LinearSpacedMap(10, -1.0, 1.0, SpecialFunctions.Erf);
for (var i = 0; i < data.Length; i++)
{
Console.Write(data[i].ToString("N") + @" ");
@@ -86,7 +85,7 @@ namespace Examples.SpecialFunctionsExamples
// 4. Sample 10 values of the complementary error function in [-1.0; 1.0]
Console.WriteLine(@"4. Sample 10 values of the complementary error function in [-1.0; 1.0]");
- data = SignalGenerator.EquidistantInterval(SpecialFunctions.Erfc, -1.0, 1.0, 10);
+ data = Generate.LinearSpacedMap(10, -1.0, 1.0, SpecialFunctions.Erfc);
for (var i = 0; i < data.Length; i++)
{
Console.Write(data[i].ToString("N") + @" ");
@@ -102,7 +101,7 @@ namespace Examples.SpecialFunctionsExamples
// 6. Sample 10 values of the inverse error function in [-1.0; 1.0]
Console.WriteLine(@"6. Sample 10 values of the inverse error function in [-1.0; 1.0]");
- data = SignalGenerator.EquidistantInterval(SpecialFunctions.ErfInv, -1.0, 1.0, 10);
+ data = Generate.LinearSpacedMap(10, -1.0, 1.0, SpecialFunctions.ErfInv);
for (var i = 0; i < data.Length; i++)
{
Console.Write(data[i].ToString("N") + @" ");
@@ -118,7 +117,7 @@ namespace Examples.SpecialFunctionsExamples
// 8. Sample 10 values of the complementary inverse error function in [-1.0; 1.0]
Console.WriteLine(@"8. Sample 10 values of the complementary inverse error function in [-1.0; 1.0]");
- data = SignalGenerator.EquidistantInterval(SpecialFunctions.ErfcInv, -1.0, 1.0, 10);
+ data = Generate.LinearSpacedMap(10, -1.0, 1.0, SpecialFunctions.ErfcInv);
for (var i = 0; i < data.Length; i++)
{
Console.Write(data[i].ToString("N") + @" ");
diff --git a/src/Examples/Statistics.cs b/src/Examples/Statistics.cs
index cd5597d4..b5c3f1aa 100644
--- a/src/Examples/Statistics.cs
+++ b/src/Examples/Statistics.cs
@@ -25,8 +25,8 @@
//
using System;
+using MathNet.Numerics;
using MathNet.Numerics.Distributions;
-using MathNet.Numerics.Signals;
using MathNet.Numerics.Statistics;
namespace Examples
@@ -124,8 +124,8 @@ namespace Examples
Console.WriteLine();
// 6. Correlation coefficient between 1000 samples of f(x) = x * 2 and f(x) = x * x
- data = SignalGenerator.EquidistantInterval(x => x * 2, 0, 100, 1000);
- dataB = SignalGenerator.EquidistantInterval(x => x * x, 0, 100, 1000);
+ data = Generate.LinearSpacedMap(1000, 0, 100, x => x * 2);
+ dataB = Generate.LinearSpacedMap(1000, 0, 100, x => x * x);
Console.WriteLine(@"7. Correlation coefficient between 1000 samples of f(x) = x * 2 and f(x) = x * x is {0}", Correlation.Pearson(data, dataB).ToString("N04"));
Console.WriteLine(@"8. Ranked correlation coefficient between 1000 samples of f(x) = x * 2 and f(x) = x * x is {0}", Correlation.Spearman(data, dataB).ToString("N04"));
Console.WriteLine();
diff --git a/src/Numerics/Generate.cs b/src/Numerics/Generate.cs
index 828a6cce..455453ba 100644
--- a/src/Numerics/Generate.cs
+++ b/src/Numerics/Generate.cs
@@ -43,6 +43,53 @@ namespace MathNet.Numerics
public static class Generate
{
+ ///
+ /// Generate samples by sampling a function at the provided points.
+ ///
+ public static T[] Map(TA[] points, Func map)
+ {
+ var res = new T[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 T[] Map2(TA[] pointsA, TB[] pointsB, Func map)
+ {
+ if (pointsA.Length != pointsB.Length)
+ {
+ throw new ArgumentException(Resources.ArgumentArraysSameLength, "pointsB");
+ }
+
+ var res = new T[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 a linearly spaced sample vector of the given length between the specified values (inclusive).
/// Equivalent to MATLAB linspace but with the length as first instead of last argument.
@@ -63,6 +110,25 @@ namespace MathNet.Numerics
return data;
}
+ ///
+ /// Generate samples by sampling a function at linearly spaced points between the specified values (inclusive).
+ ///
+ public static T[] LinearSpacedMap(int length, double start, double stop, Func map)
+ {
+ if (length <= 0) return new T[0];
+ if (length == 1) return new[] { map(stop) };
+
+ double step = (stop - start)/(length - 1);
+
+ var data = new T[length];
+ for (int i = 0; i < data.Length; i++)
+ {
+ data[i] = map(start + i*step);
+ }
+ data[data.Length - 1] = map(stop);
+ return data;
+ }
+
///
/// Generate a base 10 logarithmically spaced sample vector of the given length between the specified decade exponents (inclusive).
/// Equivalent to MATLAB logspace but with the length as first instead of last argument.
@@ -152,12 +218,149 @@ namespace MathNet.Numerics
return data;
}
+ ///
+ /// Generate samples by sampling a function at linearly spaced points within the inclusive interval (start, stop) and the provide step.
+ /// The start value is aways included as first value, but stop is only included if it stop-start is a multiple of step.
+ ///
+ public static T[] LinearRangeMap(double start, double step, double stop, Func map)
+ {
+ if (start == stop) return new T[] { map(start) };
+ if (start < stop && step < 0 || start > stop && step > 0 || step == 0d)
+ {
+ return new T[0];
+ }
+
+ var data = new T[(int)Math.Floor((stop - start)/step + 1d)];
+ for (int i = 0; i < data.Length; i++)
+ {
+ data[i] = map(start + i*step);
+ }
+ return data;
+ }
+
+ ///
+ /// Create a periodic sample vector.
+ ///
+ /// The number of samples to generate.
+ /// Samples per time unit (Hz). Must be larger than twice the frequency to satisfy the Nyquist criterion.
+ /// Frequency in periods per time unit (Hz).
+ /// The lenght of the period when sampled at one sample per time unit. This is the interval of the periodic domain, a typical value is 1.0, or 2*Pi for angular functions.
+ /// Optional phase offset.
+ /// Optional delay, relative to the phase.
+ public static double[] Periodic(int length, double samplingRate, double frequency, double amplitude = 1.0, double phase = 0.0, int delay = 0)
+ {
+ double step = frequency/samplingRate*amplitude;
+ phase = Euclid.Modulus(phase - delay*step, amplitude);
+
+ var data = new double[length];
+ for (int i = 0, k = 0; i < data.Length; i++, k++)
+ {
+ var x = phase + k*step;
+ if (x >= amplitude)
+ {
+ x %= amplitude;
+ phase = x;
+ k = 0;
+ }
+
+ data[i] = x;
+ }
+ return data;
+ }
+
+ ///
+ /// Create a periodic sample vector.
+ ///
+ /// The number of samples to generate.
+ ///
+ /// Samples per time unit (Hz). Must be larger than twice the frequency to satisfy the Nyquist criterion.
+ /// Frequency in periods per time unit (Hz).
+ /// The lenght of the period when sampled at one sample per time unit. This is the interval of the periodic domain, a typical value is 1.0, or 2*Pi for angular functions.
+ /// Optional phase offset.
+ /// Optional delay, relative to the phase.
+ public static T[] PeriodicMap(int length, Func map, double samplingRate, double frequency, double amplitude = 1.0, double phase = 0.0, int delay = 0)
+ {
+ double step = frequency/samplingRate*amplitude;
+ phase = Euclid.Modulus(phase - delay*step, amplitude);
+
+ var data = new T[length];
+ for (int i = 0, k = 0; i < data.Length; i++, k++)
+ {
+ var x = phase + k*step;
+ if (x >= amplitude)
+ {
+ x %= amplitude;
+ phase = x;
+ k = 0;
+ }
+
+ data[i] = map(x);
+ }
+ return data;
+ }
+
+ ///
+ /// Create an infinite periodic sample sequence.
+ ///
+ /// Samples per time unit (Hz). Must be larger than twice the frequency to satisfy the Nyquist criterion.
+ /// Frequency in periods per time unit (Hz).
+ /// The lenght of the period when sampled at one sample per time unit. This is the interval of the periodic domain, a typical value is 1.0, or 2*Pi for angular functions.
+ /// Optional phase offset.
+ /// Optional delay, relative to the phase.
+ public static IEnumerable PeriodicSequence(double samplingRate, double frequency, double amplitude = 1.0, double phase = 0.0, int delay = 0)
+ {
+ double step = frequency/samplingRate*amplitude;
+ phase = Euclid.Modulus(phase - delay*step, amplitude);
+
+ int k = 0;
+ while (true)
+ {
+ var x = phase + (k++)*step;
+ if (x >= amplitude)
+ {
+ x %= amplitude;
+ phase = x;
+ k = 1;
+ }
+
+ yield return x;
+ }
+ }
+
+ ///
+ /// Create an infinite periodic sample sequence.
+ ///
+ /// Samples per time unit (Hz). Must be larger than twice the frequency to satisfy the Nyquist criterion.
+ /// Frequency in periods per time unit (Hz).
+ /// The lenght of the period when sampled at one sample per time unit. This is the interval of the periodic domain, a typical value is 1.0, or 2*Pi for angular functions.
+ /// Optional phase offset.
+ /// Optional delay, relative to the phase.
+ public static IEnumerable PeriodicMapSequence(Func map, double samplingRate, double frequency, double amplitude = 1.0, double phase = 0.0, int delay = 0)
+ {
+ double step = frequency/samplingRate*amplitude;
+ phase = Euclid.Modulus(phase - delay*step, amplitude);
+
+ int k = 0;
+ while (true)
+ {
+ var x = phase + (k++)*step;
+ if (x >= amplitude)
+ {
+ x %= amplitude;
+ phase = x;
+ k = 0;
+ }
+
+ yield return map(x);
+ }
+ }
+
///
/// Create a Sine sample vector.
///
/// The number of samples to generate.
- /// Samples per unit.
- /// Frequency in samples per unit.
+ /// Samples per time unit (Hz). Must be larger than twice the frequency to satisfy the Nyquist criterion.
+ /// Frequency in periods per time unit (Hz).
/// The maximal reached peak.
/// The mean, or dc part, of the signal.
/// Optional phase offset.
@@ -168,7 +371,7 @@ namespace MathNet.Numerics
phase = (phase - delay*step)%Constants.Pi2;
var data = new double[length];
- for (int i = 0; i < length; i++)
+ for (int i = 0; i < data.Length; i++)
{
data[i] = mean + amplitude*Math.Sin(phase + i*step);
}
@@ -306,64 +509,17 @@ 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++)
+ var data = new T[length];
+ for (int i = 0; i < data.Length; i++)
{
- res[i] = map(distribution.Sample());
+ data[i] = map(distribution.Sample());
}
- return res;
+ return data;
}
///
@@ -379,12 +535,12 @@ namespace MathNet.Numerics
///
public static T[] RandomMap2(int length, IContinuousDistribution distribution, Func map)
{
- var res = new T[length];
- for (int i = 0; i < res.Length; i++)
+ var data = new T[length];
+ for (int i = 0; i < data.Length; i++)
{
- res[i] = map(distribution.Sample(), distribution.Sample());
+ data[i] = map(distribution.Sample(), distribution.Sample());
}
- return res;
+ return data;
}
///
diff --git a/src/Numerics/Signals/SignalGenerator.Equidistant.cs b/src/Numerics/Signals/SignalGenerator.Equidistant.cs
index fa9fa111..0d260022 100644
--- a/src/Numerics/Signals/SignalGenerator.Equidistant.cs
+++ b/src/Numerics/Signals/SignalGenerator.Equidistant.cs
@@ -56,39 +56,7 @@ namespace MathNet.Numerics.Signals
double intervalEnd,
int sampleCount)
{
- if (ReferenceEquals(function, null))
- {
- throw new ArgumentNullException("function");
- }
-
- if (sampleCount < 0)
- {
- throw new ArgumentOutOfRangeException("sampleCount");
- }
-
- if (sampleCount == 0)
- {
- return new T[0];
- }
-
- if (sampleCount == 1)
- {
- return new[] { function(0.5 * (intervalBegin + intervalEnd)) };
- }
-
- var samples = new T[sampleCount];
- var step = (intervalEnd - intervalBegin) / (sampleCount - 1);
- var current = intervalBegin;
-
- for (int i = 0; i < samples.Length - 1; i++)
- {
- samples[i] = function(current);
- current += step;
- }
-
- samples[samples.Length - 1] = function(intervalEnd);
-
- return samples;
+ return Generate.LinearSpacedMap(sampleCount, intervalBegin, intervalEnd, function);
}
///
@@ -111,44 +79,8 @@ namespace MathNet.Numerics.Signals
int sampleCount,
out double[] samplePoints)
{
- if (ReferenceEquals(function, null))
- {
- throw new ArgumentNullException("function");
- }
-
- if (sampleCount < 0)
- {
- throw new ArgumentOutOfRangeException("sampleCount");
- }
-
- if (sampleCount == 0)
- {
- samplePoints = new double[0];
- return new T[0];
- }
-
- if (sampleCount == 1)
- {
- samplePoints = new[] { 0.5 * (intervalBegin + intervalEnd) };
- return new[] { function(samplePoints[0]) };
- }
-
- var samples = new T[sampleCount];
- samplePoints = new double[sampleCount];
- var step = (intervalEnd - intervalBegin) / (sampleCount - 1);
- var current = intervalBegin;
-
- for (int i = 0; i < samples.Length - 1; i++)
- {
- samplePoints[i] = current;
- samples[i] = function(current);
- current += step;
- }
-
- samplePoints[samplePoints.Length - 1] = intervalEnd;
- samples[samples.Length - 1] = function(intervalEnd);
-
- return samples;
+ samplePoints = Generate.LinearSpaced(sampleCount, intervalBegin, intervalEnd);
+ return Generate.Map(samplePoints, function);
}
///
@@ -170,27 +102,7 @@ namespace MathNet.Numerics.Signals
double periodOffset,
int sampleCount)
{
- if (ReferenceEquals(function, null))
- {
- throw new ArgumentNullException("function");
- }
-
- if (sampleCount < 1)
- {
- throw new ArgumentOutOfRangeException("sampleCount");
- }
-
- var samples = new T[sampleCount];
- var step = periodLength / sampleCount;
- var current = periodOffset;
-
- for (int i = 0; i < samples.Length; i++)
- {
- samples[i] = function(current);
- current += step;
- }
-
- return samples;
+ return Generate.PeriodicMap(sampleCount, function, sampleCount, 1.0, periodLength, periodOffset);
}
///
@@ -214,29 +126,8 @@ namespace MathNet.Numerics.Signals
int sampleCount,
out double[] samplePoints)
{
- if (ReferenceEquals(function, null))
- {
- throw new ArgumentNullException("function");
- }
-
- if (sampleCount < 1)
- {
- throw new ArgumentOutOfRangeException("sampleCount");
- }
-
- var samples = new T[sampleCount];
- samplePoints = new double[sampleCount];
- var step = periodLength / sampleCount;
- var current = periodOffset;
-
- for (int i = 0; i < samples.Length; i++)
- {
- samplePoints[i] = current;
- samples[i] = function(current);
- current += step;
- }
-
- return samples;
+ samplePoints = Generate.Periodic(sampleCount, sampleCount, 1.0, periodLength, periodOffset);
+ return Generate.Map(samplePoints, function);
}
///
@@ -257,26 +148,7 @@ namespace MathNet.Numerics.Signals
double step,
int sampleCount)
{
- if (ReferenceEquals(function, null))
- {
- throw new ArgumentNullException("function");
- }
-
- if (sampleCount < 0)
- {
- throw new ArgumentOutOfRangeException("sampleCount");
- }
-
- var samples = new T[sampleCount];
- var current = start;
-
- for (int i = 0; i < samples.Length; i++)
- {
- samples[i] = function(current);
- current += step;
- }
-
- return samples;
+ return Generate.LinearSpacedMap(sampleCount, start, start + (sampleCount - 1)*step, function);
}
///
@@ -299,28 +171,8 @@ namespace MathNet.Numerics.Signals
int sampleCount,
out double[] samplePoints)
{
- if (ReferenceEquals(function, null))
- {
- throw new ArgumentNullException("function");
- }
-
- if (sampleCount < 0)
- {
- throw new ArgumentOutOfRangeException("sampleCount");
- }
-
- var samples = new T[sampleCount];
- samplePoints = new double[sampleCount];
- var current = start;
-
- for (int i = 0; i < samples.Length; i++)
- {
- samplePoints[i] = current;
- samples[i] = function(current);
- current += step;
- }
-
- return samples;
+ samplePoints = Generate.LinearSpaced(sampleCount, start, start + (sampleCount - 1)*step);
+ return Generate.Map(samplePoints, function);
}
///
diff --git a/src/UnitTests/GenerateTests.cs b/src/UnitTests/GenerateTests.cs
index 80e97483..a568cb0b 100644
--- a/src/UnitTests/GenerateTests.cs
+++ b/src/UnitTests/GenerateTests.cs
@@ -130,6 +130,32 @@ namespace MathNet.Numerics.UnitTests
Assert.That(Generate.LinearRange(1d, -1.5d, -4d), Is.EqualTo(new[] { 1d, -0.5d, -2d, -3.5 }).AsCollection);
}
+ [Test]
+ public void Periodic()
+ {
+ Assert.That(Generate.Periodic(8, 2.0, 0.5), Is.EqualTo(new[] { 0.0, 0.25, 0.5, 0.75, 0.0, 0.25, 0.5, 0.75 }).Within(1e-12).AsCollection);
+ Assert.That(Generate.Periodic(8, 2.0, 0.5, 1.0, delay: 1), Is.EqualTo(new[] { 0.75, 0.0, 0.25, 0.5, 0.75, 0.0, 0.25, 0.5 }).Within(1e-12).AsCollection);
+ Assert.That(Generate.Periodic(8, 2.0, 0.5, 1.0, delay: -1), Is.EqualTo(new[] { 0.25, 0.5, 0.75, 0.0, 0.25, 0.5, 0.75, 0.0 }).Within(1e-12).AsCollection);
+ Assert.That(Generate.Periodic(8, 2.0, 0.5, 1.0, phase: 0.7), Is.EqualTo(new[] { 0.7, 0.95, 0.2, 0.45, 0.7, 0.95, 0.2, 0.45 }).Within(1e-12).AsCollection);
+ Assert.That(Generate.Periodic(8, 2.0, 0.5, 1.0, phase: -0.3), Is.EqualTo(new[] { 0.7, 0.95, 0.2, 0.45, 0.7, 0.95, 0.2, 0.45 }).Within(1e-12).AsCollection);
+ Assert.That(Generate.Periodic(8, 2.0, 0.5, 2.0), Is.EqualTo(new[] { 0.0, 0.5, 1.0, 1.5, 0.0, 0.5, 1.0, 1.5 }).Within(1e-12).AsCollection);
+ Assert.That(Generate.Periodic(8, 2.0, 0.5, 2.0, phase: 1.9), Is.EqualTo(new[] { 1.9, 0.4, 0.9, 1.4, 1.9, 0.4, 0.9, 1.4 }).Within(1e-12).AsCollection);
+ Assert.That(Generate.Periodic(8, 8.0, 1.0), Is.EqualTo(new[] { 0.0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875 }).Within(1e-12).AsCollection);
+
+ // Angular over a full circle:
+ const double isq2 = Constants.Sqrt1Over2;
+ Assert.That(Generate.Periodic(8, 2.0, 0.5, Constants.Pi2).Select(Math.Sin), Is.EqualTo(new[] { 0.0, 1.0, 0.0, -1.0, 0.0, 1.0, 0.0, -1.0 }).Within(1e-12).AsCollection);
+ Assert.That(Generate.Periodic(8, 2.0, 0.25, Constants.Pi2).Select(Math.Sin), Is.EqualTo(new[] { 0.0, isq2, 1.0, isq2, 0.0, -isq2, -1.0, -isq2 }).Within(1e-12).AsCollection);
+ }
+
+ [Test]
+ public void PreiodicConsistentWithSequence()
+ {
+ Assert.That(
+ Generate.PeriodicSequence(16.0, 2.0, Constants.Pi2, Constants.PiOver4, 2).Take(1000).ToArray(),
+ Is.EqualTo(Generate.Periodic(1000, 16.0, 2.0, Constants.Pi2, Constants.PiOver4, 2)).Within(1e-12).AsCollection);
+ }
+
[Test]
public void SinusoidalConsistentWithSequence()
{
diff --git a/src/UnitTests/IntegralTransformsTests/FourierTest.cs b/src/UnitTests/IntegralTransformsTests/FourierTest.cs
index 6921a0fc..54860777 100644
--- a/src/UnitTests/IntegralTransformsTests/FourierTest.cs
+++ b/src/UnitTests/IntegralTransformsTests/FourierTest.cs
@@ -28,7 +28,6 @@ using System;
using MathNet.Numerics.Distributions;
using MathNet.Numerics.IntegralTransforms;
using MathNet.Numerics.IntegralTransforms.Algorithms;
-using MathNet.Numerics.Signals;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
@@ -58,7 +57,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
[Test]
public void NaiveTransformsRealSineCorrectly()
{
- var samples = SignalGenerator.EquidistantPeriodic(w => new Complex(Math.Sin(w), 0), Constants.Pi2, 0, 16);
+ var samples = Generate.PeriodicMap(16, w => new Complex(Math.Sin(w), 0), 16, 1.0, Constants.Pi2);
// real-odd transforms to imaginary odd
var dft = new DiscreteFourierTransform();
diff --git a/src/UnitTests/IntegralTransformsTests/MatchingNaiveTransformTest.cs b/src/UnitTests/IntegralTransformsTests/MatchingNaiveTransformTest.cs
index f85dfd1b..a61e9f4f 100644
--- a/src/UnitTests/IntegralTransformsTests/MatchingNaiveTransformTest.cs
+++ b/src/UnitTests/IntegralTransformsTests/MatchingNaiveTransformTest.cs
@@ -28,7 +28,6 @@ using System;
using MathNet.Numerics.Distributions;
using MathNet.Numerics.IntegralTransforms;
using MathNet.Numerics.IntegralTransforms.Algorithms;
-using MathNet.Numerics.Signals;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
@@ -80,7 +79,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
public void FourierRadix2MatchesNaiveOnRealSine(FourierOptions options)
{
var dft = new DiscreteFourierTransform();
- var samples = SignalGenerator.EquidistantPeriodic(w => new Complex(Math.Sin(w), 0), Constants.Pi2, 0, 16);
+ var samples = Generate.PeriodicMap(16, w => new Complex(Math.Sin(w), 0), 16, 1.0, Constants.Pi2);
VerifyMatchesNaiveComplex(
samples,
@@ -130,7 +129,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
public void FourierBluesteinMatchesNaiveOnRealSineNonPowerOfTwo(FourierOptions options)
{
var dft = new DiscreteFourierTransform();
- var samples = SignalGenerator.EquidistantPeriodic(w => new Complex(Math.Sin(w), 0), Constants.Pi2, 0, 14);
+ var samples = Generate.PeriodicMap(14, w => new Complex(Math.Sin(w), 0), 14, 1.0, Constants.Pi2);
VerifyMatchesNaiveComplex(
samples,