Browse Source

FFT: clean up after migration into managed provider, obsolete algorithm-specific methods

pull/555/merge
Christoph Ruegg 8 years ago
parent
commit
2bfad5ab53
  1. 28
      src/Numerics.Tests/IntegralTransformsTests/FourierTest.cs
  2. 16
      src/Numerics.Tests/IntegralTransformsTests/InverseTransformTest.cs
  3. 114
      src/Numerics.Tests/IntegralTransformsTests/MatchingNaiveTransformTest.cs
  4. 299
      src/Numerics/IntegralTransforms/Fourier.Bluestein.cs
  5. 225
      src/Numerics/IntegralTransforms/Fourier.RadixN.cs
  6. 32
      src/Numerics/IntegralTransforms/Fourier.cs
  7. 8
      src/Numerics/Providers/Common/Cuda/CudaProvider.cs
  8. 12
      src/Numerics/Providers/Common/Mkl/MklProvider.cs
  9. 8
      src/Numerics/Providers/Common/OpenBlas/OpenBlasProvider.cs
  10. 6
      src/Numerics/Providers/FourierTransform/Mkl/MklFourierTransformProvider.cs
  11. 6
      src/Numerics/Providers/LinearAlgebra/Cuda/CudaLinearAlgebraProvider.cs
  12. 6
      src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.cs
  13. 6
      src/Numerics/Providers/LinearAlgebra/OpenBlas/OpenBlasLinearAlgebraProvider.cs

28
src/Numerics.Tests/IntegralTransformsTests/FourierTest.cs

@ -118,33 +118,5 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
}
}
}
/// <summary>
/// Radix2XXX when not power of two throws <c>ArgumentException</c>.
/// </summary>
[Test]
public void Radix2ThrowsWhenNotPowerOfTwo32()
{
var samples = Generate.RandomComplex32(0x7F, GetUniform(1));
Assert.Throws(typeof(ArgumentException), () => Fourier.Radix2Forward(samples, FourierOptions.Default));
Assert.Throws(typeof(ArgumentException), () => Fourier.Radix2Inverse(samples, FourierOptions.Default));
Assert.Throws(typeof(ArgumentException), () => Fourier.Radix2(samples, -1));
Assert.Throws(typeof(ArgumentException), () => Fourier.Radix2Parallel(samples, -1));
}
/// <summary>
/// Radix2XXX when not power of two throws <c>ArgumentException</c>.
/// </summary>
[Test]
public void Radix2ThrowsWhenNotPowerOfTwo()
{
var samples = Generate.RandomComplex(0x7F, GetUniform(1));
Assert.Throws(typeof (ArgumentException), () => Fourier.Radix2Forward(samples, FourierOptions.Default));
Assert.Throws(typeof (ArgumentException), () => Fourier.Radix2Inverse(samples, FourierOptions.Default));
Assert.Throws(typeof (ArgumentException), () => Fourier.Radix2(samples, -1));
Assert.Throws(typeof (ArgumentException), () => Fourier.Radix2Parallel(samples, -1));
}
}
}

16
src/Numerics.Tests/IntegralTransformsTests/InverseTransformTest.cs

@ -98,10 +98,10 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
var work = new Complex32[samples.Length];
samples.CopyTo(work, 0);
Fourier.Radix2Forward(work, options);
Fourier.Forward(work, options);
Assert.IsFalse(work.ListAlmostEqual(samples, 6));
Fourier.Radix2Inverse(work, options);
Fourier.Inverse(work, options);
AssertHelpers.AlmostEqual(samples, work, 12);
}
@ -117,10 +117,10 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
var work = new Complex[samples.Length];
samples.CopyTo(work, 0);
Fourier.Radix2Forward(work, options);
Fourier.Forward(work, options);
Assert.IsFalse(work.ListAlmostEqual(samples, 6));
Fourier.Radix2Inverse(work, options);
Fourier.Inverse(work, options);
AssertHelpers.AlmostEqual(samples, work, 12);
}
@ -136,10 +136,10 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
var work = new Complex32[samples.Length];
samples.CopyTo(work, 0);
Fourier.BluesteinForward(work, options);
Fourier.Forward(work, options);
Assert.IsFalse(work.ListAlmostEqual(samples, 6));
Fourier.BluesteinInverse(work, options);
Fourier.Inverse(work, options);
AssertHelpers.AlmostEqual(samples, work, 10);
}
@ -155,10 +155,10 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
var work = new Complex[samples.Length];
samples.CopyTo(work, 0);
Fourier.BluesteinForward(work, options);
Fourier.Forward(work, options);
Assert.IsFalse(work.ListAlmostEqual(samples, 6));
Fourier.BluesteinInverse(work, options);
Fourier.Inverse(work, options);
AssertHelpers.AlmostEqual(samples, work, 10);
}

114
src/Numerics.Tests/IntegralTransformsTests/MatchingNaiveTransformTest.cs

