diff --git a/src/Managed.UnitTests/IntegralTransformsTests/DftTest.cs b/src/Managed.UnitTests/IntegralTransformsTests/DftTest.cs new file mode 100644 index 00000000..cf1e4b1f --- /dev/null +++ b/src/Managed.UnitTests/IntegralTransformsTests/DftTest.cs @@ -0,0 +1,246 @@ +// +// Math.NET Numerics, part of the Math.NET Project +// http://mathnet.opensourcedotnet.info +// +// Copyright (c) 2009 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.UnitTests.IntegralTransformsTests +{ + using System; + using MbUnit.Framework; + using IntegralTransforms; + using IntegralTransforms.Algorithms; + + [TestFixture] + public class DftTest + { + private static Random _random = new Random(); + + private static Complex[] ProvideSamples(int count) + { + var samples = new Complex[count]; + for (int i = 0; i < samples.Length; i++) + { + samples[i] = Complex.WithRealImaginary( + 1 - (2 * _random.NextDouble()), + 1 - (2 * _random.NextDouble())); + } + + return samples; + } + + [Test] + public void NaiveTransformsRealSineCorrectly() + { + var realSine = new Complex[16]; + for (int i = 0; i < realSine.Length; i++) + { + realSine[i] = Math.Sin(i / 8.0 * Constants.Pi); + } + + // real-odd transforms to imaginary odd + var dft = new DiscreteFourierTransform(); + var spectrum = dft.NaiveForward(realSine, FourierOptions.Matlab); + + // all real components must be zero + foreach (var c in spectrum) + { + Assert.AreApproximatelyEqual(0, c.Real, 1e-12, "real"); + } + + // all imaginary components except second and last musth be zero + for(int i = 0; i dft.Radix2Forward(samples, FourierOptions.Default)); + + Assert.Throws( + typeof(ArgumentException), + () => dft.Radix2Inverse(samples, FourierOptions.Default)); + } + + [Test] + public void BluesteinMatchesNaiveOnRealSine() + { + var realSine = new Complex[14]; + for (int i = 0; i < realSine.Length; i++) + { + realSine[i] = Math.Sin(i / 7.0 * Constants.Pi); + } + + // real-odd transforms to imaginary odd + var dft = new DiscreteFourierTransform(); + var spectrumNaive = dft.NaiveForward(realSine, FourierOptions.Matlab); + + var spectrumBluestein = new Complex[realSine.Length]; + realSine.CopyTo(spectrumBluestein, 0); + dft.BluesteinForward(spectrumBluestein, FourierOptions.Matlab); + + AssertHelpers.AlmostEqualList(spectrumNaive, spectrumBluestein, 1e-12); + } + + [Test] + public void BluesteinMatchesNaiveOnRandomPowerOfTwo() + { + var samples = ProvideSamples(0x80); + var work = new Complex[samples.Length]; + samples.CopyTo(work, 0); + + var dft = new DiscreteFourierTransform(); + var spectrumNaive = dft.NaiveForward(samples, FourierOptions.Matlab); + dft.BluesteinForward(work, FourierOptions.Matlab); + + AssertHelpers.AlmostEqualList(spectrumNaive, work, 1e-12); + } + + [Test] + public void BluesteinMatchesNaiveOnRandomNonPowerOfTwo() + { + var samples = ProvideSamples(0x7F); + var work = new Complex[samples.Length]; + samples.CopyTo(work, 0); + + var dft = new DiscreteFourierTransform(); + var spectrumNaive = dft.NaiveForward(samples, FourierOptions.Matlab); + dft.BluesteinForward(work, FourierOptions.Matlab); + + AssertHelpers.AlmostEqualList(spectrumNaive, work, 1e-12); + } + + [Test] + [Row(FourierOptions.Default)] + [Row(FourierOptions.Matlab)] + public void BluesteinIsReversible(FourierOptions options) + { + var samples = ProvideSamples(0x7FFF); + var work = new Complex[samples.Length]; + samples.CopyTo(work, 0); + + var dft = new DiscreteFourierTransform(); + dft.BluesteinForward(work, options); + + Assert.IsFalse(work.AlmostEqualListWithError(samples, 1e-12)); + + dft.BluesteinInverse(work, options); + + AssertHelpers.AlmostEqualList(samples, work, 1e-12); + } + } +} diff --git a/src/Managed.UnitTests/Managed.UnitTests.csproj b/src/Managed.UnitTests/Managed.UnitTests.csproj index ed40e357..d987d51d 100644 --- a/src/Managed.UnitTests/Managed.UnitTests.csproj +++ b/src/Managed.UnitTests/Managed.UnitTests.csproj @@ -64,6 +64,7 @@ + diff --git a/src/Managed/IntegralTransforms/Algorithms/DiscreteFourierTransform.Bluestein.cs b/src/Managed/IntegralTransforms/Algorithms/DiscreteFourierTransform.Bluestein.cs new file mode 100644 index 00000000..2fd90d99 --- /dev/null +++ b/src/Managed/IntegralTransforms/Algorithms/DiscreteFourierTransform.Bluestein.cs @@ -0,0 +1,175 @@ +// +// Math.NET Numerics, part of the Math.NET Project +// http://mathnet.opensourcedotnet.info +// +// Copyright (c) 2009 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.Algorithms +{ + using System; + using NumberTheory; + using Threading; + + /// + /// Complex Fast (FFT) Implementation of the Discrete Fourier Transform (DFT). + /// + public partial class DiscreteFourierTransform + { + /// + /// Generate the bluestein sequence for the provided problem size. + /// + /// Number of samples. + /// Bluestein sequence exp(I*Pi*k^2/N) + private static Complex[] BluesteinSequence(int n) + { + double s = Constants.Pi / n; + var sequence = new Complex[n]; + + for (int k = 0; k < sequence.Length; k++) + { + double t = s * (k * k); + sequence[k] = Complex.WithRealImaginary(Math.Cos(t), Math.Sin(t)); + } + + return sequence; + } + + /// + /// Convolution with the bluestein sequence. + /// + /// Sample Vector. + private static void BluesteinConvolution(Complex[] samples) + { + int n = samples.Length; + Complex[] sequence = BluesteinSequence(n); + + // Padding to power of two >= 2N–1 so we can apply Radix-2 FFT. + int m = ((n << 1) - 1).CeilingToPowerOfTwo(); + Complex[] b = new Complex[m]; + Complex[] a = new Complex[m]; + + Parallel.Invoke( + () => + { + // Build and transform padded sequence b_k = exp(I*Pi*k^2/N) + for (int i = 0; i < n; i++) + { + b[i] = sequence[i]; + } + + for (int i = m - n + 1; i < b.Length; i++) + { + b[i] = sequence[m - i]; + } + + Radix2(b, -1); + }, + () => + { + // Build and transform padded sequence a_k = x_k * exp(-I*Pi*k^2/N) + for (int i = 0; i < samples.Length; i++) + { + a[i] = sequence[i].Conjugate * samples[i]; + } + + Radix2(a, -1); + }); + + for (int i = 0; i < a.Length; i++) + { + a[i] *= b[i]; + } + + Radix2(a, 1); + + var nbinv = 1.0 / m; + for (int i = 0; i < samples.Length; i++) + { + samples[i] = nbinv * sequence[i].Conjugate * a[i]; + } + } + + /// + /// Swap the real and imaginary parts of each sample. + /// + /// Sample Vector. + private static void SwapRealImaginary(Complex[] samples) + { + for (int i = 0; i < samples.Length; i++) + { + samples[i] = Complex.WithRealImaginary(samples[i].Imaginary, samples[i].Real); + } + } + + /// + /// Bluestein generic DFT, useful e.g. to verify faster algorithms. + /// + /// Time-space sample vector. + /// Fourier series exponent sign. + internal static void Bluestein(Complex[] samples, int exponentSign) + { + int n = samples.Length; + if (n.IsPowerOfTwo()) + { + Radix2(samples, exponentSign); + return; + } + + if (exponentSign == 1) + { + SwapRealImaginary(samples); + } + + BluesteinConvolution(samples); + + if (exponentSign == 1) + { + SwapRealImaginary(samples); + } + } + + /// + /// Bluestein forward FFT for arbitrary sample vectors. + /// + /// Sample vector, where the FFT is evaluated in place. + /// Fourier Transform Convention Options. + public void BluesteinForward(Complex[] samples, FourierOptions options) + { + Bluestein(samples, SignByOptions(options)); + ForwardScaleByOptions(options, samples); + } + + /// + /// Bluestein inverse FFT for arbitrary sample vectors. + /// + /// Sample vector, where the FFT is evaluated in place. + /// Fourier Transform Convention Options. + public void BluesteinInverse(Complex[] samples, FourierOptions options) + { + Bluestein(samples, -SignByOptions(options)); + InverseScaleByOptions(options, samples); + } + } +} \ No newline at end of file diff --git a/src/Managed/IntegralTransforms/Algorithms/DiscreteFourierTransform.Naive.cs b/src/Managed/IntegralTransforms/Algorithms/DiscreteFourierTransform.Naive.cs new file mode 100644 index 00000000..b5ba03f8 --- /dev/null +++ b/src/Managed/IntegralTransforms/Algorithms/DiscreteFourierTransform.Naive.cs @@ -0,0 +1,95 @@ +// +// Math.NET Numerics, part of the Math.NET Project +// http://mathnet.opensourcedotnet.info +// +// Copyright (c) 2009 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.Algorithms +{ + using System; + using Threading; + + /// + /// Complex Fast (FFT) Implementation of the Discrete Fourier Transform (DFT). + /// + public partial class DiscreteFourierTransform + { + /// + /// Naive generic DFT, useful e.g. to verify faster algorithms. + /// + /// Time-space sample vector. + /// Fourier series exponent sign. + /// Corresponding frequency-space vector. + internal static Complex[] Naive(Complex[] samples, int exponentSign) + { + double w0 = exponentSign * 2 * Constants.Pi / samples.Length; + var spectrum = new Complex[samples.Length]; + + Parallel.For( + 0, + samples.Length, + k => + { + double wk = w0 * k; + Complex sum = Complex.Zero; + for (int n = 0; n < samples.Length; n++) + { + double w = n * wk; + sum += samples[n] * Complex.WithRealImaginary(Math.Cos(w), Math.Sin(w)); + } + + spectrum[k] = sum; + }); + + 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 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 Complex[] NaiveInverse(Complex[] frequencySpace, FourierOptions options) + { + var timeSpace = Naive(frequencySpace, -SignByOptions(options)); + InverseScaleByOptions(options, timeSpace); + return timeSpace; + } + } +} diff --git a/src/Managed/IntegralTransforms/Algorithms/DiscreteFourierTransform.Options.cs b/src/Managed/IntegralTransforms/Algorithms/DiscreteFourierTransform.Options.cs new file mode 100644 index 00000000..bff00a96 --- /dev/null +++ b/src/Managed/IntegralTransforms/Algorithms/DiscreteFourierTransform.Options.cs @@ -0,0 +1,93 @@ +// +// Math.NET Numerics, part of the Math.NET Project +// http://mathnet.opensourcedotnet.info +// +// Copyright (c) 2009 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.Algorithms +{ + using System; + + /// + /// Complex Fast (FFT) Implementation of the Discrete Fourier Transform (DFT). + /// + public partial class DiscreteFourierTransform + { + /// + /// Extract the exponent sign to be used in forward transforms according to the + /// provided convention options. + /// + /// Fourier Transform Convention Options. + /// Fourier series exponent sign. + private 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. + private 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. + private 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/Managed/IntegralTransforms/Algorithms/DiscreteFourierTransform.RadixN.cs b/src/Managed/IntegralTransforms/Algorithms/DiscreteFourierTransform.RadixN.cs new file mode 100644 index 00000000..6f170db6 --- /dev/null +++ b/src/Managed/IntegralTransforms/Algorithms/DiscreteFourierTransform.RadixN.cs @@ -0,0 +1,137 @@ +// +// Math.NET Numerics, part of the Math.NET Project +// http://mathnet.opensourcedotnet.info +// +// Copyright (c) 2009 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.Algorithms +{ + using System; + using NumberTheory; + using Properties; + + /// + /// Complex Fast (FFT) Implementation of the Discrete Fourier Transform (DFT). + /// + public partial class DiscreteFourierTransform + { + /// + /// Radix-2 Reorder Helper Method + /// + /// Sample type + /// Sample vector + private static void Radix2Reorder(T[] samples) + { + int j = 0; + for (int i = 0; i < samples.Length - 1; i++) + { + if (i < j) + { + T temp = samples[i]; + samples[i] = samples[j]; + samples[j] = temp; + } + + int m = samples.Length; + + do + { + m >>= 1; + j ^= m; + } while ((j & m) == 0); + } + } + + /// + /// Radix-2 Step Helper Method + /// + /// Sample vector. + /// Fourier series exponent sign. + /// Level Group Size. + /// Index inside of the level. + private static void Radix2Step(Complex[] samples, int exponentSign, int levelSize, int k) + { + // Twiddle Factor + double exponent = (exponentSign * k) * Constants.Pi / levelSize; + Complex w = Complex.WithRealImaginary(Math.Cos(exponent), Math.Sin(exponent)); + + int step = levelSize << 1; + for (int i = k; i < samples.Length; i += step) + { + Complex ai = samples[i]; + Complex t = w * samples[i + levelSize]; + samples[i] = ai + t; + samples[i + levelSize] = ai - t; + } + } + + /// + /// Radix-2 generic FFT for power-of-two sample vectors. + /// + /// Sample vector, where the FFT is evaluated in place. + /// Fourier series exponent sign. + /// + internal static void Radix2(Complex[] samples, int exponentSign) + { + if (!samples.Length.IsPowerOfTwo()) + { + throw new ArgumentException(Resources.ArgumentPowerOfTwo); + } + + Radix2Reorder(samples); + for (int levelSize = 1; levelSize < samples.Length; levelSize *= 2) + { + for (int k = 0; k <= levelSize - 1; k++) + { + Radix2Step(samples, exponentSign, levelSize, k); + } + } + } + + /// + /// Radix-2 forward FFT for power-of-two sample vectors. + /// + /// Sample vector, where the FFT is evaluated in place. + /// Fourier Transform Convention Options. + /// + public void Radix2Forward(Complex[] samples, FourierOptions options) + { + Radix2(samples, SignByOptions(options)); + ForwardScaleByOptions(options, samples); + } + + /// + /// Radix-2 inverse FFT for power-of-two sample vectors. + /// + /// Sample vector, where the FFT is evaluated in place. + /// Fourier Transform Convention Options. + /// + public void Radix2Inverse(Complex[] samples, FourierOptions options) + { + Radix2(samples, -SignByOptions(options)); + InverseScaleByOptions(options, samples); + } + } +} \ No newline at end of file diff --git a/src/Managed/IntegralTransforms/FourierOptions.cs b/src/Managed/IntegralTransforms/FourierOptions.cs new file mode 100644 index 00000000..ef1b3c29 --- /dev/null +++ b/src/Managed/IntegralTransforms/FourierOptions.cs @@ -0,0 +1,73 @@ +// +// Math.NET Numerics, part of the Math.NET Project +// http://mathnet.opensourcedotnet.info +// +// Copyright (c) 2009 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 +{ + using System; + + /// + /// Fourier Transform Convention + /// + [Flags] + public enum FourierOptions + { + // FLAGS: + + /// + /// Inverse integrand exponent (forward: positive sign; inverse: negative sign). + /// + InverseExponent = 0x01, + + /// + /// Only scale by 1/N in the inverse direction; No scaling in forward direction. + /// + AsymmetricScaling = 0x02, + + /// + /// Don't scale at all (neither on forward nor on inverse transformation). + /// + NoScaling = 0x04, + + // USABILITY POINTERS: + + /// + /// Universal; Symmetric scaling and common exponent (used in Maple). + /// + Default = 0, + + /// + /// Only scale by 1/N in the inverse direction; No scaling in forward direction (used in Matlab). [= AsymmetricScaling] + /// + Matlab = AsymmetricScaling, + + /// + /// Inverse integrand exponent; No scaling at all (used in all Numerical Recipes based implementations). [= InverseExponent | NoScaling] + /// + NumericalRecipes = InverseExponent | NoScaling + } +} diff --git a/src/Managed/Managed.csproj b/src/Managed/Managed.csproj index 7c53c4f8..2f88b753 100644 --- a/src/Managed/Managed.csproj +++ b/src/Managed/Managed.csproj @@ -55,6 +55,11 @@ + + + + + diff --git a/src/Native.UnitTests/Native.UnitTests.csproj b/src/Native.UnitTests/Native.UnitTests.csproj index b08f8b58..ef565cd1 100644 --- a/src/Native.UnitTests/Native.UnitTests.csproj +++ b/src/Native.UnitTests/Native.UnitTests.csproj @@ -74,6 +74,9 @@ DistributionTests\Continuous\NormalTests.cs + + IntegralTransformsTests\DftTest.cs + IntegrationTests\IntegrationTest.cs diff --git a/src/Native/Native.csproj b/src/Native/Native.csproj index 6064b589..07e467e3 100644 --- a/src/Native/Native.csproj +++ b/src/Native/Native.csproj @@ -71,6 +71,21 @@ Distributions\IDistribution.cs + + IntegralTransforms\Algorithms\DiscreteFourierTransform.Bluestein.cs + + + IntegralTransforms\Algorithms\DiscreteFourierTransform.Naive.cs + + + IntegralTransforms\Algorithms\DiscreteFourierTransform.Options.cs + + + IntegralTransforms\Algorithms\DiscreteFourierTransform.RadixN.cs + + + IntegralTransforms\FourierOptions.cs + Integration\Algorithms\DoubleExponentialTransformation.cs