From 671c9639bcc27e6f176d996e410e9e1f57051f71 Mon Sep 17 00:00:00 2001 From: Christoph Ruegg Date: Thu, 27 Feb 2014 21:44:21 +0100 Subject: [PATCH] FFT: code reorg, drop Transform class (now redundant) --- .../IntegralTransforms/Fourier.Bluestein.cs | 24 +- .../IntegralTransforms/Fourier.Naive.cs | 28 +-- .../IntegralTransforms/Fourier.Options.cs | 100 --------- .../IntegralTransforms/Fourier.RadixN.cs | 26 +-- src/Numerics/IntegralTransforms/Fourier.cs | 211 ++++++++++++++++++ .../IntegralTransforms/Hartley.Naive.cs | 30 +-- .../{Hartley.Options.cs => Hartley.cs} | 28 ++- src/Numerics/IntegralTransforms/Transform.cs | 81 ------- src/Numerics/Numerics.csproj | 5 +- .../IntegralTransformsTests/HartleyTest.cs | 4 +- .../InverseTransformTest.cs | 8 +- .../MatchingNaiveTransformTest.cs | 111 ++++----- .../ParsevalTheoremTest.cs | 8 +- 13 files changed, 299 insertions(+), 365 deletions(-) delete mode 100644 src/Numerics/IntegralTransforms/Fourier.Options.cs create mode 100644 src/Numerics/IntegralTransforms/Fourier.cs rename src/Numerics/IntegralTransforms/{Hartley.Options.cs => Hartley.cs} (72%) delete mode 100644 src/Numerics/IntegralTransforms/Transform.cs diff --git a/src/Numerics/IntegralTransforms/Fourier.Bluestein.cs b/src/Numerics/IntegralTransforms/Fourier.Bluestein.cs index 26fdd824..be5e7e60 100644 --- a/src/Numerics/IntegralTransforms/Fourier.Bluestein.cs +++ b/src/Numerics/IntegralTransforms/Fourier.Bluestein.cs @@ -1,4 +1,4 @@ -// +// // Math.NET Numerics, part of the Math.NET Project // http://numerics.mathdotnet.com // http://github.com/mathnet/mathnet-numerics @@ -155,27 +155,5 @@ namespace MathNet.Numerics.IntegralTransforms SwapRealImaginary(samples); } } - - /// - /// Bluestein forward FFT for arbitrary sized sample vectors. - /// - /// Sample vector, where the FFT is evaluated in place. - /// Fourier Transform Convention Options. - public static void BluesteinForward(Complex[] samples, FourierOptions options) - { - Bluestein(samples, SignByOptions(options)); - ForwardScaleByOptions(options, samples); - } - - /// - /// Bluestein inverse FFT for arbitrary sized sample vectors. - /// - /// Sample vector, where the FFT is evaluated in place. - /// Fourier Transform Convention Options. - public static void BluesteinInverse(Complex[] samples, FourierOptions options) - { - Bluestein(samples, -SignByOptions(options)); - InverseScaleByOptions(options, samples); - } } } diff --git a/src/Numerics/IntegralTransforms/Fourier.Naive.cs b/src/Numerics/IntegralTransforms/Fourier.Naive.cs index d1664b3e..af9da293 100644 --- a/src/Numerics/IntegralTransforms/Fourier.Naive.cs +++ b/src/Numerics/IntegralTransforms/Fourier.Naive.cs @@ -1,4 +1,4 @@ -// +// // Math.NET Numerics, part of the Math.NET Project // http://numerics.mathdotnet.com // http://github.com/mathnet/mathnet-numerics @@ -72,31 +72,5 @@ namespace MathNet.Numerics.IntegralTransforms return spectrum; } - - /// - /// Naive forward DFT, useful e.g. to verify faster algorithms. - /// - /// Time-space sample vector. - /// Fourier Transform Convention Options. - /// Corresponding frequency-space vector. - public static Complex[] NaiveForward(Complex[] timeSpace, FourierOptions options) - { - var frequencySpace = Naive(timeSpace, SignByOptions(options)); - ForwardScaleByOptions(options, frequencySpace); - return frequencySpace; - } - - /// - /// Naive inverse DFT, useful e.g. to verify faster algorithms. - /// - /// Frequency-space sample vector. - /// Fourier Transform Convention Options. - /// Corresponding time-space vector. - public static Complex[] NaiveInverse(Complex[] frequencySpace, FourierOptions options) - { - var timeSpace = Naive(frequencySpace, -SignByOptions(options)); - InverseScaleByOptions(options, timeSpace); - return timeSpace; - } } } diff --git a/src/Numerics/IntegralTransforms/Fourier.Options.cs b/src/Numerics/IntegralTransforms/Fourier.Options.cs deleted file mode 100644 index d1d24e91..00000000 --- a/src/Numerics/IntegralTransforms/Fourier.Options.cs +++ /dev/null @@ -1,100 +0,0 @@ -// -// Math.NET Numerics, part of the Math.NET Project -// http://numerics.mathdotnet.com -// http://github.com/mathnet/mathnet-numerics -// http://mathnetnumerics.codeplex.com -// -// 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 -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// 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 -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -using System; - -namespace MathNet.Numerics.IntegralTransforms -{ - -#if !NOSYSNUMERICS - using Complex = System.Numerics.Complex; -#endif - - /// - /// Complex Fast (FFT) Implementation of the Discrete Fourier Transform (DFT). - /// - public static partial class Fourier - { - /// - /// Extract the exponent sign to be used in forward transforms according to the - /// provided convention options. - /// - /// Fourier Transform Convention Options. - /// Fourier series exponent sign. - static int SignByOptions(FourierOptions options) - { - return (options & FourierOptions.InverseExponent) == FourierOptions.InverseExponent ? 1 : -1; - } - - /// - /// Rescale FFT-the resulting vector according to the provided convention options. - /// - /// Fourier Transform Convention Options. - /// Sample Vector. - static void ForwardScaleByOptions(FourierOptions options, Complex[] samples) - { - if ((options & FourierOptions.NoScaling) == FourierOptions.NoScaling || - (options & FourierOptions.AsymmetricScaling) == FourierOptions.AsymmetricScaling) - { - return; - } - - var scalingFactor = Math.Sqrt(1.0/samples.Length); - for (int i = 0; i < samples.Length; i++) - { - samples[i] *= scalingFactor; - } - } - - /// - /// Rescale the iFFT-resulting vector according to the provided convention options. - /// - /// Fourier Transform Convention Options. - /// Sample Vector. - static void InverseScaleByOptions(FourierOptions options, Complex[] samples) - { - if ((options & FourierOptions.NoScaling) == FourierOptions.NoScaling) - { - return; - } - - var scalingFactor = 1.0/samples.Length; - if ((options & FourierOptions.AsymmetricScaling) != FourierOptions.AsymmetricScaling) - { - scalingFactor = Math.Sqrt(scalingFactor); - } - - for (int i = 0; i < samples.Length; i++) - { - samples[i] *= scalingFactor; - } - } - } -} diff --git a/src/Numerics/IntegralTransforms/Fourier.RadixN.cs b/src/Numerics/IntegralTransforms/Fourier.RadixN.cs index c63373dd..24c78ab8 100644 --- a/src/Numerics/IntegralTransforms/Fourier.RadixN.cs +++ b/src/Numerics/IntegralTransforms/Fourier.RadixN.cs @@ -1,4 +1,4 @@ -// +// // Math.NET Numerics, part of the Math.NET Project // http://numerics.mathdotnet.com // http://github.com/mathnet/mathnet-numerics @@ -144,29 +144,5 @@ namespace MathNet.Numerics.IntegralTransforms }); } } - - /// - /// Radix-2 forward FFT for power-of-two sized sample vectors. - /// - /// Sample vector, where the FFT is evaluated in place. - /// Fourier Transform Convention Options. - /// - public static void Radix2Forward(Complex[] samples, FourierOptions options) - { - Radix2Parallel(samples, SignByOptions(options)); - ForwardScaleByOptions(options, samples); - } - - /// - /// Radix-2 inverse FFT for power-of-two sized sample vectors. - /// - /// Sample vector, where the FFT is evaluated in place. - /// Fourier Transform Convention Options. - /// - public static void Radix2Inverse(Complex[] samples, FourierOptions options) - { - Radix2Parallel(samples, -SignByOptions(options)); - InverseScaleByOptions(options, samples); - } } } diff --git a/src/Numerics/IntegralTransforms/Fourier.cs b/src/Numerics/IntegralTransforms/Fourier.cs new file mode 100644 index 00000000..cf7b0035 --- /dev/null +++ b/src/Numerics/IntegralTransforms/Fourier.cs @@ -0,0 +1,211 @@ +// +// Math.NET Numerics, part of the Math.NET Project +// http://numerics.mathdotnet.com +// http://github.com/mathnet/mathnet-numerics +// http://mathnetnumerics.codeplex.com +// +// 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 +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// 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 +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace MathNet.Numerics.IntegralTransforms +{ + +#if !NOSYSNUMERICS + using System.Numerics; +#endif + + /// + /// Complex Fast (FFT) Implementation of the Discrete Fourier Transform (DFT). + /// + public static partial class Fourier + { + /// + /// Applies the forward Fast Fourier Transform (FFT) to arbitrary-length sample vectors. + /// + /// Sample vector, where the FFT is evaluated in place. + public static void Forward(Complex[] samples) + { + BluesteinForward(samples, FourierOptions.Default); + } + + /// + /// Applies the forward Fast Fourier Transform (FFT) to arbitrary-length sample vectors. + /// + /// Sample vector, where the FFT is evaluated in place. + /// Fourier Transform Convention Options. + public static void Forward(Complex[] samples, FourierOptions options) + { + BluesteinForward(samples, options); + } + + /// + /// Applies the inverse Fast Fourier Transform (iFFT) to arbitrary-length sample vectors. + /// + /// Sample vector, where the FFT is evaluated in place. + public static void Inverse(Complex[] samples) + { + BluesteinInverse(samples, FourierOptions.Default); + } + + /// + /// Applies the inverse Fast Fourier Transform (iFFT) to arbitrary-length sample vectors. + /// + /// Sample vector, where the FFT is evaluated in place. + /// Fourier Transform Convention Options. + public static void Inverse(Complex[] samples, FourierOptions options) + { + BluesteinInverse(samples, options); + } + + /// + /// Naive forward DFT, useful e.g. to verify faster algorithms. + /// + /// Time-space sample vector. + /// Fourier Transform Convention Options. + /// Corresponding frequency-space vector. + public static Complex[] NaiveForward(Complex[] timeSpace, FourierOptions options) + { + var frequencySpace = Naive(timeSpace, SignByOptions(options)); + ForwardScaleByOptions(options, frequencySpace); + return frequencySpace; + } + + /// + /// Naive inverse DFT, useful e.g. to verify faster algorithms. + /// + /// Frequency-space sample vector. + /// Fourier Transform Convention Options. + /// Corresponding time-space vector. + public static Complex[] NaiveInverse(Complex[] frequencySpace, FourierOptions options) + { + var timeSpace = Naive(frequencySpace, -SignByOptions(options)); + InverseScaleByOptions(options, timeSpace); + return timeSpace; + } + + /// + /// Radix-2 forward FFT for power-of-two sized sample vectors. + /// + /// Sample vector, where the FFT is evaluated in place. + /// Fourier Transform Convention Options. + /// + public static void Radix2Forward(Complex[] samples, FourierOptions options) + { + Radix2Parallel(samples, SignByOptions(options)); + ForwardScaleByOptions(options, samples); + } + + /// + /// Radix-2 inverse FFT for power-of-two sized sample vectors. + /// + /// Sample vector, where the FFT is evaluated in place. + /// Fourier Transform Convention Options. + /// + public static void Radix2Inverse(Complex[] samples, FourierOptions options) + { + Radix2Parallel(samples, -SignByOptions(options)); + InverseScaleByOptions(options, samples); + } + + /// + /// Bluestein forward FFT for arbitrary sized sample vectors. + /// + /// Sample vector, where the FFT is evaluated in place. + /// Fourier Transform Convention Options. + public static void BluesteinForward(Complex[] samples, FourierOptions options) + { + Bluestein(samples, SignByOptions(options)); + ForwardScaleByOptions(options, samples); + } + + /// + /// Bluestein inverse FFT for arbitrary sized sample vectors. + /// + /// Sample vector, where the FFT is evaluated in place. + /// Fourier Transform Convention Options. + public static void BluesteinInverse(Complex[] samples, FourierOptions options) + { + Bluestein(samples, -SignByOptions(options)); + InverseScaleByOptions(options, samples); + } + + + /// + /// Extract the exponent sign to be used in forward transforms according to the + /// provided convention options. + /// + /// Fourier Transform Convention Options. + /// Fourier series exponent sign. + static int SignByOptions(FourierOptions options) + { + return (options & FourierOptions.InverseExponent) == FourierOptions.InverseExponent ? 1 : -1; + } + + /// + /// Rescale FFT-the resulting vector according to the provided convention options. + /// + /// Fourier Transform Convention Options. + /// Sample Vector. + static void ForwardScaleByOptions(FourierOptions options, Complex[] samples) + { + if ((options & FourierOptions.NoScaling) == FourierOptions.NoScaling || + (options & FourierOptions.AsymmetricScaling) == FourierOptions.AsymmetricScaling) + { + return; + } + + var scalingFactor = Math.Sqrt(1.0/samples.Length); + for (int i = 0; i < samples.Length; i++) + { + samples[i] *= scalingFactor; + } + } + + /// + /// Rescale the iFFT-resulting vector according to the provided convention options. + /// + /// Fourier Transform Convention Options. + /// Sample Vector. + static void InverseScaleByOptions(FourierOptions options, Complex[] samples) + { + if ((options & FourierOptions.NoScaling) == FourierOptions.NoScaling) + { + return; + } + + var scalingFactor = 1.0/samples.Length; + if ((options & FourierOptions.AsymmetricScaling) != FourierOptions.AsymmetricScaling) + { + scalingFactor = Math.Sqrt(scalingFactor); + } + + for (int i = 0; i < samples.Length; i++) + { + samples[i] *= scalingFactor; + } + } + } +} diff --git a/src/Numerics/IntegralTransforms/Hartley.Naive.cs b/src/Numerics/IntegralTransforms/Hartley.Naive.cs index 5d7c68fd..22965448 100644 --- a/src/Numerics/IntegralTransforms/Hartley.Naive.cs +++ b/src/Numerics/IntegralTransforms/Hartley.Naive.cs @@ -1,10 +1,10 @@ -// +// // Math.NET Numerics, part of the Math.NET Project // 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 @@ -66,31 +66,5 @@ namespace MathNet.Numerics.IntegralTransforms return spectrum; } - - /// - /// Naive forward DHT, useful e.g. to verify faster algorithms. - /// - /// Time-space sample vector. - /// Hartley Transform Convention Options. - /// Corresponding frequency-space vector. - public static double[] NaiveForward(double[] timeSpace, HartleyOptions options) - { - var frequencySpace = Naive(timeSpace); - ForwardScaleByOptions(options, frequencySpace); - return frequencySpace; - } - - /// - /// Naive inverse DHT, useful e.g. to verify faster algorithms. - /// - /// Frequency-space sample vector. - /// Hartley Transform Convention Options. - /// Corresponding time-space vector. - public static double[] NaiveInverse(double[] frequencySpace, HartleyOptions options) - { - var timeSpace = Naive(frequencySpace); - InverseScaleByOptions(options, timeSpace); - return timeSpace; - } } } diff --git a/src/Numerics/IntegralTransforms/Hartley.Options.cs b/src/Numerics/IntegralTransforms/Hartley.cs similarity index 72% rename from src/Numerics/IntegralTransforms/Hartley.Options.cs rename to src/Numerics/IntegralTransforms/Hartley.cs index 7e4c896a..d3b838ad 100644 --- a/src/Numerics/IntegralTransforms/Hartley.Options.cs +++ b/src/Numerics/IntegralTransforms/Hartley.cs @@ -1,4 +1,4 @@ -// +// // Math.NET Numerics, part of the Math.NET Project // http://numerics.mathdotnet.com // http://github.com/mathnet/mathnet-numerics @@ -37,6 +37,32 @@ namespace MathNet.Numerics.IntegralTransforms /// public static partial class Hartley { + /// + /// Naive forward DHT, useful e.g. to verify faster algorithms. + /// + /// Time-space sample vector. + /// Hartley Transform Convention Options. + /// Corresponding frequency-space vector. + public static double[] NaiveForward(double[] timeSpace, HartleyOptions options) + { + var frequencySpace = Naive(timeSpace); + ForwardScaleByOptions(options, frequencySpace); + return frequencySpace; + } + + /// + /// Naive inverse DHT, useful e.g. to verify faster algorithms. + /// + /// Frequency-space sample vector. + /// Hartley Transform Convention Options. + /// Corresponding time-space vector. + public static double[] NaiveInverse(double[] frequencySpace, HartleyOptions options) + { + var timeSpace = Naive(frequencySpace); + InverseScaleByOptions(options, timeSpace); + return timeSpace; + } + /// /// Rescale FFT-the resulting vector according to the provided convention options. /// diff --git a/src/Numerics/IntegralTransforms/Transform.cs b/src/Numerics/IntegralTransforms/Transform.cs deleted file mode 100644 index 371758ef..00000000 --- a/src/Numerics/IntegralTransforms/Transform.cs +++ /dev/null @@ -1,81 +0,0 @@ -// -// Math.NET Numerics, part of the Math.NET Project -// http://numerics.mathdotnet.com -// http://github.com/mathnet/mathnet-numerics -// http://mathnetnumerics.codeplex.com -// -// 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 -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// 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 -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -namespace MathNet.Numerics.IntegralTransforms -{ - -#if !NOSYSNUMERICS - using Complex = System.Numerics.Complex; -#endif - - /// - /// Integral Transforms (including FFT). - /// - public static class Transform - { - /// - /// Applies the forward Fast Fourier Transform (FFT) to arbitrary-length sample vectors. - /// - /// Sample vector, where the FFT is evaluated in place. - public static void FourierForward(Complex[] samples) - { - Fourier.BluesteinForward(samples, FourierOptions.Default); - } - - /// - /// Applies the forward Fast Fourier Transform (FFT) to arbitrary-length sample vectors. - /// - /// Sample vector, where the FFT is evaluated in place. - /// Fourier Transform Convention Options. - public static void FourierForward(Complex[] samples, FourierOptions options) - { - Fourier.BluesteinForward(samples, options); - } - - /// - /// Applies the inverse Fast Fourier Transform (iFFT) to arbitrary-length sample vectors. - /// - /// Sample vector, where the FFT is evaluated in place. - public static void FourierInverse(Complex[] samples) - { - Fourier.BluesteinInverse(samples, FourierOptions.Default); - } - - /// - /// Applies the inverse Fast Fourier Transform (iFFT) to arbitrary-length sample vectors. - /// - /// Sample vector, where the FFT is evaluated in place. - /// Fourier Transform Convention Options. - public static void FourierInverse(Complex[] samples, FourierOptions options) - { - Fourier.BluesteinInverse(samples, options); - } - } -} diff --git a/src/Numerics/Numerics.csproj b/src/Numerics/Numerics.csproj index d96ef466..ec0826ec 100644 --- a/src/Numerics/Numerics.csproj +++ b/src/Numerics/Numerics.csproj @@ -93,6 +93,8 @@ + + @@ -372,14 +374,11 @@ - - - diff --git a/src/UnitTests/IntegralTransformsTests/HartleyTest.cs b/src/UnitTests/IntegralTransformsTests/HartleyTest.cs index a2da4c73..9b77d91e 100644 --- a/src/UnitTests/IntegralTransformsTests/HartleyTest.cs +++ b/src/UnitTests/IntegralTransformsTests/HartleyTest.cs @@ -89,13 +89,13 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests samples, 5, false, - s => Transform.FourierForward(s, fourierOptions), + s => Fourier.Forward(s, fourierOptions), s => Hartley.NaiveForward(s, hartleyOptions)); VerifyMatchesDft( samples, 5, true, - s => Transform.FourierInverse(s, fourierOptions), + s => Fourier.Inverse(s, fourierOptions), s => Hartley.NaiveInverse(s, hartleyOptions)); } } diff --git a/src/UnitTests/IntegralTransformsTests/InverseTransformTest.cs b/src/UnitTests/IntegralTransformsTests/InverseTransformTest.cs index 85e288c3..3b0d6d0e 100644 --- a/src/UnitTests/IntegralTransformsTests/InverseTransformTest.cs +++ b/src/UnitTests/IntegralTransformsTests/InverseTransformTest.cs @@ -139,16 +139,16 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests var work = new Complex[samples.Length]; samples.CopyTo(work, 0); - Transform.FourierForward(work); + Fourier.Forward(work); Assert.IsFalse(work.ListAlmostEqual(samples, 6)); - Transform.FourierInverse(work); + Fourier.Inverse(work); AssertHelpers.ListAlmostEqual(samples, work, 10); - Transform.FourierInverse(work, FourierOptions.Default); + Fourier.Inverse(work, FourierOptions.Default); Assert.IsFalse(work.ListAlmostEqual(samples, 6)); - Transform.FourierForward(work, FourierOptions.Default); + Fourier.Forward(work, FourierOptions.Default); AssertHelpers.ListAlmostEqual(samples, work, 10); } } diff --git a/src/UnitTests/IntegralTransformsTests/MatchingNaiveTransformTest.cs b/src/UnitTests/IntegralTransformsTests/MatchingNaiveTransformTest.cs index 8a94c543..a2d174b0 100644 --- a/src/UnitTests/IntegralTransformsTests/MatchingNaiveTransformTest.cs +++ b/src/UnitTests/IntegralTransformsTests/MatchingNaiveTransformTest.cs @@ -54,20 +54,18 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests return new ContinuousUniform(-1, 1, new System.Random(seed)); } - /// - /// Verify matches naive complex. - /// - static void VerifyMatchesNaiveComplex( + static void Verify( Complex[] samples, int maximumErrorDecimalPlaces, - Func naive, - Action fast) + FourierOptions options, + Func naive, + Action fast) { - var spectrumNaive = naive(samples); + var spectrumNaive = naive(samples, options); var spectrumFast = new Complex[samples.Length]; samples.CopyTo(spectrumFast, 0); - fast(spectrumFast); + fast(spectrumFast, options); AssertHelpers.ListAlmostEqual(spectrumNaive, spectrumFast, maximumErrorDecimalPlaces); } @@ -79,21 +77,12 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests [TestCase(FourierOptions.Default)] [TestCase(FourierOptions.Matlab)] [TestCase(FourierOptions.NumericalRecipes)] - public void FourierRadix2MatchesNaiveOnRealSine(FourierOptions options) + public void FourierRadix2MatchesNaive_RealSine(FourierOptions options) { var samples = Generate.PeriodicMap(16, w => new Complex(Math.Sin(w), 0), 16, 1.0, Constants.Pi2); - VerifyMatchesNaiveComplex( - samples, - 12, - s => Fourier.NaiveForward(s, options), - s => Fourier.Radix2Forward(s, options)); - - VerifyMatchesNaiveComplex( - samples, - 12, - s => Fourier.NaiveInverse(s, options), - s => Fourier.Radix2Inverse(s, options)); + Verify(samples, 12, options, Fourier.NaiveForward, Fourier.Radix2Forward); + Verify(samples, 12, options, Fourier.NaiveInverse, Fourier.Radix2Inverse); } /// @@ -103,21 +92,12 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests [TestCase(FourierOptions.Default)] [TestCase(FourierOptions.Matlab)] [TestCase(FourierOptions.NumericalRecipes)] - public void FourierRadix2MatchesNaiveOnRandom(FourierOptions options) + public void FourierRadix2MatchesNaive_Random(FourierOptions options) { var samples = Generate.RandomComplex(0x80, GetUniform(1)); - VerifyMatchesNaiveComplex( - samples, - 10, - s => Fourier.NaiveForward(s, options), - s => Fourier.Radix2Forward(s, options)); - - VerifyMatchesNaiveComplex( - samples, - 10, - s => Fourier.NaiveInverse(s, options), - s => Fourier.Radix2Inverse(s, options)); + Verify(samples, 10, options, Fourier.NaiveForward, Fourier.Radix2Forward); + Verify(samples, 10, options, Fourier.NaiveInverse, Fourier.Radix2Inverse); } /// @@ -127,21 +107,12 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests [TestCase(FourierOptions.Default)] [TestCase(FourierOptions.Matlab)] [TestCase(FourierOptions.NumericalRecipes)] - public void FourierBluesteinMatchesNaiveOnRealSineNonPowerOfTwo(FourierOptions options) + public void FourierBluesteinMatchesNaive_RealSine_Arbitrary(FourierOptions options) { var samples = Generate.PeriodicMap(14, w => new Complex(Math.Sin(w), 0), 14, 1.0, Constants.Pi2); - VerifyMatchesNaiveComplex( - samples, - 12, - s => Fourier.NaiveForward(s, options), - s => Fourier.BluesteinForward(s, options)); - - VerifyMatchesNaiveComplex( - samples, - 12, - s => Fourier.NaiveInverse(s, options), - s => Fourier.BluesteinInverse(s, options)); + Verify(samples, 12, options, Fourier.NaiveForward, Fourier.BluesteinForward); + Verify(samples, 12, options, Fourier.NaiveInverse, Fourier.BluesteinInverse); } /// @@ -151,21 +122,12 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests [TestCase(FourierOptions.Default)] [TestCase(FourierOptions.Matlab)] [TestCase(FourierOptions.NumericalRecipes)] - public void FourierBluesteinMatchesNaiveOnRandomPowerOfTwo(FourierOptions options) + public void FourierBluesteinMatchesNaive_Random_PowerOfTwo(FourierOptions options) { var samples = Generate.RandomComplex(0x80, GetUniform(1)); - VerifyMatchesNaiveComplex( - samples, - 10, - s => Fourier.NaiveForward(s, options), - s => Fourier.BluesteinForward(s, options)); - - VerifyMatchesNaiveComplex( - samples, - 10, - s => Fourier.NaiveInverse(s, options), - s => Fourier.BluesteinInverse(s, options)); + Verify(samples, 10, options, Fourier.NaiveForward, Fourier.BluesteinForward); + Verify(samples, 10, options, Fourier.NaiveInverse, Fourier.BluesteinInverse); } /// @@ -175,20 +137,35 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests [TestCase(FourierOptions.Default)] [TestCase(FourierOptions.Matlab)] [TestCase(FourierOptions.NumericalRecipes)] - public void FourierBluesteinMatchesNaiveOnRandomNonPowerOfTwo(FourierOptions options) + public void FourierBluesteinMatchesNaive_Random_Arbitrary(FourierOptions options) { var samples = Generate.RandomComplex(0x7F, GetUniform(1)); - VerifyMatchesNaiveComplex( - samples, - 10, - s => Fourier.NaiveForward(s, options), - s => Fourier.BluesteinForward(s, options)); - VerifyMatchesNaiveComplex( - samples, - 10, - s => Fourier.NaiveInverse(s, options), - s => Fourier.BluesteinInverse(s, options)); + Verify(samples, 10, options, Fourier.NaiveForward, Fourier.BluesteinForward); + Verify(samples, 10, options, Fourier.NaiveInverse, Fourier.BluesteinInverse); + } + + [Test, Explicit("Long-Running")] + public void AlgorithmsMatchNaive_PowerOfTwo_Large() + { + // 65536 = 2^16 + const FourierOptions options = FourierOptions.NoScaling; + var samples = Generate.RandomComplex(65536, GetUniform(1)); + var naive = Fourier.NaiveForward(samples, options); + + Verify(samples, 10, options, (a, b) => naive, Fourier.Radix2Forward); + Verify(samples, 10, options, (a, b) => naive, Fourier.BluesteinForward); + } + + [Test, Explicit("Long-Running")] + public void AlgorithmsMatchNaive_Arbitrary_Large() + { + // 30870 = 2*3*3*5*7*7*7 + const FourierOptions options = FourierOptions.NoScaling; + var samples = Generate.RandomComplex(30870, GetUniform(1)); + var naive = Fourier.NaiveForward(samples, options); + + Verify(samples, 10, options, (a, b) => naive, Fourier.BluesteinForward); } } } diff --git a/src/UnitTests/IntegralTransformsTests/ParsevalTheoremTest.cs b/src/UnitTests/IntegralTransformsTests/ParsevalTheoremTest.cs index ca7cfe2a..1816b7e5 100644 --- a/src/UnitTests/IntegralTransformsTests/ParsevalTheoremTest.cs +++ b/src/UnitTests/IntegralTransformsTests/ParsevalTheoremTest.cs @@ -42,7 +42,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests #endif /// - /// Parseval theorem verification tests. + /// Parseval's theorem verification tests. /// [TestFixture, Category("FFT")] public class ParsevalTheoremTest @@ -56,7 +56,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests } /// - /// Fourier default transform satisfies parsevals theorem. + /// Fourier default transform satisfies Parseval's theorem. /// /// Samples count. [TestCase(0x1000)] @@ -71,7 +71,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests samples.CopyTo(work, 0); // Default -> Symmetric Scaling - Transform.FourierForward(work); + Fourier.Forward(work); var frequencySpaceEnergy = (from s in work select s.MagnitudeSquared()).Mean(); @@ -79,7 +79,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests } /// - /// Hartley default naive satisfies parsevals theorem. + /// Hartley default naive satisfies Parseval's theorem. /// /// Samples count. [TestCase(0x40)]