@ -129,8 +129,8 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
{
var samples = Generate.PeriodicMap(16, w => new Complex32((float)Math.Sin(w), 0), 16, 1.0, Constants.Pi2);
Verify(samples, 6, options, Fourier.NaiveForward, Fourier.Radix2Forward);
Verify(samples, 6, options, Fourier.NaiveInverse, Fourier.Radix2Inverse);
Verify(samples, 6, options, Fourier.NaiveForward, Fourier.Forward);
Verify(samples, 6, options, Fourier.NaiveInverse, Fourier.Inverse);
}
/// <summary>
@ -144,8 +144,8 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
{
var samples = Generate.PeriodicMap(16, w => new Complex(Math.Sin(w), 0), 16, 1.0, Constants.Pi2);
Verify(samples, 12, options, Fourier.NaiveForward, Fourier.Radix2Forward);
Verify(samples, 12, options, Fourier.NaiveInverse, Fourier.Radix2Inverse);
Verify(samples, 12, options, Fourier.NaiveForward, Fourier.Forward);
Verify(samples, 12, options, Fourier.NaiveInverse, Fourier.Inverse);
}
/// <summary>
@ -159,8 +159,8 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
{
var samples = Generate.RandomComplex32(0x80, GetUniform(1));
Verify(samples, 5, options, Fourier.NaiveForward, Fourier.Radix2Forward);
Verify(samples, 5, options, Fourier.NaiveInverse, Fourier.Radix2Inverse);
Verify(samples, 5, options, Fourier.NaiveForward, Fourier.Forward);
Verify(samples, 5, options, Fourier.NaiveInverse, Fourier.Inverse);
}
/// <summary>
@ -174,8 +174,8 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
{
var samples = Generate.RandomComplex(0x80, GetUniform(1));
Verify(samples, 10, options, Fourier.NaiveForward, Fourier.Radix2Forward);
Verify(samples, 10, options, Fourier.NaiveInverse, Fourier.Radix2Inverse);
Verify(samples, 10, options, Fourier.NaiveForward, Fourier.Forward);
Verify(samples, 10, options, Fourier.NaiveInverse, Fourier.Inverse);
}
/// <summary>
@ -189,8 +189,8 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
{
var samples = Generate.PeriodicMap(14, w => new Complex32((float)Math.Sin(w), 0), 14, 1.0, Constants.Pi2);
Verify(samples, 6, options, Fourier.NaiveForward, Fourier.BluesteinForward);
Verify(samples, 6, options, Fourier.NaiveInverse, Fourier.BluesteinInverse);
Verify(samples, 6, options, Fourier.NaiveForward, Fourier.Forward);
Verify(samples, 6, options, Fourier.NaiveInverse, Fourier.Inverse);
}
/// <summary>
@ -204,8 +204,8 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
{
var samples = Generate.PeriodicMap(14, w => new Complex(Math.Sin(w), 0), 14, 1.0, Constants.Pi2);
Verify(samples, 12, options, Fourier.NaiveForward, Fourier.BluesteinForward);
Verify(samples, 12, options, Fourier.NaiveInverse, Fourier.BluesteinInverse);
Verify(samples, 12, options, Fourier.NaiveForward, Fourier.Forward);
Verify(samples, 12, options, Fourier.NaiveInverse, Fourier.Inverse);
}
/// <summary>
@ -219,8 +219,8 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
{
var samples = Generate.RandomComplex32(0x80, GetUniform(1));
Verify(samples, 5, options, Fourier.NaiveForward, Fourier.BluesteinForward);
Verify(samples, 5, options, Fourier.NaiveInverse, Fourier.BluesteinInverse);
Verify(samples, 5, options, Fourier.NaiveForward, Fourier.Forward);
Verify(samples, 5, options, Fourier.NaiveInverse, Fourier.Inverse);
}
/// <summary>
@ -234,8 +234,8 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
{
var samples = Generate.RandomComplex(0x80, GetUniform(1));
Verify(samples, 10, options, Fourier.NaiveForward, Fourier.BluesteinForward);
Verify(samples, 10, options, Fourier.NaiveInverse, Fourier.BluesteinInverse);
Verify(samples, 10, options, Fourier.NaiveForward, Fourier.Forward);
Verify(samples, 10, options, Fourier.NaiveInverse, Fourier.Inverse);
}
/// <summary>
@ -249,8 +249,8 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
{
var samples = Generate.RandomComplex32(0x7F, GetUniform(1));
Verify(samples, 5, options, Fourier.NaiveForward, Fourier.BluesteinForward);
Verify(samples, 5, options, Fourier.NaiveInverse, Fourier.BluesteinInverse);
Verify(samples, 5, options, Fourier.NaiveForward, Fourier.Forward);
Verify(samples, 5, options, Fourier.NaiveInverse, Fourier.Inverse);
}
/// <summary>
@ -264,8 +264,8 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
{
var samples = Generate.RandomComplex(0x7F, GetUniform(1));
Verify(samples, 10, options, Fourier.NaiveForward, Fourier.BluesteinForward);
Verify(samples, 10, options, Fourier.NaiveInverse, Fourier.BluesteinInverse);
Verify(samples, 10, options, Fourier.NaiveForward, Fourier.Forward);
Verify(samples, 10, options, Fourier.NaiveInverse, Fourier.Inverse);
}
/// <summary>
@ -282,8 +282,8 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
{
var samples = Generate.RandomComplex32(0x7F, GetUniform(1));
VerifyInplace(samples, 5, options, Fourier.Forward, Fourier.BluesteinForward);
VerifyInplace(samples, 5, options, Fourier.Inverse, Fourier.BluesteinInverse);
VerifyInplace(samples, 5, options, Fourier.Forward, Fourier.Forward);
VerifyInplace(samples, 5, options, Fourier.Inverse, Fourier.Inverse);
}
/// <summary>
@ -300,8 +300,8 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
{
var samples = Generate.RandomComplex(0x7F, GetUniform(1));
VerifyInplace(samples, 10, options, Fourier.Forward, Fourier.BluesteinForward);
VerifyInplace(samples, 10, options, Fourier.Inverse, Fourier.BluesteinInverse);
VerifyInplace(samples, 10, options, Fourier.Forward, Fourier.Forward);
VerifyInplace(samples, 10, options, Fourier.Inverse, Fourier.Inverse);
}
[TestCase(FourierOptions.Default, 128)]
@ -359,77 +359,61 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
}
[Test]
public void AlgorithmsMatchProvider_PowerOfTwo_Large_32()
public void ProviderMatchesManagedProvider_PowerOfTwo_Large_32()
{
// 65536 = 2^16
var samples = Generate.RandomComplex32(65536, GetUniform(1));
var managed = FourierTransformControl.CreateManaged();
VerifyInplace(samples, 5, FourierOptions.NoScaling, (s, o) => FourierTransformControl.Provider.Forward(s, FourierTransformScaling.NoScaling), Fourier.Radix2Forward);
VerifyInplace(samples, 5, FourierOptions.NoScaling, (s, o) => FourierTransformControl.Provider.Forward(s, FourierTransformScaling.NoScaling), Fourier.BluesteinForward);
VerifyInplace(samples, 5, FourierOptions.NoScaling, (s, o) => managed.Forward(s, FourierTransformScaling.NoScaling), (s, o) => FourierTransformControl.Provider.Forward(s, FourierTransformScaling.NoScaling));
}
[Test]
public void AlgorithmsMatchProvider_PowerOfTwo_Large()
public void ProviderMatchesManagedProvider_PowerOfTwo_Large()
{
// 65536 = 2^16
var samples = Generate.RandomComplex(65536, GetUniform(1));
var managed = FourierTransformControl.CreateManaged();
VerifyInplace(samples, 10, FourierOptions.NoScaling, (s,o) => FourierTransformControl.Provider.Forward(s, FourierTransformScaling.NoScaling), Fourier.Radix2Forward);
VerifyInplace(samples, 10, FourierOptions.NoScaling, (s, o) => FourierTransformControl.Provider.Forward(s, FourierTransformScaling.NoScaling), Fourier.BluesteinForward);
VerifyInplace(samples, 10, FourierOptions.NoScaling, (s, o) => managed.Forward(s, FourierTransformScaling.NoScaling), (s, o) => FourierTransformControl.Provider.Forward(s, FourierTransformScaling.NoScaling));
}
[Test]
public void AlgorithmsMatchProvider_Arbitrary_Large_32()
public void ProviderMatchesManagedProvider_Arbitrary_Large_32()
{
// 30870 = 2*3*3*5*7*7*7
const FourierOptions options = FourierOptions.NoScaling;
var samples = Generate.RandomComplex32(30870, GetUniform(1));
var managed = FourierTransformControl.CreateManaged();
var provider = new Complex32[samples.Length];
samples.Copy(provider);
FourierTransformControl.Provider.Forward(provider, FourierTransformScaling.NoScaling);
Verify(samples, 5, options, (a, b) => provider, Fourier.BluesteinForward);
VerifyInplace(samples, 5, FourierOptions.NoScaling, (s, o) => managed.Forward(s, FourierTransformScaling.NoScaling), (s, o) => FourierTransformControl.Provider.Forward(s, FourierTransformScaling.NoScaling));
}
[Test]
public void AlgorithmsMatchProvider_Arbitrary_Large()
public void ProviderMatchesManagedProvider_Arbitrary_Large()
{
// 30870 = 2*3*3*5*7*7*7
const FourierOptions options = FourierOptions.NoScaling;
var samples = Generate.RandomComplex(30870, GetUniform(1));
var managed = FourierTransformControl.CreateManaged();
var provider = new Complex[samples.Length];
samples.Copy(provider);
FourierTransformControl.Provider.Forward(provider, FourierTransformScaling.NoScaling);
Verify(samples, 10, options, (a, b) => provider, Fourier.BluesteinForward);
VerifyInplace(samples, 10, FourierOptions.NoScaling, (s, o) => managed.Forward(s, FourierTransformScaling.NoScaling), (s, o) => FourierTransformControl.Provider.Forward(s, FourierTransformScaling.NoScaling));
}
[Test]
public void AlgorithmsMatchProvider_Arbitrary_Large_GH286_32()
public void ProviderMatchesManagedProvider_Arbitrary_Large_GH286_32()
{
const FourierOptions options = FourierOptions.NoScaling;
var samples = Generate.RandomComplex32(46500, GetUniform(1));
var managed = FourierTransformControl.CreateManaged();
var provider = new Complex32[samples.Length];
samples.Copy(provider);
FourierTransformControl.Provider.Forward(provider, FourierTransformScaling.NoScaling);
Verify(samples, 5, options, (a, b) => provider, Fourier.BluesteinForward);
VerifyInplace(samples, 5, FourierOptions.NoScaling, (s, o) => managed.Forward(s, FourierTransformScaling.NoScaling), (s, o) => FourierTransformControl.Provider.Forward(s, FourierTransformScaling.NoScaling));
}
[Test]
public void AlgorithmsMatchProvider_Arbitrary_Large_GH286()
public void ProviderMatchesManagedProvider_Arbitrary_Large_GH286()
{
const FourierOptions options = FourierOptions.NoScaling;
var samples = Generate.RandomComplex(46500, GetUniform(1));
var managed = FourierTransformControl.CreateManaged();
var provider = new Complex[samples.Length];
samples.Copy(provider);
FourierTransformControl.Provider.Forward(provider, FourierTransformScaling.NoScaling);
Verify(samples, 10, options, (a, b) => provider, Fourier.BluesteinForward);
VerifyInplace(samples, 10, FourierOptions.NoScaling, (s, o) => managed.Forward(s, FourierTransformScaling.NoScaling), (s, o) => FourierTransformControl.Provider.Forward(s, FourierTransformScaling.NoScaling));
}
[Test, Explicit("Long-Running")]
@ -440,8 +424,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
var samples = Generate.RandomComplex32(65536, GetUniform(1));
var naive = Fourier.NaiveForward(samples, options);
Verify(samples, 5, options, (a, b) => naive, Fourier.Radix2Forward);
Verify(samples, 5, options, (a, b) => naive, Fourier.BluesteinForward);
Verify(samples, 3, options, (a, b) => naive, Fourier.Forward);
}
[Test, Explicit("Long-Running")]
@ -452,8 +435,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
var samples = Generate.RandomComplex(65536, GetUniform(1));
var naive = Fourier.NaiveForward(samples, options);
Verify(samples, 10, options, (a, b) => naive, Fourier.Radix2Forward);
Verify(samples, 10, options, (a, b) => naive, Fourier.BluesteinForward);
Verify(samples, 10, options, (a, b) => naive, Fourier.Forward);
}
[Test, Explicit("Long-Running")]
@ -463,7 +445,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
const FourierOptions options = FourierOptions.NoScaling;
var samples = Generate.RandomComplex32(30870, GetUniform(1));
Verify(samples, 5, options, Fourier.NaiveForward, Fourier.BluesteinForward);
Verify(samples, 4, options, Fourier.NaiveForward, Fourier.Forward);
}
[Test, Explicit("Long-Running")]
@ -474,7 +456,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
var samples = Generate.RandomComplex(30870, GetUniform(1));
var naive = Fourier.NaiveForward(samples, options);
Verify(samples, 10, options, (a, b) => naive, Fourier.BluesteinForward);
Verify(samples, 10, options, (a, b) => naive, Fourier.Forward);
}
[Test, Explicit("Long-Running")]
@ -483,7 +465,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
const FourierOptions options = FourierOptions.NoScaling;
var samples = Generate.RandomComplex32(46500, GetUniform(1));
Verify(samples, 5, options, Fourier.NaiveForward, Fourier.BluesteinForward);
Verify(samples, 4, options, Fourier.NaiveForward, Fourier.Forward);
}
[Test, Explicit("Long-Running")]
@ -493,7 +475,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests
var samples = Generate.RandomComplex(46500, GetUniform(1));
var naive = Fourier.NaiveForward(samples, options);
Verify(samples, 10, options, (a, b) => naive, Fourier.BluesteinForward);
Verify(samples, 10, options, (a, b) => naive, Fourier.Forward);
}
}
}

