diff --git a/src/Numerics/Generate.cs b/src/Numerics/Generate.cs
index 4a70e8ab..005eccef 100644
--- a/src/Numerics/Generate.cs
+++ b/src/Numerics/Generate.cs
@@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
-// Copyright (c) 2009-2013 Math.NET
+// Copyright (c) 2009-2014 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@@ -259,12 +259,12 @@ namespace MathNet.Numerics
}
///
- /// Create a periodic sample vector.
+ /// Create a periodic wave.
///
/// 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.
+ /// The length 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)
@@ -289,13 +289,13 @@ namespace MathNet.Numerics
}
///
- /// Create a periodic sample vector.
+ /// Create a periodic wave.
///
/// The number of samples to generate.
/// The function to apply to each of the values and evaluate the resulting sample.
/// 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.
+ /// The length 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)
@@ -320,11 +320,11 @@ namespace MathNet.Numerics
}
///
- /// Create an infinite periodic sample sequence.
+ /// Create an infinite periodic wave 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.
+ /// The length 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)
@@ -348,12 +348,12 @@ namespace MathNet.Numerics
}
///
- /// Create an infinite periodic sample sequence.
+ /// Create an infinite periodic wave sequence.
///
/// The function to apply to each of the values and evaluate the resulting sample.
/// 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.
+ /// The length 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)
@@ -377,13 +377,13 @@ namespace MathNet.Numerics
}
///
- /// Create a Sine sample vector.
+ /// Create a Sine wave.
///
/// 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 maximal reached peak.
- /// The mean, or dc part, of the signal.
+ /// The mean, or DC part, of the signal.
/// Optional phase offset.
/// Optional delay, relative to the phase.
public static double[] Sinusoidal(int length, double samplingRate, double frequency, double amplitude, double mean = 0.0, double phase = 0.0, int delay = 0)
@@ -400,12 +400,12 @@ namespace MathNet.Numerics
}
///
- /// Create an infinite Sine sample sequence.
+ /// Create an infinite Sine wave sequence.
///
/// Samples per unit.
/// Frequency in samples per unit.
/// The maximal reached peak.
- /// The mean, or dc part, of the signal.
+ /// The mean, or DC part, of the signal.
/// Optional phase offset.
/// Optional delay, relative to the phase.
public static IEnumerable SinusoidalSequence(double samplingRate, double frequency, double amplitude, double mean = 0.0, double phase = 0.0, int delay = 0)
@@ -423,6 +423,97 @@ namespace MathNet.Numerics
}
}
+ ///
+ /// Create a periodic square wave, starting with the high phase.
+ ///
+ /// The number of samples to generate.
+ /// Number of samples of the high phase.
+ /// Number of samples of the low phase.
+ /// Sample value to be emitted during the low phase.
+ /// Sample value to be emitted during the high phase.
+ /// Optional delay.
+ public static double[] Square(int length, int highDuration, int lowDuration, double lowValue, double highValue, int delay = 0)
+ {
+ var duration = highDuration + lowDuration;
+ return PeriodicMap(length, x => x < highDuration ? highValue : lowValue, 1.0, 1.0/duration, duration, 0.0, delay);
+ }
+
+ ///
+ /// Create an infinite periodic square wave sequence, starting with the high phase.
+ ///
+ /// Number of samples of the high phase.
+ /// Number of samples of the low phase.
+ /// Sample value to be emitted during the low phase.
+ /// Sample value to be emitted during the high phase.
+ /// Optional delay.
+ public static IEnumerable SquareSequence(int highDuration, int lowDuration, double lowValue, double highValue, int delay = 0)
+ {
+ var duration = highDuration + lowDuration;
+ return PeriodicMapSequence(x => x < highDuration ? highValue : lowValue, 1.0, 1.0/duration, duration, 0.0, delay);
+ }
+
+ ///
+ /// Create a periodic triangle wave, starting with the raise phase from the lowest sample.
+ ///
+ /// The number of samples to generate.
+ /// Number of samples of the raise phase.
+ /// Number of samples of the fall phase.
+ /// Lowest sample value.
+ /// Highest sample value.
+ /// Optional delay.
+ public static double[] Triangle(int length, int raiseDuration, int fallDuration, double lowValue, double highValue, int delay = 0)
+ {
+ var duration = raiseDuration + fallDuration;
+ var height = highValue - lowValue;
+ var raise = height / raiseDuration;
+ var fall = height / fallDuration;
+ return PeriodicMap(length, x => x < raiseDuration ? lowValue + x*raise : highValue - (x-raiseDuration)*fall, 1.0, 1.0/duration, duration, 0.0, delay);
+ }
+
+ ///
+ /// Create an infinite periodic triangle wave sequence, starting with the raise phase from the lowest sample.
+ ///
+ /// Number of samples of the raise phase.
+ /// Number of samples of the fall phase.
+ /// Lowest sample value.
+ /// Highest sample value.
+ /// Optional delay.
+ public static IEnumerable TriangleSequence(int raiseDuration, int fallDuration, double lowValue, double highValue, int delay = 0)
+ {
+ var duration = raiseDuration + fallDuration;
+ var height = highValue - lowValue;
+ var raise = height / raiseDuration;
+ var fall = height / fallDuration;
+ return PeriodicMapSequence(x => x < raiseDuration ? lowValue + x*raise : highValue - (x-raiseDuration)*fall, 1.0, 1.0/duration, duration, 0.0, delay);
+ }
+
+ ///
+ /// Create a periodic sawtooth wave, starting with the lowest sample.
+ ///
+ /// The number of samples to generate.
+ /// Number of samples a full sawtooth period.
+ /// Lowest sample value.
+ /// Highest sample value.
+ /// Optional delay.
+ public static double[] Sawtooth(int length, int period, double lowValue, double highValue, int delay = 0)
+ {
+ var height = highValue - lowValue;
+ return PeriodicMap(length, x => x + lowValue, 1.0, 1.0/period, height*period/(period-1), 0.0, delay);
+ }
+
+ ///
+ /// Create an infinite periodic sawtooth wave sequence, starting with the lowest sample.
+ ///
+ /// Number of samples a full sawtooth period.
+ /// Lowest sample value.
+ /// Highest sample value.
+ /// Optional delay.
+ public static IEnumerable SawtoothSequence(int period, double lowValue, double highValue, int delay = 0)
+ {
+ var height = highValue - lowValue;
+ return PeriodicMapSequence(x => x + lowValue, 1.0, 1.0/period, height*period/(period-1), 0.0, delay);
+ }
+
///
/// Create an array with each field set to the same value.
///
diff --git a/src/UnitTests/GenerateTests.cs b/src/UnitTests/GenerateTests.cs
index 8eb13ae0..522a43ef 100644
--- a/src/UnitTests/GenerateTests.cs
+++ b/src/UnitTests/GenerateTests.cs
@@ -3,9 +3,9 @@
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
-//
-// Copyright (c) 2009-2013 Math.NET
-//
+//
+// Copyright (c) 2009-2014 Math.NET
+//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
@@ -14,10 +14,10 @@
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
-//
+//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
-//
+//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -148,6 +148,28 @@ namespace MathNet.Numerics.UnitTests
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 StandardWaves()
+ {
+ Assert.That(Generate.Square(12, 3, 7, -1.0, 1.0, delay: 1), Is.EqualTo(new[] { -1.0, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1 }).Within(1e-12).AsCollection);
+ Assert.That(Generate.Triangle(12, 4, 7, -1.0, 1.0, delay: 1), Is.EqualTo(new[] { -0.714, -1, -0.5, 0, 0.5, 1, 0.714, 0.429, 0.143, -0.143, -0.429, -0.714 }).Within(1e-3).AsCollection);
+ Assert.That(Generate.Sawtooth(12, 5, -1.0, 1.0, delay: 1), Is.EqualTo(new[] { 1.0, -1, -0.5, 0, 0.5, 1, -1, -0.5, 0, 0.5, 1, -1 }).Within(1e-12).AsCollection);
+ }
+
+ [Test]
+ public void StandardWavesConsistentWithSequence()
+ {
+ Assert.That(
+ Generate.SquareSequence(3, 7, -1.0, 1.0, delay: -2).Take(1000).ToArray(),
+ Is.EqualTo(Generate.Square(1000, 3, 7, -1.0, 1.0, delay: -2)).Within(1e-12).AsCollection);
+ Assert.That(
+ Generate.TriangleSequence(4, 7, -1.0, 1.0, delay: -2).Take(1000).ToArray(),
+ Is.EqualTo(Generate.Triangle(1000, 4, 7, -1.0, 1.0, delay: -2)).Within(1e-12).AsCollection);
+ Assert.That(
+ Generate.SawtoothSequence(5, -1.0, 1.0, delay: -2).Take(1000).ToArray(),
+ Is.EqualTo(Generate.Sawtooth(1000, 5, -1.0, 1.0, delay: -2)).Within(1e-12).AsCollection);
+ }
+
[Test]
public void PeriodicConsistentWithSinusoidal()
{