From 33039634e33afe61cdd4c4011354d02cda4c451c Mon Sep 17 00:00:00 2001 From: macaba Date: Sat, 13 Nov 2021 16:55:19 +0000 Subject: [PATCH] Span & Memory on Fourier --- .../IntegralTransformsTests/FourierTest.cs | 8 +- .../InverseTransformTest.cs | 16 ++-- .../MatchingReferenceTransformTest.cs | 40 +++++----- .../ParsevalTheoremTest.cs | 8 +- .../ReferenceDiscreteFourierTransform.cs | 44 +++++------ .../FourierTransformProviderTests.cs | 7 +- .../Double/LinearAlgebraProviderTests.cs | 2 +- src/Numerics/Generate.cs | 12 +-- src/Numerics/IntegralTransforms/Fourier.cs | 76 +++++++++---------- src/Numerics/LinearAlgebra/Builder.cs | 8 +- .../LinearAlgebra/Complex/DenseMatrix.cs | 2 +- .../LinearAlgebra/Complex/DenseVector.cs | 2 +- .../LinearAlgebra/Complex/DiagonalMatrix.cs | 2 +- .../LinearAlgebra/Complex32/DenseMatrix.cs | 2 +- .../LinearAlgebra/Complex32/DenseVector.cs | 2 +- .../LinearAlgebra/Complex32/DiagonalMatrix.cs | 2 +- src/Numerics/Numerics.csproj | 1 + .../IFourierTransformProvider.cs | 25 +++--- ...nagedFourierTransformProvider.Bluestein.cs | 48 ++++++------ .../ManagedFourierTransformProvider.Radix2.cs | 38 +++++----- ...ManagedFourierTransformProvider.Scaling.cs | 8 +- .../ManagedFourierTransformProvider.cs | 48 ++++++------ 22 files changed, 201 insertions(+), 200 deletions(-) diff --git a/src/Numerics.Tests/IntegralTransformsTests/FourierTest.cs b/src/Numerics.Tests/IntegralTransformsTests/FourierTest.cs index d9305b52..afaf3f09 100644 --- a/src/Numerics.Tests/IntegralTransformsTests/FourierTest.cs +++ b/src/Numerics.Tests/IntegralTransformsTests/FourierTest.cs @@ -43,7 +43,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests [Test] public void ReferenceDftTransformsRealSineCorrectly32() { - var samples = Generate.PeriodicMap(16, w => new Complex32((float)Math.Sin(w), 0), 16, 1.0, Constants.Pi2); + var samples = Generate.PeriodicMap(16, w => new Complex32((float)Math.Sin(w), 0), 16, 1.0, Constants.Pi2).ToArray(); // real-odd transforms to imaginary odd ReferenceDiscreteFourierTransform.Forward(samples, FourierOptions.Matlab); @@ -75,7 +75,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests [Test] public void ReferenceDftTransformsRealSineCorrectly64() { - var samples = Generate.PeriodicMap(16, w => new Complex(Math.Sin(w), 0), 16, 1.0, Constants.Pi2); + var samples = Generate.PeriodicMap(16, w => new Complex(Math.Sin(w), 0), 16, 1.0, Constants.Pi2).ToArray(); // real-odd transforms to imaginary odd ReferenceDiscreteFourierTransform.Forward(samples, FourierOptions.Matlab); @@ -107,7 +107,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests [Test] public void FourierDefaultTransformsRealSineCorrectly32() { - var samples = Generate.PeriodicMap(16, w => new Complex32((float)Math.Sin(w), 0), 16, 1.0, Constants.Pi2); + var samples = Generate.PeriodicMap(16, w => new Complex32((float)Math.Sin(w), 0), 16, 1.0, Constants.Pi2).ToArray(); // real-odd transforms to imaginary odd Fourier.Forward(samples, FourierOptions.Matlab); @@ -139,7 +139,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests [Test] public void FourierDefaultTransformsRealSineCorrectly64() { - var samples = Generate.PeriodicMap(16, w => new Complex(Math.Sin(w), 0), 16, 1.0, Constants.Pi2); + var samples = Generate.PeriodicMap(16, w => new Complex(Math.Sin(w), 0), 16, 1.0, Constants.Pi2).ToArray(); // real-odd transforms to imaginary odd Fourier.Forward(samples, FourierOptions.Matlab); diff --git a/src/Numerics.Tests/IntegralTransformsTests/InverseTransformTest.cs b/src/Numerics.Tests/IntegralTransformsTests/InverseTransformTest.cs index f9367f80..8f518a52 100644 --- a/src/Numerics.Tests/IntegralTransformsTests/InverseTransformTest.cs +++ b/src/Numerics.Tests/IntegralTransformsTests/InverseTransformTest.cs @@ -58,13 +58,13 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests { var samples = Generate.RandomComplex32(0x80, GetUniform(1)); var work = new Complex32[samples.Length]; - samples.CopyTo(work, 0); + samples.CopyTo(work); ReferenceDiscreteFourierTransform.Forward(work, options); - Assert.IsFalse(work.ListAlmostEqual(samples, 6)); + Assert.IsFalse(work.ListAlmostEqual(samples.ToArray(), 6)); ReferenceDiscreteFourierTransform.Inverse(work, options); - AssertHelpers.AlmostEqual(samples, work, 11); + AssertHelpers.AlmostEqual(samples.ToArray(), work, 11); } /// @@ -75,7 +75,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests [TestCase(FourierOptions.Matlab)] public void ReferenceDftIsReversible64(FourierOptions options) { - var samples = Generate.RandomComplex(0x80, GetUniform(1)); + var samples = Generate.RandomComplex(0x80, GetUniform(1)).ToArray(); var work = new Complex[samples.Length]; samples.CopyTo(work, 0); @@ -94,7 +94,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests [TestCase(FourierOptions.Matlab)] public void FourierRadix2IsReversible32(FourierOptions options) { - var samples = Generate.RandomComplex32(0x8000, GetUniform(1)); + var samples = Generate.RandomComplex32(0x8000, GetUniform(1)).ToArray(); var work = new Complex32[samples.Length]; samples.CopyTo(work, 0); @@ -113,7 +113,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests [TestCase(FourierOptions.Matlab)] public void FourierRadix2IsReversible64(FourierOptions options) { - var samples = Generate.RandomComplex(0x8000, GetUniform(1)); + var samples = Generate.RandomComplex(0x8000, GetUniform(1)).ToArray(); var work = new Complex[samples.Length]; samples.CopyTo(work, 0); @@ -132,7 +132,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests [TestCase(FourierOptions.Matlab)] public void FourierBluesteinIsReversible32(FourierOptions options) { - var samples = Generate.RandomComplex32(0x7FFF, GetUniform(1)); + var samples = Generate.RandomComplex32(0x7FFF, GetUniform(1)).ToArray(); var work = new Complex32[samples.Length]; samples.CopyTo(work, 0); @@ -151,7 +151,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests [TestCase(FourierOptions.Matlab)] public void FourierBluesteinIsReversible64(FourierOptions options) { - var samples = Generate.RandomComplex(0x7FFF, GetUniform(1)); + var samples = Generate.RandomComplex(0x7FFF, GetUniform(1)).ToArray(); var work = new Complex[samples.Length]; samples.CopyTo(work, 0); diff --git a/src/Numerics.Tests/IntegralTransformsTests/MatchingReferenceTransformTest.cs b/src/Numerics.Tests/IntegralTransformsTests/MatchingReferenceTransformTest.cs index f2e35df2..70bbb8b7 100644 --- a/src/Numerics.Tests/IntegralTransformsTests/MatchingReferenceTransformTest.cs +++ b/src/Numerics.Tests/IntegralTransformsTests/MatchingReferenceTransformTest.cs @@ -51,72 +51,72 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests } static void Verify( - Complex32[] samples, + Memory samples, int maximumErrorDecimalPlaces, FourierOptions options, - Action expected, - Action actual) + Action, FourierOptions> expected, + Action, FourierOptions> actual) { var spectrumExpected = new Complex32[samples.Length]; - samples.CopyTo(spectrumExpected, 0); + samples.CopyTo(spectrumExpected); expected(spectrumExpected, options); var spectrumActual = new Complex32[samples.Length]; - samples.CopyTo(spectrumActual, 0); + samples.CopyTo(spectrumActual); actual(spectrumActual, options); AssertHelpers.AlmostEqual(spectrumExpected, spectrumActual, maximumErrorDecimalPlaces); } static void Verify( - Complex[] samples, + Memory samples, int maximumErrorDecimalPlaces, FourierOptions options, - Action expected, - Action actual) + Action, FourierOptions> expected, + Action, FourierOptions> actual) { var spectrumExpected = new Complex[samples.Length]; - samples.CopyTo(spectrumExpected, 0); + samples.CopyTo(spectrumExpected); expected(spectrumExpected, options); var spectrumActual = new Complex[samples.Length]; - samples.CopyTo(spectrumActual, 0); + samples.CopyTo(spectrumActual); actual(spectrumActual, options); AssertHelpers.AlmostEqual(spectrumExpected, spectrumActual, maximumErrorDecimalPlaces); } static void Verify( - Complex32[] samples, + Memory samples, int maximumErrorDecimalPlaces, FourierTransformScaling options, - Action expected, - Action actual) + Action, FourierTransformScaling> expected, + Action, FourierTransformScaling> actual) { var spectrumExpected = new Complex32[samples.Length]; - samples.CopyTo(spectrumExpected, 0); + samples.CopyTo(spectrumExpected); expected(spectrumExpected, options); var spectrumActual = new Complex32[samples.Length]; - samples.CopyTo(spectrumActual, 0); + samples.CopyTo(spectrumActual); actual(spectrumActual, options); AssertHelpers.AlmostEqual(spectrumExpected, spectrumActual, maximumErrorDecimalPlaces); } static void Verify( - Complex[] samples, + Memory samples, int maximumErrorDecimalPlaces, FourierTransformScaling options, - Action expected, - Action actual) + Action, FourierTransformScaling> expected, + Action, FourierTransformScaling> actual) { var spectrumExpected = new Complex[samples.Length]; - samples.CopyTo(spectrumExpected, 0); + samples.CopyTo(spectrumExpected); expected(spectrumExpected, options); var spectrumActual = new Complex[samples.Length]; - samples.CopyTo(spectrumActual, 0); + samples.CopyTo(spectrumActual); actual(spectrumActual, options); AssertHelpers.AlmostEqual(spectrumExpected, spectrumActual, maximumErrorDecimalPlaces); diff --git a/src/Numerics.Tests/IntegralTransformsTests/ParsevalTheoremTest.cs b/src/Numerics.Tests/IntegralTransformsTests/ParsevalTheoremTest.cs index 09231a04..29e6c5eb 100644 --- a/src/Numerics.Tests/IntegralTransformsTests/ParsevalTheoremTest.cs +++ b/src/Numerics.Tests/IntegralTransformsTests/ParsevalTheoremTest.cs @@ -58,7 +58,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests [TestCase(0x7FF)] public void ReferenceDftSatisfiesParsevalsTheorem32(int count) { - var samples = Generate.RandomComplex32(count, GetUniform(1)); + var samples = Generate.RandomComplex32(count, GetUniform(1)).ToArray(); var timeSpaceEnergy = (from s in samples select s.MagnitudeSquared()).Mean(); var spectrum = new Complex32[samples.Length]; @@ -77,7 +77,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests [TestCase(0x7FF)] public void ReferenceDftSatisfiesParsevalsTheorem64(int count) { - var samples = Generate.RandomComplex(count, GetUniform(1)); + var samples = Generate.RandomComplex(count, GetUniform(1)).ToArray(); var timeSpaceEnergy = (from s in samples select s.MagnitudeSquared()).Mean(); var spectrum = new Complex[samples.Length]; @@ -96,7 +96,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests [TestCase(0x7FF)] public void FourierDefaultTransformSatisfiesParsevalsTheorem32(int count) { - var samples = Generate.RandomComplex32(count, GetUniform(1)); + var samples = Generate.RandomComplex32(count, GetUniform(1)).ToArray(); var timeSpaceEnergy = (from s in samples select s.MagnitudeSquared()).Mean(); var spectrum = new Complex32[samples.Length]; @@ -115,7 +115,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests [TestCase(0x7FF)] public void FourierDefaultTransformSatisfiesParsevalsTheorem64(int count) { - var samples = Generate.RandomComplex(count, GetUniform(1)); + var samples = Generate.RandomComplex(count, GetUniform(1)).ToArray(); var timeSpaceEnergy = (from s in samples select s.MagnitudeSquared()).Mean(); var spectrum = new Complex[samples.Length]; diff --git a/src/Numerics.Tests/IntegralTransformsTests/ReferenceDiscreteFourierTransform.cs b/src/Numerics.Tests/IntegralTransformsTests/ReferenceDiscreteFourierTransform.cs index b3d14102..00750f8f 100644 --- a/src/Numerics.Tests/IntegralTransformsTests/ReferenceDiscreteFourierTransform.cs +++ b/src/Numerics.Tests/IntegralTransformsTests/ReferenceDiscreteFourierTransform.cs @@ -10,7 +10,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests /// /// Naive forward DFT, useful e.g. to verify faster algorithms. /// - public static void Forward(Complex32[] samples, FourierOptions options = FourierOptions.Default) + public static void Forward(Memory samples, FourierOptions options = FourierOptions.Default) { Naive(samples, SignByOptions(options)); ForwardScaleByOptions(options, samples); @@ -19,7 +19,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests /// /// Naive forward DFT, useful e.g. to verify faster algorithms. /// - public static void Forward(Complex[] samples, FourierOptions options = FourierOptions.Default) + public static void Forward(Memory samples, FourierOptions options = FourierOptions.Default) { Naive(samples, SignByOptions(options)); ForwardScaleByOptions(options, samples); @@ -28,7 +28,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests /// /// Naive inverse DFT, useful e.g. to verify faster algorithms. /// - public static void Inverse(Complex32[] spectrum, FourierOptions options = FourierOptions.Default) + public static void Inverse(Memory spectrum, FourierOptions options = FourierOptions.Default) { Naive(spectrum, -SignByOptions(options)); InverseScaleByOptions(options, spectrum); @@ -37,7 +37,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests /// /// Naive inverse DFT, useful e.g. to verify faster algorithms. /// - public static void Inverse(Complex[] spectrum, FourierOptions options = FourierOptions.Default) + public static void Inverse(Memory spectrum, FourierOptions options = FourierOptions.Default) { Naive(spectrum, -SignByOptions(options)); InverseScaleByOptions(options, spectrum); @@ -49,10 +49,10 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests /// Time-space sample vector. /// Fourier series exponent sign. /// Corresponding frequency-space vector. - static void Naive(Complex32[] samples, int exponentSign) + static void Naive(Memory samples, int exponentSign) { var w0 = exponentSign * Constants.Pi2 / samples.Length; - var spectrum = new Complex32[samples.Length]; + Memory spectrum = new Complex32[samples.Length]; CommonParallel.For(0, samples.Length, (u, v) => { @@ -63,14 +63,14 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests for (var n = 0; n < samples.Length; n++) { var w = n * wk; - sum += samples[n] * new Complex32((float)Math.Cos(w), (float)Math.Sin(w)); + sum += samples.Span[n] * new Complex32((float)Math.Cos(w), (float)Math.Sin(w)); } - spectrum[i] = sum; + spectrum.Span[i] = sum; } }); - spectrum.Copy(samples); + spectrum.CopyTo(samples); } /// @@ -79,10 +79,10 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests /// Time-space sample vector. /// Fourier series exponent sign. /// Corresponding frequency-space vector. - static void Naive(Complex[] samples, int exponentSign) + static void Naive(Memory samples, int exponentSign) { var w0 = exponentSign * Constants.Pi2 / samples.Length; - var spectrum = new Complex[samples.Length]; + Memory spectrum = new Complex[samples.Length]; CommonParallel.For(0, samples.Length, (u, v) => { @@ -93,14 +93,14 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests for (var n = 0; n < samples.Length; n++) { var w = n * wk; - sum += samples[n] * new Complex(Math.Cos(w), Math.Sin(w)); + sum += samples.Span[n] * new Complex(Math.Cos(w), Math.Sin(w)); } - spectrum[i] = sum; + spectrum.Span[i] = sum; } }); - spectrum.Copy(samples); + spectrum.CopyTo(samples); } /// @@ -119,7 +119,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests /// /// Fourier Transform Convention Options. /// Sample Vector. - static void ForwardScaleByOptions(FourierOptions options, Complex32[] samples) + static void ForwardScaleByOptions(FourierOptions options, Memory samples) { if ((options & FourierOptions.NoScaling) == FourierOptions.NoScaling || (options & FourierOptions.AsymmetricScaling) == FourierOptions.AsymmetricScaling) @@ -130,7 +130,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests var scalingFactor = (float)Math.Sqrt(1.0 / samples.Length); for (int i = 0; i < samples.Length; i++) { - samples[i] *= scalingFactor; + samples.Span[i] *= scalingFactor; } } @@ -139,7 +139,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests /// /// Fourier Transform Convention Options. /// Sample Vector. - static void ForwardScaleByOptions(FourierOptions options, Complex[] samples) + static void ForwardScaleByOptions(FourierOptions options, Memory samples) { if ((options & FourierOptions.NoScaling) == FourierOptions.NoScaling || (options & FourierOptions.AsymmetricScaling) == FourierOptions.AsymmetricScaling) @@ -150,7 +150,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests var scalingFactor = Math.Sqrt(1.0 / samples.Length); for (int i = 0; i < samples.Length; i++) { - samples[i] *= scalingFactor; + samples.Span[i] *= scalingFactor; } } @@ -159,7 +159,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests /// /// Fourier Transform Convention Options. /// Sample Vector. - static void InverseScaleByOptions(FourierOptions options, Complex32[] samples) + static void InverseScaleByOptions(FourierOptions options, Memory samples) { if ((options & FourierOptions.NoScaling) == FourierOptions.NoScaling) { @@ -174,7 +174,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests for (int i = 0; i < samples.Length; i++) { - samples[i] *= scalingFactor; + samples.Span[i] *= scalingFactor; } } @@ -183,7 +183,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests /// /// Fourier Transform Convention Options. /// Sample Vector. - static void InverseScaleByOptions(FourierOptions options, Complex[] samples) + static void InverseScaleByOptions(FourierOptions options, Memory samples) { if ((options & FourierOptions.NoScaling) == FourierOptions.NoScaling) { @@ -198,7 +198,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests for (int i = 0; i < samples.Length; i++) { - samples[i] *= scalingFactor; + samples.Span[i] *= scalingFactor; } } } diff --git a/src/Numerics.Tests/Providers/FourierTransform/FourierTransformProviderTests.cs b/src/Numerics.Tests/Providers/FourierTransform/FourierTransformProviderTests.cs index 20e97095..5016eee8 100644 --- a/src/Numerics.Tests/Providers/FourierTransform/FourierTransformProviderTests.cs +++ b/src/Numerics.Tests/Providers/FourierTransform/FourierTransformProviderTests.cs @@ -45,7 +45,7 @@ namespace MathNet.Numerics.UnitTests.Providers.FourierTransform [Test] public void ProviderSurvivesFreeResources() { - var samples = Generate.PeriodicMap(16, w => new Complex(Math.Sin(w), 0), 16, 1.0, Constants.Pi2); + var samples = Generate.PeriodicMap(16, w => new Complex(Math.Sin(w), 0), 16, 1.0, Constants.Pi2).ToArray(); var spectrum1 = new Complex[samples.Length]; samples.Copy(spectrum1); @@ -66,7 +66,7 @@ namespace MathNet.Numerics.UnitTests.Providers.FourierTransform [Test] public void ForwardInplaceRealSine() { - var samples = Generate.PeriodicMap(16, w => new Complex(Math.Sin(w), 0), 16, 1.0, Constants.Pi2); + var samples = Generate.PeriodicMap(16, w => new Complex(Math.Sin(w), 0), 16, 1.0, Constants.Pi2).ToArray(); var spectrum = new Complex[samples.Length]; // real-odd transforms to imaginary odd @@ -101,7 +101,7 @@ namespace MathNet.Numerics.UnitTests.Providers.FourierTransform [TestCase(0x7FF)] public void ForwardInplaceParsevalTheorem(int count) { - var samples = Generate.RandomComplex(count, GetUniform(1)); + var samples = Generate.RandomComplex(count, GetUniform(1)).ToArray(); var timeSpaceEnergy = Generate.Map(samples, s => s.MagnitudeSquared()).Mean(); FourierTransformControl.Provider.Forward(samples, FourierTransformScaling.SymmetricScaling); @@ -114,6 +114,5 @@ namespace MathNet.Numerics.UnitTests.Providers.FourierTransform { return new ContinuousUniform(-1, 1, new System.Random(seed)); } - } } diff --git a/src/Numerics.Tests/Providers/LinearAlgebra/Double/LinearAlgebraProviderTests.cs b/src/Numerics.Tests/Providers/LinearAlgebra/Double/LinearAlgebraProviderTests.cs index 623de83c..930dfe95 100644 --- a/src/Numerics.Tests/Providers/LinearAlgebra/Double/LinearAlgebraProviderTests.cs +++ b/src/Numerics.Tests/Providers/LinearAlgebra/Double/LinearAlgebraProviderTests.cs @@ -75,7 +75,7 @@ namespace MathNet.Numerics.UnitTests.Providers.LinearAlgebra.Double [Test] public void ProviderSurvivesFreeResources() { - var samples = Generate.PeriodicMap(16, w => Math.Sin(w), 16, 1.0, Constants.Pi2); + var samples = Generate.PeriodicMap(16, w => Math.Sin(w), 16, 1.0, Constants.Pi2).ToArray(); var result1 = new double[samples.Length]; LinearAlgebraControl.Provider.ScaleArray(2.5, samples, result1); diff --git a/src/Numerics/Generate.cs b/src/Numerics/Generate.cs index 570eafd4..619bd905 100644 --- a/src/Numerics/Generate.cs +++ b/src/Numerics/Generate.cs @@ -367,7 +367,7 @@ namespace MathNet.Numerics /// 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) + public static Memory PeriodicMap(int length, Func map, double samplingRate, double frequency, double amplitude = 1.0, double phase = 0.0, int delay = 0) { if (length < 0) { @@ -511,7 +511,7 @@ namespace MathNet.Numerics /// 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) + public static Memory 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); @@ -540,7 +540,7 @@ namespace MathNet.Numerics /// 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) + public static Memory Triangle(int length, int raiseDuration, int fallDuration, double lowValue, double highValue, int delay = 0) { var duration = raiseDuration + fallDuration; var height = highValue - lowValue; @@ -574,7 +574,7 @@ namespace MathNet.Numerics /// Lowest sample value. /// Highest sample value. /// Optional delay. - public static double[] Sawtooth(int length, int period, double lowValue, double highValue, int delay = 0) + public static Memory 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); @@ -1041,7 +1041,7 @@ namespace MathNet.Numerics /// /// Create random samples. /// - public static Complex[] RandomComplex(int length, IContinuousDistribution distribution) + public static Memory RandomComplex(int length, IContinuousDistribution distribution) { return RandomMap2(length, distribution, (r, i) => new Complex(r, i)); } @@ -1057,7 +1057,7 @@ namespace MathNet.Numerics /// /// Create random samples. /// - public static Complex32[] RandomComplex32(int length, IContinuousDistribution distribution) + public static Memory RandomComplex32(int length, IContinuousDistribution distribution) { return RandomMap2(length, distribution, (r, i) => new Complex32((float)r, (float)i)); } diff --git a/src/Numerics/IntegralTransforms/Fourier.cs b/src/Numerics/IntegralTransforms/Fourier.cs index f10785d1..26325cd5 100644 --- a/src/Numerics/IntegralTransforms/Fourier.cs +++ b/src/Numerics/IntegralTransforms/Fourier.cs @@ -44,7 +44,7 @@ namespace MathNet.Numerics.IntegralTransforms /// 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(Complex32[] samples) + public static void Forward(Memory samples) { FourierTransformControl.Provider.Forward(samples, FourierTransformScaling.SymmetricScaling); } @@ -53,7 +53,7 @@ namespace MathNet.Numerics.IntegralTransforms /// 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) + public static void Forward(Memory samples) { FourierTransformControl.Provider.Forward(samples, FourierTransformScaling.SymmetricScaling); } @@ -63,7 +63,7 @@ namespace MathNet.Numerics.IntegralTransforms /// /// Sample vector, where the FFT is evaluated in place. /// Fourier Transform Convention Options. - public static void Forward(Complex32[] samples, FourierOptions options) + public static void Forward(Memory samples, FourierOptions options) { switch (options) { @@ -89,7 +89,7 @@ namespace MathNet.Numerics.IntegralTransforms /// /// Sample vector, where the FFT is evaluated in place. /// Fourier Transform Convention Options. - public static void Forward(Complex[] samples, FourierOptions options) + public static void Forward(Memory samples, FourierOptions options) { switch (options) { @@ -116,7 +116,7 @@ namespace MathNet.Numerics.IntegralTransforms /// Real part of the sample vector, where the FFT is evaluated in place. /// Imaginary part of the sample vector, where the FFT is evaluated in place. /// Fourier Transform Convention Options. - public static void Forward(float[] real, float[] imaginary, FourierOptions options = FourierOptions.Default) + public static void Forward(Span real, Span imaginary, FourierOptions options = FourierOptions.Default) { if (real.Length != imaginary.Length) { @@ -147,7 +147,7 @@ namespace MathNet.Numerics.IntegralTransforms /// Real part of the sample vector, where the FFT is evaluated in place. /// Imaginary part of the sample vector, where the FFT is evaluated in place. /// Fourier Transform Convention Options. - public static void Forward(double[] real, double[] imaginary, FourierOptions options = FourierOptions.Default) + public static void Forward(Span real, Span imaginary, FourierOptions options = FourierOptions.Default) { if (real.Length != imaginary.Length) { @@ -181,7 +181,7 @@ namespace MathNet.Numerics.IntegralTransforms /// Data array of length N+2 (if N is even) or N+1 (if N is odd). /// The number of samples. /// Fourier Transform Convention Options. - public static void ForwardReal(float[] data, int n, FourierOptions options = FourierOptions.Default) + public static void ForwardReal(Span data, int n, FourierOptions options = FourierOptions.Default) { int length = n.IsEven() ? n + 2 : n + 1; if (data.Length < length) @@ -215,7 +215,7 @@ namespace MathNet.Numerics.IntegralTransforms /// Data array of length N+2 (if N is even) or N+1 (if N is odd). /// The number of samples. /// Fourier Transform Convention Options. - public static void ForwardReal(double[] data, int n, FourierOptions options = FourierOptions.Default) + public static void ForwardReal(Span data, int n, FourierOptions options = FourierOptions.Default) { int length = n.IsEven() ? n + 2 : n + 1; if (data.Length < length) @@ -249,7 +249,7 @@ namespace MathNet.Numerics.IntegralTransforms /// For example, with two dimensions "rows" and "columns" the samples are assumed to be organized row by row. /// /// Fourier Transform Convention Options. - public static void ForwardMultiDim(Complex32[] samples, int[] dimensions, FourierOptions options = FourierOptions.Default) + public static void ForwardMultiDim(Span samples, Span dimensions, FourierOptions options = FourierOptions.Default) { switch (options) { @@ -279,7 +279,7 @@ namespace MathNet.Numerics.IntegralTransforms /// For example, with two dimensions "rows" and "columns" the samples are assumed to be organized row by row. /// /// Fourier Transform Convention Options. - public static void ForwardMultiDim(Complex[] samples, int[] dimensions, FourierOptions options = FourierOptions.Default) + public static void ForwardMultiDim(Span samples, Span dimensions, FourierOptions options = FourierOptions.Default) { switch (options) { @@ -308,7 +308,7 @@ namespace MathNet.Numerics.IntegralTransforms /// The number of columns. /// Data available organized column by column instead of row by row can be processed directly by swapping the rows and columns arguments. /// Fourier Transform Convention Options. - public static void Forward2D(Complex32[] samplesRowWise, int rows, int columns, FourierOptions options = FourierOptions.Default) + public static void Forward2D(Span samplesRowWise, int rows, int columns, FourierOptions options = FourierOptions.Default) { ForwardMultiDim(samplesRowWise, new[] { rows, columns }, options); } @@ -321,7 +321,7 @@ namespace MathNet.Numerics.IntegralTransforms /// The number of columns. /// Data available organized column by column instead of row by row can be processed directly by swapping the rows and columns arguments. /// Fourier Transform Convention Options. - public static void Forward2D(Complex[] samplesRowWise, int rows, int columns, FourierOptions options = FourierOptions.Default) + public static void Forward2D(Span samplesRowWise, int rows, int columns, FourierOptions options = FourierOptions.Default) { ForwardMultiDim(samplesRowWise, new[] { rows, columns }, options); } @@ -386,7 +386,7 @@ namespace MathNet.Numerics.IntegralTransforms /// Applies the inverse Fast Fourier Transform (iFFT) to arbitrary-length sample vectors. /// /// Spectrum data, where the iFFT is evaluated in place. - public static void Inverse(Complex32[] spectrum) + public static void Inverse(Memory spectrum) { FourierTransformControl.Provider.Backward(spectrum, FourierTransformScaling.SymmetricScaling); } @@ -395,7 +395,7 @@ namespace MathNet.Numerics.IntegralTransforms /// Applies the inverse Fast Fourier Transform (iFFT) to arbitrary-length sample vectors. /// /// Spectrum data, where the iFFT is evaluated in place. - public static void Inverse(Complex[] spectrum) + public static void Inverse(Memory spectrum) { FourierTransformControl.Provider.Backward(spectrum, FourierTransformScaling.SymmetricScaling); } @@ -405,7 +405,7 @@ namespace MathNet.Numerics.IntegralTransforms /// /// Spectrum data, where the iFFT is evaluated in place. /// Fourier Transform Convention Options. - public static void Inverse(Complex32[] spectrum, FourierOptions options) + public static void Inverse(Memory spectrum, FourierOptions options) { switch (options) { @@ -435,7 +435,7 @@ namespace MathNet.Numerics.IntegralTransforms /// /// Spectrum data, where the iFFT is evaluated in place. /// Fourier Transform Convention Options. - public static void Inverse(Complex[] spectrum, FourierOptions options) + public static void Inverse(Memory spectrum, FourierOptions options) { switch (options) { @@ -466,7 +466,7 @@ namespace MathNet.Numerics.IntegralTransforms /// Real part of the sample vector, where the iFFT is evaluated in place. /// Imaginary part of the sample vector, where the iFFT is evaluated in place. /// Fourier Transform Convention Options. - public static void Inverse(float[] real, float[] imaginary, FourierOptions options = FourierOptions.Default) + public static void Inverse(Memory real, Memory imaginary, FourierOptions options = FourierOptions.Default) { if (real.Length != imaginary.Length) { @@ -479,15 +479,15 @@ namespace MathNet.Numerics.IntegralTransforms Complex32[] data = new Complex32[real.Length]; for (int i = 0; i < data.Length; i++) { - data[i] = new Complex32(real[i], imaginary[i]); + data[i] = new Complex32(real.Span[i], imaginary.Span[i]); } Inverse(data, options); for (int i = 0; i < data.Length; i++) { - real[i] = data[i].Real; - imaginary[i] = data[i].Imaginary; + real.Span[i] = data[i].Real; + imaginary.Span[i] = data[i].Imaginary; } } @@ -497,7 +497,7 @@ namespace MathNet.Numerics.IntegralTransforms /// Real part of the sample vector, where the iFFT is evaluated in place. /// Imaginary part of the sample vector, where the iFFT is evaluated in place. /// Fourier Transform Convention Options. - public static void Inverse(double[] real, double[] imaginary, FourierOptions options = FourierOptions.Default) + public static void Inverse(Memory real, Memory imaginary, FourierOptions options = FourierOptions.Default) { if (real.Length != imaginary.Length) { @@ -510,15 +510,15 @@ namespace MathNet.Numerics.IntegralTransforms Complex[] data = new Complex[real.Length]; for (int i = 0; i < data.Length; i++) { - data[i] = new Complex(real[i], imaginary[i]); + data[i] = new Complex(real.Span[i], imaginary.Span[i]); } Inverse(data, options); for (int i = 0; i < data.Length; i++) { - real[i] = data[i].Real; - imaginary[i] = data[i].Imaginary; + real.Span[i] = data[i].Real; + imaginary.Span[i] = data[i].Imaginary; } } @@ -531,7 +531,7 @@ namespace MathNet.Numerics.IntegralTransforms /// Data array of length N+2 (if N is even) or N+1 (if N is odd). /// The number of samples. /// Fourier Transform Convention Options. - public static void InverseReal(float[] data, int n, FourierOptions options = FourierOptions.Default) + public static void InverseReal(Memory data, int n, FourierOptions options = FourierOptions.Default) { int length = n.IsEven() ? n + 2 : n + 1; if (data.Length < length) @@ -547,13 +547,13 @@ namespace MathNet.Numerics.IntegralTransforms switch (options) { case FourierOptions.NoScaling: - FourierTransformControl.Provider.BackwardReal(data, n, FourierTransformScaling.NoScaling); + FourierTransformControl.Provider.BackwardReal(data.Span, n, FourierTransformScaling.NoScaling); break; case FourierOptions.AsymmetricScaling: - FourierTransformControl.Provider.BackwardReal(data, n, FourierTransformScaling.BackwardScaling); + FourierTransformControl.Provider.BackwardReal(data.Span, n, FourierTransformScaling.BackwardScaling); break; default: - FourierTransformControl.Provider.BackwardReal(data, n, FourierTransformScaling.SymmetricScaling); + FourierTransformControl.Provider.BackwardReal(data.Span, n, FourierTransformScaling.SymmetricScaling); break; } } @@ -567,7 +567,7 @@ namespace MathNet.Numerics.IntegralTransforms /// Data array of length N+2 (if N is even) or N+1 (if N is odd). /// The number of samples. /// Fourier Transform Convention Options. - public static void InverseReal(double[] data, int n, FourierOptions options = FourierOptions.Default) + public static void InverseReal(Memory data, int n, FourierOptions options = FourierOptions.Default) { int length = n.IsEven() ? n + 2 : n + 1; if (data.Length < length) @@ -583,13 +583,13 @@ namespace MathNet.Numerics.IntegralTransforms switch (options) { case FourierOptions.NoScaling: - FourierTransformControl.Provider.BackwardReal(data, n, FourierTransformScaling.NoScaling); + FourierTransformControl.Provider.BackwardReal(data.Span, n, FourierTransformScaling.NoScaling); break; case FourierOptions.AsymmetricScaling: - FourierTransformControl.Provider.BackwardReal(data, n, FourierTransformScaling.BackwardScaling); + FourierTransformControl.Provider.BackwardReal(data.Span, n, FourierTransformScaling.BackwardScaling); break; default: - FourierTransformControl.Provider.BackwardReal(data, n, FourierTransformScaling.SymmetricScaling); + FourierTransformControl.Provider.BackwardReal(data.Span, n, FourierTransformScaling.SymmetricScaling); break; } } @@ -603,7 +603,7 @@ namespace MathNet.Numerics.IntegralTransforms /// For example, with two dimensions "rows" and "columns" the samples are assumed to be organized row by row. /// /// Fourier Transform Convention Options. - public static void InverseMultiDim(Complex32[] spectrum, int[] dimensions, FourierOptions options = FourierOptions.Default) + public static void InverseMultiDim(Span spectrum, Span dimensions, FourierOptions options = FourierOptions.Default) { switch (options) { @@ -637,7 +637,7 @@ namespace MathNet.Numerics.IntegralTransforms /// For example, with two dimensions "rows" and "columns" the samples are assumed to be organized row by row. /// /// Fourier Transform Convention Options. - public static void InverseMultiDim(Complex[] spectrum, int[] dimensions, FourierOptions options = FourierOptions.Default) + public static void InverseMultiDim(Span spectrum, Span dimensions, FourierOptions options = FourierOptions.Default) { switch (options) { @@ -670,7 +670,7 @@ namespace MathNet.Numerics.IntegralTransforms /// The number of columns. /// Data available organized column by column instead of row by row can be processed directly by swapping the rows and columns arguments. /// Fourier Transform Convention Options. - public static void Inverse2D(Complex32[] spectrumRowWise, int rows, int columns, FourierOptions options = FourierOptions.Default) + public static void Inverse2D(Span spectrumRowWise, int rows, int columns, FourierOptions options = FourierOptions.Default) { InverseMultiDim(spectrumRowWise, new[] { rows, columns }, options); } @@ -683,7 +683,7 @@ namespace MathNet.Numerics.IntegralTransforms /// The number of columns. /// Data available organized column by column instead of row by row can be processed directly by swapping the rows and columns arguments. /// Fourier Transform Convention Options. - public static void Inverse2D(Complex[] spectrumRowWise, int rows, int columns, FourierOptions options = FourierOptions.Default) + public static void Inverse2D(Span spectrumRowWise, int rows, int columns, FourierOptions options = FourierOptions.Default) { InverseMultiDim(spectrumRowWise, new[] { rows, columns }, options); } @@ -753,9 +753,9 @@ namespace MathNet.Numerics.IntegralTransforms /// /// Number of samples. /// The sampling rate of the time-space data. - public static double[] FrequencyScale(int length, double sampleRate) + public static Span FrequencyScale(int length, double sampleRate) { - double[] scale = new double[length]; + Span scale = new double[length]; double f = 0, step = sampleRate / length; int secondHalf = (length >> 1) + 1; for (int i = 0; i < secondHalf; i++) diff --git a/src/Numerics/LinearAlgebra/Builder.cs b/src/Numerics/LinearAlgebra/Builder.cs index 3371f702..280ea674 100644 --- a/src/Numerics/LinearAlgebra/Builder.cs +++ b/src/Numerics/LinearAlgebra/Builder.cs @@ -198,7 +198,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex public override Matrix Random(int rows, int columns, IContinuousDistribution distribution) { - return Dense(rows, columns, Generate.RandomComplex(rows*columns, distribution)); + return Dense(rows, columns, Generate.RandomComplex(rows*columns, distribution).ToArray()); } public override IIterationStopCriterion[] IterativeSolverStopCriteria(int maxIterations = 1000) @@ -236,7 +236,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex public override Vector Random(int length, IContinuousDistribution distribution) { - return Dense(Generate.RandomComplex(length, distribution)); + return Dense(Generate.RandomComplex(length, distribution).ToArray()); } } } @@ -266,7 +266,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 public override Matrix Random(int rows, int columns, IContinuousDistribution distribution) { - return Dense(rows, columns, Generate.RandomComplex32(rows*columns, distribution)); + return Dense(rows, columns, Generate.RandomComplex32(rows*columns, distribution).ToArray()); } public override IIterationStopCriterion[] IterativeSolverStopCriteria(int maxIterations = 1000) @@ -304,7 +304,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 public override Vector Random(int length, IContinuousDistribution distribution) { - return Dense(Generate.RandomComplex32(length, distribution)); + return Dense(Generate.RandomComplex32(length, distribution).ToArray()); } } } diff --git a/src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs b/src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs index f4684392..20e8ff52 100644 --- a/src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs @@ -396,7 +396,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex /// public static DenseMatrix CreateRandom(int rows, int columns, IContinuousDistribution distribution) { - return new DenseMatrix(new DenseColumnMajorMatrixStorage(rows, columns, Generate.RandomComplex(rows*columns, distribution))); + return new DenseMatrix(new DenseColumnMajorMatrixStorage(rows, columns, Generate.RandomComplex(rows*columns, distribution).ToArray())); } /// diff --git a/src/Numerics/LinearAlgebra/Complex/DenseVector.cs b/src/Numerics/LinearAlgebra/Complex/DenseVector.cs index 16d3270a..be88364f 100644 --- a/src/Numerics/LinearAlgebra/Complex/DenseVector.cs +++ b/src/Numerics/LinearAlgebra/Complex/DenseVector.cs @@ -164,7 +164,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex /// public static DenseVector CreateRandom(int length, IContinuousDistribution distribution) { - var samples = Generate.RandomComplex(length, distribution); + var samples = Generate.RandomComplex(length, distribution).ToArray(); return new DenseVector(new DenseVectorStorage(length, samples)); } diff --git a/src/Numerics/LinearAlgebra/Complex/DiagonalMatrix.cs b/src/Numerics/LinearAlgebra/Complex/DiagonalMatrix.cs index 8fe960d5..f80b4032 100644 --- a/src/Numerics/LinearAlgebra/Complex/DiagonalMatrix.cs +++ b/src/Numerics/LinearAlgebra/Complex/DiagonalMatrix.cs @@ -190,7 +190,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex /// public static DiagonalMatrix CreateRandom(int rows, int columns, IContinuousDistribution distribution) { - return new DiagonalMatrix(new DiagonalMatrixStorage(rows, columns, Generate.RandomComplex(Math.Min(rows, columns), distribution))); + return new DiagonalMatrix(new DiagonalMatrixStorage(rows, columns, Generate.RandomComplex(Math.Min(rows, columns), distribution).ToArray())); } /// diff --git a/src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs b/src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs index 3d402371..dd38ea21 100644 --- a/src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs @@ -396,7 +396,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 /// public static DenseMatrix CreateRandom(int rows, int columns, IContinuousDistribution distribution) { - return new DenseMatrix(new DenseColumnMajorMatrixStorage(rows, columns, Generate.RandomComplex32(rows*columns, distribution))); + return new DenseMatrix(new DenseColumnMajorMatrixStorage(rows, columns, Generate.RandomComplex32(rows*columns, distribution).ToArray())); } /// diff --git a/src/Numerics/LinearAlgebra/Complex32/DenseVector.cs b/src/Numerics/LinearAlgebra/Complex32/DenseVector.cs index 8d24bd42..8252101c 100644 --- a/src/Numerics/LinearAlgebra/Complex32/DenseVector.cs +++ b/src/Numerics/LinearAlgebra/Complex32/DenseVector.cs @@ -164,7 +164,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 /// public static DenseVector CreateRandom(int length, IContinuousDistribution distribution) { - var samples = Generate.RandomComplex32(length, distribution); + var samples = Generate.RandomComplex32(length, distribution).ToArray(); return new DenseVector(new DenseVectorStorage(length, samples)); } diff --git a/src/Numerics/LinearAlgebra/Complex32/DiagonalMatrix.cs b/src/Numerics/LinearAlgebra/Complex32/DiagonalMatrix.cs index 9549ae80..ea6423fd 100644 --- a/src/Numerics/LinearAlgebra/Complex32/DiagonalMatrix.cs +++ b/src/Numerics/LinearAlgebra/Complex32/DiagonalMatrix.cs @@ -190,7 +190,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 /// public static DiagonalMatrix CreateRandom(int rows, int columns, IContinuousDistribution distribution) { - return new DiagonalMatrix(new DiagonalMatrixStorage(rows, columns, Generate.RandomComplex32(Math.Min(rows, columns), distribution))); + return new DiagonalMatrix(new DiagonalMatrixStorage(rows, columns, Generate.RandomComplex32(Math.Min(rows, columns), distribution).ToArray())); } /// diff --git a/src/Numerics/Numerics.csproj b/src/Numerics/Numerics.csproj index b03e2c82..93e6e113 100644 --- a/src/Numerics/Numerics.csproj +++ b/src/Numerics/Numerics.csproj @@ -49,6 +49,7 @@ Control.Describe now includes CPU architecture and family identifier if knowall runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/Numerics/Providers/FourierTransform/IFourierTransformProvider.cs b/src/Numerics/Providers/FourierTransform/IFourierTransformProvider.cs index dfe3791a..ea4ad819 100644 --- a/src/Numerics/Providers/FourierTransform/IFourierTransformProvider.cs +++ b/src/Numerics/Providers/FourierTransform/IFourierTransformProvider.cs @@ -27,6 +27,7 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using System; using Complex = System.Numerics.Complex; namespace MathNet.Numerics.Providers.FourierTransform @@ -58,19 +59,19 @@ namespace MathNet.Numerics.Providers.FourierTransform /// void FreeResources(); - void Forward(Complex32[] samples, FourierTransformScaling scaling); - void Forward(Complex[] samples, FourierTransformScaling scaling); - void Backward(Complex32[] spectrum, FourierTransformScaling scaling); - void Backward(Complex[] spectrum, FourierTransformScaling scaling); + void Forward(Memory samples, FourierTransformScaling scaling); + void Forward(Memory samples, FourierTransformScaling scaling); + void Backward(Memory spectrum, FourierTransformScaling scaling); + void Backward(Memory spectrum, FourierTransformScaling scaling); - void ForwardReal(float[] samples, int n, FourierTransformScaling scaling); - void ForwardReal(double[] samples, int n, FourierTransformScaling scaling); - void BackwardReal(float[] spectrum, int n, FourierTransformScaling scaling); - void BackwardReal(double[] spectrum, int n, FourierTransformScaling scaling); + void ForwardReal(Span samples, int n, FourierTransformScaling scaling); + void ForwardReal(Span samples, int n, FourierTransformScaling scaling); + void BackwardReal(Span spectrum, int n, FourierTransformScaling scaling); + void BackwardReal(Span spectrum, int n, FourierTransformScaling scaling); - void ForwardMultidim(Complex32[] samples, int[] dimensions, FourierTransformScaling scaling); - void ForwardMultidim(Complex[] samples, int[] dimensions, FourierTransformScaling scaling); - void BackwardMultidim(Complex32[] spectrum, int[] dimensions, FourierTransformScaling scaling); - void BackwardMultidim(Complex[] spectrum, int[] dimensions, FourierTransformScaling scaling); + void ForwardMultidim(Span samples, Span dimensions, FourierTransformScaling scaling); + void ForwardMultidim(Span samples, Span dimensions, FourierTransformScaling scaling); + void BackwardMultidim(Span spectrum, Span dimensions, FourierTransformScaling scaling); + void BackwardMultidim(Span spectrum, Span dimensions, FourierTransformScaling scaling); } } diff --git a/src/Numerics/Providers/FourierTransform/ManagedFourierTransformProvider.Bluestein.cs b/src/Numerics/Providers/FourierTransform/ManagedFourierTransformProvider.Bluestein.cs index 17efd697..47aaac71 100644 --- a/src/Numerics/Providers/FourierTransform/ManagedFourierTransformProvider.Bluestein.cs +++ b/src/Numerics/Providers/FourierTransform/ManagedFourierTransformProvider.Bluestein.cs @@ -45,7 +45,7 @@ namespace MathNet.Numerics.Providers.FourierTransform /// /// Number of samples. /// Bluestein sequence exp(I*Pi*k^2/N) - static Complex32[] BluesteinSequence32(int n) + static Memory BluesteinSequence32(int n) { double s = Constants.Pi / n; var sequence = new Complex32[n]; @@ -77,7 +77,7 @@ namespace MathNet.Numerics.Providers.FourierTransform /// /// Number of samples. /// Bluestein sequence exp(I*Pi*k^2/N) - static Complex[] BluesteinSequence(int n) + static Memory BluesteinSequence(int n) { double s = Constants.Pi / n; var sequence = new Complex[n]; @@ -108,10 +108,10 @@ namespace MathNet.Numerics.Providers.FourierTransform /// Convolution with the bluestein sequence (Parallel Version). /// /// Sample Vector. - static void BluesteinConvolutionParallel(Complex32[] samples) + static void BluesteinConvolutionParallel(Memory samples) { int n = samples.Length; - Complex32[] sequence = BluesteinSequence32(n); + Memory sequence = BluesteinSequence32(n); // Padding to power of two >= 2N–1 so we can apply Radix-2 FFT. int m = ((n << 1) - 1).CeilingToPowerOfTwo(); @@ -124,12 +124,12 @@ namespace MathNet.Numerics.Providers.FourierTransform // Build and transform padded sequence b_k = exp(I*Pi*k^2/N) for (int i = 0; i < n; i++) { - b[i] = sequence[i]; + b[i] = sequence.Span[i]; } for (int i = m - n + 1; i < b.Length; i++) { - b[i] = sequence[m - i]; + b[i] = sequence.Span[m - i]; } Radix2Forward(b); @@ -139,7 +139,7 @@ namespace MathNet.Numerics.Providers.FourierTransform // 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]; + a[i] = sequence.Span[i].Conjugate() * samples.Span[i]; } Radix2Forward(a); @@ -155,7 +155,7 @@ namespace MathNet.Numerics.Providers.FourierTransform var nbinv = 1.0f / m; for (int i = 0; i < samples.Length; i++) { - samples[i] = nbinv * sequence[i].Conjugate() * a[i]; + samples.Span[i] = nbinv * sequence.Span[i].Conjugate() * a[i]; } } @@ -163,10 +163,10 @@ namespace MathNet.Numerics.Providers.FourierTransform /// Convolution with the bluestein sequence (Parallel Version). /// /// Sample Vector. - static void BluesteinConvolutionParallel(Complex[] samples) + static void BluesteinConvolutionParallel(Memory samples) { int n = samples.Length; - Complex[] sequence = BluesteinSequence(n); + Memory sequence = BluesteinSequence(n); // Padding to power of two >= 2N–1 so we can apply Radix-2 FFT. int m = ((n << 1) - 1).CeilingToPowerOfTwo(); @@ -179,12 +179,12 @@ namespace MathNet.Numerics.Providers.FourierTransform // Build and transform padded sequence b_k = exp(I*Pi*k^2/N) for (int i = 0; i < n; i++) { - b[i] = sequence[i]; + b[i] = sequence.Span[i]; } for (int i = m - n + 1; i < b.Length; i++) { - b[i] = sequence[m - i]; + b[i] = sequence.Span[m - i]; } Radix2Forward(b); @@ -194,7 +194,7 @@ namespace MathNet.Numerics.Providers.FourierTransform // 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]; + a[i] = sequence.Span[i].Conjugate() * samples.Span[i]; } Radix2Forward(a); @@ -210,7 +210,7 @@ namespace MathNet.Numerics.Providers.FourierTransform var nbinv = 1.0 / m; for (int i = 0; i < samples.Length; i++) { - samples[i] = nbinv * sequence[i].Conjugate() * a[i]; + samples.Span[i] = nbinv * sequence.Span[i].Conjugate() * a[i]; } } @@ -218,7 +218,7 @@ namespace MathNet.Numerics.Providers.FourierTransform /// Swap the real and imaginary parts of each sample. /// /// Sample Vector. - static void SwapRealImaginary(Complex32[] samples) + static void SwapRealImaginary(Span samples) { for (int i = 0; i < samples.Length; i++) { @@ -230,7 +230,7 @@ namespace MathNet.Numerics.Providers.FourierTransform /// Swap the real and imaginary parts of each sample. /// /// Sample Vector. - static void SwapRealImaginary(Complex[] samples) + static void SwapRealImaginary(Span samples) { for (int i = 0; i < samples.Length; i++) { @@ -241,7 +241,7 @@ namespace MathNet.Numerics.Providers.FourierTransform /// /// Bluestein generic FFT for arbitrary sized sample vectors. /// - static void BluesteinForward(Complex[] samples) + static void BluesteinForward(Memory samples) { BluesteinConvolutionParallel(samples); } @@ -249,17 +249,17 @@ namespace MathNet.Numerics.Providers.FourierTransform /// /// Bluestein generic FFT for arbitrary sized sample vectors. /// - static void BluesteinInverse(Complex[] spectrum) + static void BluesteinInverse(Memory spectrum) { - SwapRealImaginary(spectrum); + SwapRealImaginary(spectrum.Span); BluesteinConvolutionParallel(spectrum); - SwapRealImaginary(spectrum); + SwapRealImaginary(spectrum.Span); } /// /// Bluestein generic FFT for arbitrary sized sample vectors. /// - static void BluesteinForward(Complex32[] samples) + static void BluesteinForward(Memory samples) { BluesteinConvolutionParallel(samples); } @@ -267,11 +267,11 @@ namespace MathNet.Numerics.Providers.FourierTransform /// /// Bluestein generic FFT for arbitrary sized sample vectors. /// - static void BluesteinInverse(Complex32[] spectrum) + static void BluesteinInverse(Memory spectrum) { - SwapRealImaginary(spectrum); + SwapRealImaginary(spectrum.Span); BluesteinConvolutionParallel(spectrum); - SwapRealImaginary(spectrum); + SwapRealImaginary(spectrum.Span); } } } diff --git a/src/Numerics/Providers/FourierTransform/ManagedFourierTransformProvider.Radix2.cs b/src/Numerics/Providers/FourierTransform/ManagedFourierTransformProvider.Radix2.cs index fe6c453f..05d4388d 100644 --- a/src/Numerics/Providers/FourierTransform/ManagedFourierTransformProvider.Radix2.cs +++ b/src/Numerics/Providers/FourierTransform/ManagedFourierTransformProvider.Radix2.cs @@ -40,7 +40,7 @@ namespace MathNet.Numerics.Providers.FourierTransform /// /// Sample type /// Sample vector - static void Radix2Reorder(T[] samples) + static void Radix2Reorder(Span samples) { var j = 0; for (var i = 0; i < samples.Length - 1; i++) @@ -73,7 +73,7 @@ namespace MathNet.Numerics.Providers.FourierTransform #if !NET40 [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif - static void Radix2Step(Complex32[] samples, int exponentSign, int levelSize, int k) + static void Radix2Step(Span samples, int exponentSign, int levelSize, int k) { // Twiddle Factor var exponent = (exponentSign * k) * Constants.Pi / levelSize; @@ -99,7 +99,7 @@ namespace MathNet.Numerics.Providers.FourierTransform #if !NET40 [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif - static void Radix2Step(Complex[] samples, int exponentSign, int levelSize, int k) + static void Radix2Step(Span samples, int exponentSign, int levelSize, int k) { // Twiddle Factor var exponent = (exponentSign * k) * Constants.Pi / levelSize; @@ -118,7 +118,7 @@ namespace MathNet.Numerics.Providers.FourierTransform /// /// Radix-2 generic FFT for power-of-two sized sample vectors. /// - static void Radix2Forward(Complex32[] data) + static void Radix2Forward(Span data) { Radix2Reorder(data); for (var levelSize = 1; levelSize < data.Length; levelSize *= 2) @@ -133,7 +133,7 @@ namespace MathNet.Numerics.Providers.FourierTransform /// /// Radix-2 generic FFT for power-of-two sized sample vectors. /// - static void Radix2Forward(Complex[] data) + static void Radix2Forward(Span data) { Radix2Reorder(data); for (var levelSize = 1; levelSize < data.Length; levelSize *= 2) @@ -148,7 +148,7 @@ namespace MathNet.Numerics.Providers.FourierTransform /// /// Radix-2 generic FFT for power-of-two sized sample vectors. /// - static void Radix2Inverse(Complex32[] data) + static void Radix2Inverse(Span data) { Radix2Reorder(data); for (var levelSize = 1; levelSize < data.Length; levelSize *= 2) @@ -163,7 +163,7 @@ namespace MathNet.Numerics.Providers.FourierTransform /// /// Radix-2 generic FFT for power-of-two sized sample vectors. /// - static void Radix2Inverse(Complex[] data) + static void Radix2Inverse(Span data) { Radix2Reorder(data); for (var levelSize = 1; levelSize < data.Length; levelSize *= 2) @@ -178,9 +178,9 @@ namespace MathNet.Numerics.Providers.FourierTransform /// /// Radix-2 generic FFT for power-of-two sample vectors (Parallel Version). /// - static void Radix2ForwardParallel(Complex32[] data) + static void Radix2ForwardParallel(Memory data) { - Radix2Reorder(data); + Radix2Reorder(data.Span); for (var levelSize = 1; levelSize < data.Length; levelSize *= 2) { var size = levelSize; @@ -189,7 +189,7 @@ namespace MathNet.Numerics.Providers.FourierTransform { for (int i = u; i < v; i++) { - Radix2Step(data, -1, size, i); + Radix2Step(data.Span, -1, size, i); } }); } @@ -198,9 +198,9 @@ namespace MathNet.Numerics.Providers.FourierTransform /// /// Radix-2 generic FFT for power-of-two sample vectors (Parallel Version). /// - static void Radix2ForwardParallel(Complex[] data) + static void Radix2ForwardParallel(Memory data) { - Radix2Reorder(data); + Radix2Reorder(data.Span); for (var levelSize = 1; levelSize < data.Length; levelSize *= 2) { var size = levelSize; @@ -209,7 +209,7 @@ namespace MathNet.Numerics.Providers.FourierTransform { for (int i = u; i < v; i++) { - Radix2Step(data, -1, size, i); + Radix2Step(data.Span, -1, size, i); } }); } @@ -218,9 +218,9 @@ namespace MathNet.Numerics.Providers.FourierTransform /// /// Radix-2 generic FFT for power-of-two sample vectors (Parallel Version). /// - static void Radix2InverseParallel(Complex32[] data) + static void Radix2InverseParallel(Memory data) { - Radix2Reorder(data); + Radix2Reorder(data.Span); for (var levelSize = 1; levelSize < data.Length; levelSize *= 2) { var size = levelSize; @@ -229,7 +229,7 @@ namespace MathNet.Numerics.Providers.FourierTransform { for (int i = u; i < v; i++) { - Radix2Step(data, 1, size, i); + Radix2Step(data.Span, 1, size, i); } }); } @@ -238,9 +238,9 @@ namespace MathNet.Numerics.Providers.FourierTransform /// /// Radix-2 generic FFT for power-of-two sample vectors (Parallel Version). /// - static void Radix2InverseParallel(Complex[] data) + static void Radix2InverseParallel(Memory data) { - Radix2Reorder(data); + Radix2Reorder(data.Span); for (var levelSize = 1; levelSize < data.Length; levelSize *= 2) { var size = levelSize; @@ -249,7 +249,7 @@ namespace MathNet.Numerics.Providers.FourierTransform { for (int i = u; i < v; i++) { - Radix2Step(data, 1, size, i); + Radix2Step(data.Span, 1, size, i); } }); } diff --git a/src/Numerics/Providers/FourierTransform/ManagedFourierTransformProvider.Scaling.cs b/src/Numerics/Providers/FourierTransform/ManagedFourierTransformProvider.Scaling.cs index f9d0673f..284dc3fb 100644 --- a/src/Numerics/Providers/FourierTransform/ManagedFourierTransformProvider.Scaling.cs +++ b/src/Numerics/Providers/FourierTransform/ManagedFourierTransformProvider.Scaling.cs @@ -39,7 +39,7 @@ namespace MathNet.Numerics.Providers.FourierTransform /// Fully rescale the FFT result. /// /// Sample Vector. - static void FullRescale(Complex32[] samples) + static void FullRescale(Span samples) { var scalingFactor = (float)1.0 / samples.Length; for (int i = 0; i < samples.Length; i++) @@ -52,7 +52,7 @@ namespace MathNet.Numerics.Providers.FourierTransform /// Fully rescale the FFT result. /// /// Sample Vector. - static void FullRescale(Complex[] samples) + static void FullRescale(Span samples) { var scalingFactor = 1.0 / samples.Length; for (int i = 0; i < samples.Length; i++) @@ -65,7 +65,7 @@ namespace MathNet.Numerics.Providers.FourierTransform /// Half rescale the FFT result (e.g. for symmetric transforms). /// /// Sample Vector. - static void HalfRescale(Complex32[] samples) + static void HalfRescale(Span samples) { var scalingFactor = (float)Math.Sqrt(1.0 / samples.Length); for (int i = 0; i < samples.Length; i++) @@ -78,7 +78,7 @@ namespace MathNet.Numerics.Providers.FourierTransform /// Fully rescale the FFT result (e.g. for symmetric transforms). /// /// Sample Vector. - static void HalfRescale(Complex[] samples) + static void HalfRescale(Span samples) { var scalingFactor = Math.Sqrt(1.0 / samples.Length); for (int i = 0; i < samples.Length; i++) diff --git a/src/Numerics/Providers/FourierTransform/ManagedFourierTransformProvider.cs b/src/Numerics/Providers/FourierTransform/ManagedFourierTransformProvider.cs index 36c6a4ba..abdcadae 100644 --- a/src/Numerics/Providers/FourierTransform/ManagedFourierTransformProvider.cs +++ b/src/Numerics/Providers/FourierTransform/ManagedFourierTransformProvider.cs @@ -64,7 +64,7 @@ namespace MathNet.Numerics.Providers.FourierTransform return "Managed"; } - public void Forward(Complex32[] samples, FourierTransformScaling scaling) + public void Forward(Memory samples, FourierTransformScaling scaling) { if (samples.Length.IsPowerOfTwo()) { @@ -74,7 +74,7 @@ namespace MathNet.Numerics.Providers.FourierTransform } else { - Radix2Forward(samples); + Radix2Forward(samples.Span); } } else @@ -86,18 +86,18 @@ namespace MathNet.Numerics.Providers.FourierTransform { case FourierTransformScaling.SymmetricScaling: { - HalfRescale(samples); + HalfRescale(samples.Span); break; } case FourierTransformScaling.ForwardScaling: { - FullRescale(samples); + FullRescale(samples.Span); break; } } } - public void Forward(Complex[] samples, FourierTransformScaling scaling) + public void Forward(Memory samples, FourierTransformScaling scaling) { if (samples.Length.IsPowerOfTwo()) { @@ -107,7 +107,7 @@ namespace MathNet.Numerics.Providers.FourierTransform } else { - Radix2Forward(samples); + Radix2Forward(samples.Span); } } else @@ -119,18 +119,18 @@ namespace MathNet.Numerics.Providers.FourierTransform { case FourierTransformScaling.SymmetricScaling: { - HalfRescale(samples); + HalfRescale(samples.Span); break; } case FourierTransformScaling.ForwardScaling: { - FullRescale(samples); + FullRescale(samples.Span); break; } } } - public void Backward(Complex32[] spectrum, FourierTransformScaling scaling) + public void Backward(Memory spectrum, FourierTransformScaling scaling) { if (spectrum.Length.IsPowerOfTwo()) { @@ -140,7 +140,7 @@ namespace MathNet.Numerics.Providers.FourierTransform } else { - Radix2Inverse(spectrum); + Radix2Inverse(spectrum.Span); } } else @@ -152,18 +152,18 @@ namespace MathNet.Numerics.Providers.FourierTransform { case FourierTransformScaling.SymmetricScaling: { - HalfRescale(spectrum); + HalfRescale(spectrum.Span); break; } case FourierTransformScaling.BackwardScaling: { - FullRescale(spectrum); + FullRescale(spectrum.Span); break; } } } - public void Backward(Complex[] spectrum, FourierTransformScaling scaling) + public void Backward(Memory spectrum, FourierTransformScaling scaling) { if (spectrum.Length.IsPowerOfTwo()) { @@ -173,7 +173,7 @@ namespace MathNet.Numerics.Providers.FourierTransform } else { - Radix2Inverse(spectrum); + Radix2Inverse(spectrum.Span); } } else @@ -185,18 +185,18 @@ namespace MathNet.Numerics.Providers.FourierTransform { case FourierTransformScaling.SymmetricScaling: { - HalfRescale(spectrum); + HalfRescale(spectrum.Span); break; } case FourierTransformScaling.BackwardScaling: { - FullRescale(spectrum); + FullRescale(spectrum.Span); break; } } } - public void ForwardReal(float[] samples, int n, FourierTransformScaling scaling) + public void ForwardReal(Span samples, int n, FourierTransformScaling scaling) { // TODO: backport proper, optimized implementation from Iridium @@ -227,7 +227,7 @@ namespace MathNet.Numerics.Providers.FourierTransform } } - public void ForwardReal(double[] samples, int n, FourierTransformScaling scaling) + public void ForwardReal(Span samples, int n, FourierTransformScaling scaling) { // TODO: backport proper, optimized implementation from Iridium @@ -258,7 +258,7 @@ namespace MathNet.Numerics.Providers.FourierTransform } } - public void BackwardReal(float[] spectrum, int n, FourierTransformScaling scaling) + public void BackwardReal(Span spectrum, int n, FourierTransformScaling scaling) { // TODO: backport proper, optimized implementation from Iridium @@ -288,7 +288,7 @@ namespace MathNet.Numerics.Providers.FourierTransform spectrum[n] = 0f; } - public void BackwardReal(double[] spectrum, int n, FourierTransformScaling scaling) + public void BackwardReal(Span spectrum, int n, FourierTransformScaling scaling) { // TODO: backport proper, optimized implementation from Iridium @@ -318,22 +318,22 @@ namespace MathNet.Numerics.Providers.FourierTransform spectrum[n] = 0d; } - public void ForwardMultidim(Complex32[] samples, int[] dimensions, FourierTransformScaling scaling) + public void ForwardMultidim(Span samples, Span dimensions, FourierTransformScaling scaling) { throw new NotSupportedException(); } - public void ForwardMultidim(Complex[] samples, int[] dimensions, FourierTransformScaling scaling) + public void ForwardMultidim(Span samples, Span dimensions, FourierTransformScaling scaling) { throw new NotSupportedException(); } - public void BackwardMultidim(Complex32[] spectrum, int[] dimensions, FourierTransformScaling scaling) + public void BackwardMultidim(Span spectrum, Span dimensions, FourierTransformScaling scaling) { throw new NotSupportedException(); } - public void BackwardMultidim(Complex[] spectrum, int[] dimensions, FourierTransformScaling scaling) + public void BackwardMultidim(Span spectrum, Span dimensions, FourierTransformScaling scaling) { throw new NotSupportedException(); }