299
src/Numerics/IntegralTransforms/Fourier.Bluestein.cs

@ -1,299 +0,0 @@
// <copyright file="Fourier.Bluestein.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
//
// Copyright (c) 2009-2015 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.
// </copyright>
using System;
using System.Numerics;
using MathNet.Numerics.Threading;
namespace MathNet.Numerics.IntegralTransforms
{
/// <summary>
/// Complex Fast (FFT) Implementation of the Discrete Fourier Transform (DFT).
/// </summary>
public static partial class Fourier
{
/// <summary>
/// Sequences with length greater than Math.Sqrt(Int32.MaxValue) + 1
/// will cause k*k in the Bluestein sequence to overflow (GH-286).
/// </summary>
const int BluesteinSequenceLengthThreshold = 46341;
/// <summary>
/// Generate the bluestein sequence for the provided problem size.
/// </summary>
/// <param name="n">Number of samples.</param>
/// <returns>Bluestein sequence exp(I*Pi*k^2/N)</returns>
static Complex32[] BluesteinSequence32(int n)
{
double s = Constants.Pi / n;
var sequence = new Complex32[n];
// TODO: benchmark whether the second variation is significantly
// faster than the former one. If not just use the former one always.
if (n > BluesteinSequenceLengthThreshold)
{
for (int k = 0; k < sequence.Length; k++)
{
double t = (s * k) * k;
sequence[k] = new Complex32((float)Math.Cos(t), (float)Math.Sin(t));
}
}
else
{
for (int k = 0; k < sequence.Length; k++)
{
double t = s * (k * k);
sequence[k] = new Complex32((float)Math.Cos(t), (float)Math.Sin(t));
}
}
return sequence;
}
/// <summary>
/// Generate the bluestein sequence for the provided problem size.
/// </summary>
/// <param name="n">Number of samples.</param>
/// <returns>Bluestein sequence exp(I*Pi*k^2/N)</returns>
static Complex[] BluesteinSequence(int n)
{
double s = Constants.Pi/n;
var sequence = new Complex[n];
// TODO: benchmark whether the second variation is significantly
// faster than the former one. If not just use the former one always.
if (n > BluesteinSequenceLengthThreshold)
{
for (int k = 0; k < sequence.Length; k++)
{
double t = (s*k)*k;
sequence[k] = new Complex(Math.Cos(t), Math.Sin(t));
}
}
else
{
for (int k = 0; k < sequence.Length; k++)
{
double t = s*(k*k);
sequence[k] = new Complex(Math.Cos(t), Math.Sin(t));
}
}
return sequence;
}
/// <summary>
/// Convolution with the bluestein sequence (Parallel Version).
/// </summary>
/// <param name="samples">Sample Vector.</param>
static void BluesteinConvolutionParallel(Complex32[] samples)
{
int n = samples.Length;
Complex32[] sequence = BluesteinSequence32(n);
// Padding to power of two >= 2N–1 so we can apply Radix-2 FFT.
int m = ((n << 1) - 1).CeilingToPowerOfTwo();
var b = new Complex32[m];
var a = new Complex32[m];
CommonParallel.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];
}
Radix2Parallel(a, 1);
var nbinv = 1.0f / m;
for (int i = 0; i < samples.Length; i++)
{
samples[i] = nbinv * sequence[i].Conjugate() * a[i];
}
}
/// <summary>
/// Convolution with the bluestein sequence (Parallel Version).
/// </summary>
/// <param name="samples">Sample Vector.</param>
static void BluesteinConvolutionParallel(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();
var b = new Complex[m];
var a = new Complex[m];
CommonParallel.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];
}
Radix2Parallel(a, 1);
var nbinv = 1.0/m;
for (int i = 0; i < samples.Length; i++)
{
samples[i] = nbinv*sequence[i].Conjugate()*a[i];
}
}
/// <summary>
/// Swap the real and imaginary parts of each sample.
/// </summary>
/// <param name="samples">Sample Vector.</param>
static void SwapRealImaginary(Complex32[] samples)
{
for (int i = 0; i < samples.Length; i++)
{
samples[i] = new Complex32(samples[i].Imaginary, samples[i].Real);
}
}
/// <summary>
/// Swap the real and imaginary parts of each sample.
/// </summary>
/// <param name="samples">Sample Vector.</param>
static void SwapRealImaginary(Complex[] samples)
{
for (int i = 0; i < samples.Length; i++)
{
samples[i] = new Complex(samples[i].Imaginary, samples[i].Real);
}
}
/// <summary>
/// Bluestein generic FFT for arbitrary sized sample vectors.
/// </summary>
/// <param name="samples">Time-space sample vector.</param>
/// <param name="exponentSign">Fourier series exponent sign.</param>
internal static void Bluestein(Complex32[] samples, int exponentSign)
{
int n = samples.Length;
if (n.IsPowerOfTwo())
{
Radix2Parallel(samples, exponentSign);
return;
}
if (exponentSign == 1)
{
SwapRealImaginary(samples);
}
BluesteinConvolutionParallel(samples);
if (exponentSign == 1)
{
SwapRealImaginary(samples);
}
}
/// <summary>
/// Bluestein generic FFT for arbitrary sized sample vectors.
/// </summary>
/// <param name="samples">Time-space sample vector.</param>
/// <param name="exponentSign">Fourier series exponent sign.</param>
internal static void Bluestein(Complex[] samples, int exponentSign)
{
int n = samples.Length;
if (n.IsPowerOfTwo())
{
Radix2Parallel(samples, exponentSign);
return;
}
if (exponentSign == 1)
{
SwapRealImaginary(samples);
}
BluesteinConvolutionParallel(samples);
if (exponentSign == 1)
{
SwapRealImaginary(samples);
}
}
}
}

