diff --git a/src/Numerics/IntegralTransforms/Fourier.cs b/src/Numerics/IntegralTransforms/Fourier.cs index 74a96752..c9703e4b 100644 --- a/src/Numerics/IntegralTransforms/Fourier.cs +++ b/src/Numerics/IntegralTransforms/Fourier.cs @@ -3,7 +3,7 @@ // http://numerics.mathdotnet.com // http://github.com/mathnet/mathnet-numerics // -// Copyright (c) 2009-2015 Math.NET +// Copyright (c) 2009-2016 Math.NET // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -28,6 +28,7 @@ // using System; +using MathNet.Numerics.Providers.FourierTransform; namespace MathNet.Numerics.IntegralTransforms { @@ -46,7 +47,7 @@ namespace MathNet.Numerics.IntegralTransforms /// Sample vector, where the FFT is evaluated in place. public static void Forward(Complex[] samples) { - BluesteinForward(samples, FourierOptions.Default); + Control.FourierTransformProvider.ForwardInplace(samples, FourierTransformScaling.SymmetricScaling); } /// @@ -56,7 +57,23 @@ namespace MathNet.Numerics.IntegralTransforms /// Fourier Transform Convention Options. public static void Forward(Complex[] samples, FourierOptions options) { - BluesteinForward(samples, options); + switch (options) + { + case FourierOptions.NoScaling: + case FourierOptions.AsymmetricScaling: + Control.FourierTransformProvider.ForwardInplace(samples, FourierTransformScaling.NoScaling); + break; + case FourierOptions.InverseExponent: + Control.FourierTransformProvider.BackwardInplace(samples, FourierTransformScaling.SymmetricScaling); + break; + case FourierOptions.InverseExponent | FourierOptions.NoScaling: + case FourierOptions.InverseExponent | FourierOptions.AsymmetricScaling: + Control.FourierTransformProvider.BackwardInplace(samples, FourierTransformScaling.NoScaling); + break; + default: + Control.FourierTransformProvider.ForwardInplace(samples, FourierTransformScaling.SymmetricScaling); + break; + } } /// @@ -65,7 +82,7 @@ namespace MathNet.Numerics.IntegralTransforms /// Sample vector, where the FFT is evaluated in place. public static void Inverse(Complex[] samples) { - BluesteinInverse(samples, FourierOptions.Default); + Control.FourierTransformProvider.BackwardInplace(samples, FourierTransformScaling.SymmetricScaling); } /// @@ -75,7 +92,27 @@ namespace MathNet.Numerics.IntegralTransforms /// Fourier Transform Convention Options. public static void Inverse(Complex[] samples, FourierOptions options) { - BluesteinInverse(samples, options); + switch (options) + { + case FourierOptions.NoScaling: + Control.FourierTransformProvider.BackwardInplace(samples, FourierTransformScaling.NoScaling); + break; + case FourierOptions.AsymmetricScaling: + Control.FourierTransformProvider.BackwardInplace(samples, FourierTransformScaling.BackwardScaling); + break; + case FourierOptions.InverseExponent: + Control.FourierTransformProvider.ForwardInplace(samples, FourierTransformScaling.SymmetricScaling); + break; + case FourierOptions.InverseExponent | FourierOptions.NoScaling: + Control.FourierTransformProvider.ForwardInplace(samples, FourierTransformScaling.NoScaling); + break; + case FourierOptions.InverseExponent | FourierOptions.AsymmetricScaling: + Control.FourierTransformProvider.ForwardInplace(samples, FourierTransformScaling.ForwardScaling); + break; + default: + Control.FourierTransformProvider.BackwardInplace(samples, FourierTransformScaling.SymmetricScaling); + break; + } } /// diff --git a/src/Numerics/Providers/FourierTransform/IFourierTransformProvider.cs b/src/Numerics/Providers/FourierTransform/IFourierTransformProvider.cs index ec44d664..f5fea08e 100644 --- a/src/Numerics/Providers/FourierTransform/IFourierTransformProvider.cs +++ b/src/Numerics/Providers/FourierTransform/IFourierTransformProvider.cs @@ -38,7 +38,8 @@ namespace MathNet.Numerics.Providers.FourierTransform { NoScaling = 0, SymmetricScaling = 1, - AsymmetricScaling = 2 + BackwardScaling = 2, + ForwardScaling = 3 } public interface IFourierTransformProvider diff --git a/src/Numerics/Providers/FourierTransform/ManagedFourierTransformProvider.cs b/src/Numerics/Providers/FourierTransform/ManagedFourierTransformProvider.cs index 58d42e3d..b5c89c3e 100644 --- a/src/Numerics/Providers/FourierTransform/ManagedFourierTransformProvider.cs +++ b/src/Numerics/Providers/FourierTransform/ManagedFourierTransformProvider.cs @@ -26,6 +26,7 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using System.Collections; using MathNet.Numerics.IntegralTransforms; namespace MathNet.Numerics.Providers.FourierTransform @@ -41,7 +42,7 @@ namespace MathNet.Numerics.Providers.FourierTransform /// Try to find out whether the provider is available, at least in principle. /// Verification may still fail if available, but it will certainly fail if unavailable. /// - public virtual bool IsAvailable() + public bool IsAvailable() { return true; } @@ -49,26 +50,49 @@ namespace MathNet.Numerics.Providers.FourierTransform /// /// Initialize and verify that the provided is indeed available. If not, fall back to alternatives like the managed provider /// - public virtual void InitializeVerify() + public void InitializeVerify() { } - public override string ToString() + public string ToString() { return "Managed"; } - public virtual void ForwardInplace(Complex[] complex, FourierTransformScaling scaling) + public void ForwardInplace(Complex[] complex, FourierTransformScaling scaling) { - Fourier.BluesteinForward(complex, Options(scaling)); + switch (scaling) + { + case FourierTransformScaling.SymmetricScaling: + Fourier.BluesteinForward(complex, FourierOptions.Default); + break; + case FourierTransformScaling.ForwardScaling: + // Only backward scaling can be expressed with options, hence the double-inverse + Fourier.BluesteinInverse(complex, FourierOptions.AsymmetricScaling | FourierOptions.InverseExponent); + break; + default: + Fourier.BluesteinForward(complex, FourierOptions.NoScaling); + break; + } } - public virtual void BackwardInplace(Complex[] complex, FourierTransformScaling scaling) + public void BackwardInplace(Complex[] complex, FourierTransformScaling scaling) { - Fourier.BluesteinInverse(complex, Options(scaling)); + switch (scaling) + { + case FourierTransformScaling.SymmetricScaling: + Fourier.BluesteinInverse(complex, FourierOptions.Default); + break; + case FourierTransformScaling.BackwardScaling: + Fourier.BluesteinInverse(complex, FourierOptions.AsymmetricScaling); + break; + default: + Fourier.BluesteinInverse(complex, FourierOptions.NoScaling); + break; + } } - public virtual Complex[] Forward(Complex[] complexTimeSpace, FourierTransformScaling scaling) + public Complex[] Forward(Complex[] complexTimeSpace, FourierTransformScaling scaling) { Complex[] work = new Complex[complexTimeSpace.Length]; complexTimeSpace.Copy(work); @@ -76,26 +100,12 @@ namespace MathNet.Numerics.Providers.FourierTransform return work; } - public virtual Complex[] Backward(Complex[] complexFrequenceSpace, FourierTransformScaling scaling) + public Complex[] Backward(Complex[] complexFrequenceSpace, FourierTransformScaling scaling) { Complex[] work = new Complex[complexFrequenceSpace.Length]; complexFrequenceSpace.Copy(work); BackwardInplace(work, scaling); return work; } - - private FourierOptions Options(FourierTransformScaling scaling) - { - switch (scaling) - { - case FourierTransformScaling.NoScaling: - return FourierOptions.NoScaling; - case FourierTransformScaling.AsymmetricScaling: - return FourierOptions.AsymmetricScaling; - case FourierTransformScaling.SymmetricScaling: - default: - return FourierOptions.Default; - } - } } } diff --git a/src/Numerics/Providers/FourierTransform/Mkl/MklFourierTransformProvider.cs b/src/Numerics/Providers/FourierTransform/Mkl/MklFourierTransformProvider.cs index cf033d09..eb7b413d 100644 --- a/src/Numerics/Providers/FourierTransform/Mkl/MklFourierTransformProvider.cs +++ b/src/Numerics/Providers/FourierTransform/Mkl/MklFourierTransformProvider.cs @@ -152,24 +152,26 @@ namespace MathNet.Numerics.Providers.FourierTransform.Mkl return work; } - private double ForwardScaling(FourierTransformScaling scaling, int length) + static double ForwardScaling(FourierTransformScaling scaling, int length) { switch (scaling) { case FourierTransformScaling.SymmetricScaling: return Math.Sqrt(1.0/length); + case FourierTransformScaling.ForwardScaling: + return 1.0/length; default: return 1.0; } } - private double BackwardScaling(FourierTransformScaling scaling, int length) + static double BackwardScaling(FourierTransformScaling scaling, int length) { switch (scaling) { case FourierTransformScaling.SymmetricScaling: return Math.Sqrt(1.0/length); - case FourierTransformScaling.AsymmetricScaling: + case FourierTransformScaling.BackwardScaling: return 1.0/length; default: return 1.0; diff --git a/src/UnitTests/FourierTransformProviderTests/FourierTransformProviderTests.cs b/src/UnitTests/FourierTransformProviderTests/FourierTransformProviderTests.cs index 91e67507..c29e2689 100644 --- a/src/UnitTests/FourierTransformProviderTests/FourierTransformProviderTests.cs +++ b/src/UnitTests/FourierTransformProviderTests/FourierTransformProviderTests.cs @@ -55,7 +55,7 @@ namespace MathNet.Numerics.UnitTests.FourierTransformProviderTests // real-odd transforms to imaginary odd samples.Copy(spectrum); - Control.FourierTransformProvider.ForwardInplace(spectrum, FourierTransformScaling.AsymmetricScaling); + Control.FourierTransformProvider.ForwardInplace(spectrum, FourierTransformScaling.BackwardScaling); // all real components must be zero foreach (var c in spectrum)