225
src/Numerics/IntegralTransforms/Fourier.RadixN.cs

@ -1,225 +0,0 @@
// <copyright file="Fourier.RadixN.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
//
// Copyright (c) 2009-2014 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using MathNet.Numerics.Properties;
using MathNet.Numerics.Threading;
namespace MathNet.Numerics.IntegralTransforms
{
/// <summary>
/// Complex Fast (FFT) Implementation of the Discrete Fourier Transform (DFT).
/// </summary>
public static partial class Fourier
{
/// <summary>
/// Radix-2 Reorder Helper Method
/// </summary>
/// <typeparam name="T">Sample type</typeparam>
/// <param name="samples">Sample vector</param>
static void Radix2Reorder<T>(T[] samples)
{
var j = 0;
for (var i = 0; i < samples.Length - 1; i++)
{
if (i < j)
{
var temp = samples[i];
samples[i] = samples[j];
samples[j] = temp;
}
var m = samples.Length;
do
{
m >>= 1;
j ^= m;
}
while ((j & m) == 0);
}
}
/// <summary>
/// Radix-2 Step Helper Method
/// </summary>
/// <param name="samples">Sample vector.</param>
/// <param name="exponentSign">Fourier series exponent sign.</param>
/// <param name="levelSize">Level Group Size.</param>
/// <param name="k">Index inside of the level.</param>
#if !NET40
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
static void Radix2Step(Complex32[] samples, int exponentSign, int levelSize, int k)
{
// Twiddle Factor
var exponent = (exponentSign * k) * Constants.Pi / levelSize;
var w = new Complex32((float)Math.Cos(exponent), (float)Math.Sin(exponent));
var step = levelSize << 1;
for (var i = k; i < samples.Length; i += step)
{
var ai = samples[i];
var t = w * samples[i + levelSize];
samples[i] = ai + t;
samples[i + levelSize] = ai - t;
}
}
/// <summary>
/// Radix-2 Step Helper Method
/// </summary>
/// <param name="samples">Sample vector.</param>
/// <param name="exponentSign">Fourier series exponent sign.</param>
/// <param name="levelSize">Level Group Size.</param>
/// <param name="k">Index inside of the level.</param>
#if !NET40
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
static void Radix2Step(Complex[] samples, int exponentSign, int levelSize, int k)
{
// Twiddle Factor
var exponent = (exponentSign*k)*Constants.Pi/levelSize;
var w = new Complex(Math.Cos(exponent), Math.Sin(exponent));
var step = levelSize << 1;
for (var i = k; i < samples.Length; i += step)
{
var ai = samples[i];
var t = w*samples[i + levelSize];
samples[i] = ai + t;
samples[i + levelSize] = ai - t;
}
}
/// <summary>
/// Radix-2 generic FFT for power-of-two sized sample vectors.
/// </summary>
/// <param name="samples">Sample vector, where the FFT is evaluated in place.</param>
/// <param name="exponentSign">Fourier series exponent sign.</param>
/// <exception cref="ArgumentException"/>
internal static void Radix2(Complex32[] samples, int exponentSign)
{
if (!samples.Length.IsPowerOfTwo())
{
throw new ArgumentException(Resources.ArgumentPowerOfTwo);
}
Radix2Reorder(samples);
for (var levelSize = 1; levelSize < samples.Length; levelSize *= 2)
{
for (var k = 0; k < levelSize; k++)
{
Radix2Step(samples, exponentSign, levelSize, k);
}
}
}
/// <summary>
/// Radix-2 generic FFT for power-of-two sized sample vectors.
/// </summary>
/// <param name="samples">Sample vector, where the FFT is evaluated in place.</param>
/// <param name="exponentSign">Fourier series exponent sign.</param>
/// <exception cref="ArgumentException"/>
internal static void Radix2(Complex[] samples, int exponentSign)
{
if (!samples.Length.IsPowerOfTwo())
{
throw new ArgumentException(Resources.ArgumentPowerOfTwo);
}
Radix2Reorder(samples);
for (var levelSize = 1; levelSize < samples.Length; levelSize *= 2)
{
for (var k = 0; k < levelSize; k++)
{
Radix2Step(samples, exponentSign, levelSize, k);
}
}
}
/// <summary>
/// Radix-2 generic FFT for power-of-two sample vectors (Parallel Version).
/// </summary>
/// <param name="samples">Sample vector, where the FFT is evaluated in place.</param>
/// <param name="exponentSign">Fourier series exponent sign.</param>
/// <exception cref="ArgumentException"/>
internal static void Radix2Parallel(Complex32[] samples, int exponentSign)
{
if (!samples.Length.IsPowerOfTwo())
{
throw new ArgumentException(Resources.ArgumentPowerOfTwo);
}
Radix2Reorder(samples);
for (var levelSize = 1; levelSize < samples.Length; levelSize *= 2)
{
var size = levelSize;
CommonParallel.For(0, size, 64, (u, v) =>
{
for (int i = u; i < v; i++)
{
Radix2Step(samples, exponentSign, size, i);
}
});
}
}
/// <summary>
/// Radix-2 generic FFT for power-of-two sample vectors (Parallel Version).
/// </summary>
/// <param name="samples">Sample vector, where the FFT is evaluated in place.</param>
/// <param name="exponentSign">Fourier series exponent sign.</param>
/// <exception cref="ArgumentException"/>
internal static void Radix2Parallel(Complex[] samples, int exponentSign)
{
if (!samples.Length.IsPowerOfTwo())
{
throw new ArgumentException(Resources.ArgumentPowerOfTwo);
}
Radix2Reorder(samples);
for (var levelSize = 1; levelSize < samples.Length; levelSize *= 2)
{
var size = levelSize;
CommonParallel.For(0, size, 64, (u, v) =>
{
for (int i = u; i < v; i++)
{
Radix2Step(samples, exponentSign, size, i);
}
});
}
}
}
}

32
src/Numerics/IntegralTransforms/Fourier.cs

@ -803,10 +803,10 @@ namespace MathNet.Numerics.IntegralTransforms
/// <param name="samples">Sample vector, where the FFT is evaluated in place.</param>
/// <param name="options">Fourier Transform Convention Options.</param>
/// <exception cref="ArgumentException"/>
[Obsolete("Use Forward instead. Will be dropped in version 5.0 and behave like Forward until then.")]
public static void Radix2Forward(Complex32[] samples, FourierOptions options = FourierOptions.Default)
{
Radix2Parallel(samples, SignByOptions(options));
ForwardScaleByOptions(options, samples);
Forward(samples, options);
}
/// <summary>
@ -815,10 +815,10 @@ namespace MathNet.Numerics.IntegralTransforms
/// <param name="samples">Sample vector, where the FFT is evaluated in place.</param>
/// <param name="options">Fourier Transform Convention Options.</param>
/// <exception cref="ArgumentException"/>
[Obsolete("Use Forward instead. Will be dropped in version 5.0 and behave like Forward until then.")]
public static void Radix2Forward(Complex[] samples, FourierOptions options = FourierOptions.Default)
{
Radix2Parallel(samples, SignByOptions(options));
ForwardScaleByOptions(options, samples);
Forward(samples, options);
}
/// <summary>
@ -827,10 +827,10 @@ namespace MathNet.Numerics.IntegralTransforms
/// <param name="spectrum">Sample vector, where the FFT is evaluated in place.</param>
/// <param name="options">Fourier Transform Convention Options.</param>
/// <exception cref="ArgumentException"/>
[Obsolete("Use Inverse instead. Will be dropped in version 5.0 and behave like Inverse until then.")]
public static void Radix2Inverse(Complex32[] spectrum, FourierOptions options = FourierOptions.Default)
{
Radix2Parallel(spectrum, -SignByOptions(options));
InverseScaleByOptions(options, spectrum);
Inverse(spectrum, options);
}
/// <summary>
@ -839,10 +839,10 @@ namespace MathNet.Numerics.IntegralTransforms
/// <param name="spectrum">Sample vector, where the FFT is evaluated in place.</param>
/// <param name="options">Fourier Transform Convention Options.</param>
/// <exception cref="ArgumentException"/>
[Obsolete("Use Inverse instead. Will be dropped in version 5.0 and behave like Inverse until then.")]
public static void Radix2Inverse(Complex[] spectrum, FourierOptions options = FourierOptions.Default)
{
Radix2Parallel(spectrum, -SignByOptions(options));
InverseScaleByOptions(options, spectrum);
Inverse(spectrum, options);
}
/// <summary>
@ -850,10 +850,10 @@ namespace MathNet.Numerics.IntegralTransforms
/// </summary>
/// <param name="samples">Sample vector, where the FFT is evaluated in place.</param>
/// <param name="options">Fourier Transform Convention Options.</param>
[Obsolete("Use Forward instead. Will be dropped in version 5.0 and behave like Forward until then.")]
public static void BluesteinForward(Complex32[] samples, FourierOptions options = FourierOptions.Default)
{
Bluestein(samples, SignByOptions(options));
ForwardScaleByOptions(options, samples);
Forward(samples, options);
}
/// <summary>
@ -861,10 +861,10 @@ namespace MathNet.Numerics.IntegralTransforms
/// </summary>
/// <param name="samples">Sample vector, where the FFT is evaluated in place.</param>
/// <param name="options">Fourier Transform Convention Options.</param>
[Obsolete("Use Forward instead. Will be dropped in version 5.0 and behave like Forward until then.")]
public static void BluesteinForward(Complex[] samples, FourierOptions options = FourierOptions.Default)
{
Bluestein(samples, SignByOptions(options));
ForwardScaleByOptions(options, samples);
Forward(samples, options);
}
/// <summary>
@ -872,10 +872,10 @@ namespace MathNet.Numerics.IntegralTransforms
/// </summary>
/// <param name="spectrum">Sample vector, where the FFT is evaluated in place.</param>
/// <param name="options">Fourier Transform Convention Options.</param>
[Obsolete("Use Inverse instead. Will be dropped in version 5.0 and behave like Inverse until then.")]
public static void BluesteinInverse(Complex32[] spectrum, FourierOptions options = FourierOptions.Default)
{
Bluestein(spectrum, -SignByOptions(options));
InverseScaleByOptions(options, spectrum);
Inverse(spectrum, options);
}
/// <summary>
@ -883,10 +883,10 @@ namespace MathNet.Numerics.IntegralTransforms
/// </summary>
/// <param name="spectrum">Sample vector, where the FFT is evaluated in place.</param>
/// <param name="options">Fourier Transform Convention Options.</param>
[Obsolete("Use Inverse instead. Will be dropped in version 5.0 and behave like Inverse until then.")]
public static void BluesteinInverse(Complex[] spectrum, FourierOptions options = FourierOptions.Default)
{
Bluestein(spectrum, -SignByOptions(options));
InverseScaleByOptions(options, spectrum);
Inverse(spectrum, options);
}
/// <summary>

8
src/Numerics/Providers/Common/Cuda/CudaProvider.cs

@ -36,8 +36,8 @@ namespace MathNet.Numerics.Providers.Common.Cuda
{
public static class CudaProvider
{
const int _designTimeRevision = 1;
const int _minimumCompatibleRevision = 1;
const int DesignTimeRevision = 1;
const int MinimumCompatibleRevision = 1;
static int _nativeRevision;
static bool _nativeX86;
@ -62,7 +62,7 @@ namespace MathNet.Numerics.Providers.Common.Cuda
int a = SafeNativeMethods.query_capability(0);
int b = SafeNativeMethods.query_capability(1);
int nativeRevision = SafeNativeMethods.query_capability((int)ProviderConfig.Revision);
return a == 0 && b == -1 && nativeRevision >= _minimumCompatibleRevision;
return a == 0 && b == -1 && nativeRevision >= MinimumCompatibleRevision;
}
catch
{
@ -104,7 +104,7 @@ namespace MathNet.Numerics.Providers.Common.Cuda
throw new NotSupportedException("Cuda Native Provider does not support capability querying and is therefore not compatible. Consider upgrading to a newer version.", e);
}
if (a != 0 || b != -1 || _nativeRevision < _minimumCompatibleRevision)
if (a != 0 || b != -1 || _nativeRevision < MinimumCompatibleRevision)
{
throw new NotSupportedException("Cuda Native Provider too old. Consider upgrading to a newer version.");
}

12
src/Numerics/Providers/Common/Mkl/MklProvider.cs

@ -36,8 +36,8 @@ namespace MathNet.Numerics.Providers.Common.Mkl
{
public static class MklProvider
{
const int _designTimeRevision = 12;
const int _minimumCompatibleRevision = 4;
const int DesignTimeRevision = 12;
const int MinimumCompatibleRevision = 4;
static int _nativeRevision;
static Version _mklVersion;
@ -63,7 +63,7 @@ namespace MathNet.Numerics.Providers.Common.Mkl
int a = SafeNativeMethods.query_capability(0);
int b = SafeNativeMethods.query_capability(1);
int nativeRevision = SafeNativeMethods.query_capability((int)ProviderConfig.Revision);
return a == 0 && b == -1 && nativeRevision >= _minimumCompatibleRevision;
return a == 0 && b == -1 && nativeRevision >= MinimumCompatibleRevision;
}
catch
{
@ -134,7 +134,7 @@ namespace MathNet.Numerics.Providers.Common.Mkl
throw new NotSupportedException("MKL Native Provider does not support capability querying and is therefore not compatible. Consider upgrading to a newer version.", e);
}
if (a != 0 || b != -1 || _nativeRevision < _minimumCompatibleRevision)
if (a != 0 || b != -1 || _nativeRevision < MinimumCompatibleRevision)
{
throw new NotSupportedException("MKL Native Provider too old. Consider upgrading to a newer version.");
}
@ -300,8 +300,8 @@ namespace MathNet.Numerics.Providers.Common.Mkl
if (_nativeX64) parts.Add("x64");
if (_nativeIA64) parts.Add("IA64");
parts.Add("revision " + _nativeRevision);
if (_nativeRevision > _designTimeRevision) parts.Add("ahead revision " + _designTimeRevision);
if (_nativeRevision < _designTimeRevision) parts.Add("behind revision " + _designTimeRevision);
if (_nativeRevision > DesignTimeRevision) parts.Add("ahead revision " + DesignTimeRevision);
if (_nativeRevision < DesignTimeRevision) parts.Add("behind revision " + DesignTimeRevision);
if (_mklVersion.Major > 0)
{
parts.Add(_mklVersion.Build == 0

8
src/Numerics/Providers/Common/OpenBlas/OpenBlasProvider.cs

@ -36,8 +36,8 @@ namespace MathNet.Numerics.Providers.Common.OpenBlas
{
public static class OpenBlasProvider
{
const int _designTimeRevision = 1;
const int _minimumCompatibleRevision = 1;
const int DesignTimeRevision = 1;
const int MinimumCompatibleRevision = 1;
static int _nativeRevision;
static bool _nativeX86;
@ -63,7 +63,7 @@ namespace MathNet.Numerics.Providers.Common.OpenBlas
int a = SafeNativeMethods.query_capability(0);
int b = SafeNativeMethods.query_capability(1);
int nativeRevision = SafeNativeMethods.query_capability((int)ProviderConfig.Revision);
return a == 0 && b == -1 && nativeRevision >= _minimumCompatibleRevision;
return a == 0 && b == -1 && nativeRevision >= MinimumCompatibleRevision;
}
catch
{
@ -106,7 +106,7 @@ namespace MathNet.Numerics.Providers.Common.OpenBlas
throw new NotSupportedException("OpenBLAS Native Provider does not support capability querying and is therefore not compatible. Consider upgrading to a newer version.", e);
}
if (a != 0 || b != -1 || _nativeRevision < _minimumCompatibleRevision)
if (a != 0 || b != -1 || _nativeRevision < MinimumCompatibleRevision)
{
throw new NotSupportedException("OpenBLAS Native Provider too old. Consider upgrading to a newer version.");
}

6
src/Numerics/Providers/FourierTransform/Mkl/MklFourierTransformProvider.cs

@ -37,7 +37,7 @@ namespace MathNet.Numerics.Providers.FourierTransform.Mkl
{
internal class MklFourierTransformProvider : IFourierTransformProvider, IDisposable
{
const int _minimumCompatibleRevision = 11;
const int MinimumCompatibleRevision = 11;
class Kernel
{
@ -72,9 +72,9 @@ namespace MathNet.Numerics.Providers.FourierTransform.Mkl
public void InitializeVerify()
{
int revision = MklProvider.Load(hintPath: _hintPath);
if (revision < _minimumCompatibleRevision)
if (revision < MinimumCompatibleRevision)
{
throw new NotSupportedException($"MKL Native Provider revision r{revision} is too old. Consider upgrading to a newer version. Revision r{_minimumCompatibleRevision} and newer are supported.");
throw new NotSupportedException($"MKL Native Provider revision r{revision} is too old. Consider upgrading to a newer version. Revision r{MinimumCompatibleRevision} and newer are supported.");
}
// we only support exactly one major version, since major version changes imply a breaking change.

6
src/Numerics/Providers/LinearAlgebra/Cuda/CudaLinearAlgebraProvider.cs

@ -39,7 +39,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
/// </summary>
internal partial class CudaLinearAlgebraProvider : ManagedLinearAlgebraProvider, IDisposable
{
const int _minimumCompatibleRevision = 1;
const int MinimumCompatibleRevision = 1;
readonly string _hintPath;
IntPtr _blasHandle;
@ -67,9 +67,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
public override void InitializeVerify()
{
int revision = CudaProvider.Load(hintPath: _hintPath);
if (revision < _minimumCompatibleRevision)
if (revision < MinimumCompatibleRevision)
{
throw new NotSupportedException($"Cuda Native Provider revision r{revision} is too old. Consider upgrading to a newer version. Revision r{_minimumCompatibleRevision} and newer are supported.");
throw new NotSupportedException($"Cuda Native Provider revision r{revision} is too old. Consider upgrading to a newer version. Revision r{MinimumCompatibleRevision} and newer are supported.");
}
int linearAlgebra = SafeNativeMethods.query_capability((int)ProviderCapability.LinearAlgebraMajor);

6
src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.cs

@ -50,7 +50,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
/// </summary>
internal partial class MklLinearAlgebraProvider : ManagedLinearAlgebraProvider, IDisposable
{
const int _minimumCompatibleRevision = 4;
const int MinimumCompatibleRevision = 4;
readonly string _hintPath;
readonly MklConsistency _consistency;
@ -93,9 +93,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
public override void InitializeVerify()
{
int revision = MklProvider.Load(_hintPath, _consistency, _precision, _accuracy);
if (revision < _minimumCompatibleRevision)
if (revision < MinimumCompatibleRevision)
{
throw new NotSupportedException($"MKL Native Provider revision r{revision} is too old. Consider upgrading to a newer version. Revision r{_minimumCompatibleRevision} and newer are supported.");
throw new NotSupportedException($"MKL Native Provider revision r{revision} is too old. Consider upgrading to a newer version. Revision r{MinimumCompatibleRevision} and newer are supported.");
}
_linearAlgebraMajor = SafeNativeMethods.query_capability((int)ProviderCapability.LinearAlgebraMajor);

6
src/Numerics/Providers/LinearAlgebra/OpenBlas/OpenBlasLinearAlgebraProvider.cs

@ -57,7 +57,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
/// </summary>
internal partial class OpenBlasLinearAlgebraProvider : ManagedLinearAlgebraProvider, IDisposable
{
const int _minimumCompatibleRevision = 1;
const int MinimumCompatibleRevision = 1;
readonly string _hintPath;
@ -83,9 +83,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
public override void InitializeVerify()
{
int revision = OpenBlasProvider.Load(hintPath: _hintPath);
if (revision < _minimumCompatibleRevision)
if (revision < MinimumCompatibleRevision)
{
throw new NotSupportedException($"OpenBLAS Native Provider revision r{revision} is too old. Consider upgrading to a newer version. Revision r{_minimumCompatibleRevision} and newer are supported.");
throw new NotSupportedException($"OpenBLAS Native Provider revision r{revision} is too old. Consider upgrading to a newer version. Revision r{MinimumCompatibleRevision} and newer are supported.");
}
int linearAlgebra = SafeNativeMethods.query_capability((int)ProviderCapability.LinearAlgebraMajor);

Loading…
Cancel
Save