diff --git a/src/NativeProviders/MKL/capabilities.cpp b/src/NativeProviders/MKL/capabilities.cpp index 85a7ff64..0c422644 100644 --- a/src/NativeProviders/MKL/capabilities.cpp +++ b/src/NativeProviders/MKL/capabilities.cpp @@ -41,7 +41,7 @@ extern "C" { #endif // COMMON/SHARED - case 64: return 10; // revision + case 64: return 11; // revision case 65: return 1; // numerical consistency, precision and accuracy modes case 66: return 1; // threading control case 67: return 1; // memory management @@ -54,7 +54,8 @@ extern "C" { case 256: return 0; // basic optimization // FFT - case 384: return 0; // basic FFT + case 384: return 1; // basic FFT (major - breaking) + case 385: return 0; // basic FFT (minor - non-breaking) default: return 0; // unknown or not supported diff --git a/src/Numerics/Numerics.csproj b/src/Numerics/Numerics.csproj index 601d96ac..06febca7 100644 --- a/src/Numerics/Numerics.csproj +++ b/src/Numerics/Numerics.csproj @@ -172,10 +172,10 @@ True Resources.resx + - @@ -188,7 +188,7 @@ - + @@ -206,7 +206,7 @@ - + @@ -225,7 +225,7 @@ - + diff --git a/src/Numerics/Providers/Common/Mkl/MklProvider.cs b/src/Numerics/Providers/Common/Mkl/MklProvider.cs new file mode 100644 index 00000000..c096513c --- /dev/null +++ b/src/Numerics/Providers/Common/Mkl/MklProvider.cs @@ -0,0 +1,84 @@ +// +// Math.NET Numerics, part of the Math.NET Project +// http://numerics.mathdotnet.com +// http://github.com/mathnet/mathnet-numerics +// +// Copyright (c) 2009-2016 Math.NET +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace MathNet.Numerics.Providers.Common.Mkl +{ + internal static class MklProvider + { + static int _nativeRevision; + static bool _nativeX86; + static bool _nativeX64; + static bool _nativeIA64; + + public static void Load(int minRevision) + { + int a, b; + try + { + // Load the native library + NativeProviderLoader.TryLoad(SafeNativeMethods.DllName); + + a = SafeNativeMethods.query_capability(0); + b = SafeNativeMethods.query_capability(1); + + _nativeX86 = SafeNativeMethods.query_capability((int)ProviderPlatform.x86) > 0; + _nativeX64 = SafeNativeMethods.query_capability((int)ProviderPlatform.x64) > 0; + _nativeIA64 = SafeNativeMethods.query_capability((int)ProviderPlatform.ia64) > 0; + + _nativeRevision = SafeNativeMethods.query_capability((int)ProviderConfig.Revision); + } + catch (DllNotFoundException e) + { + throw new NotSupportedException("MKL Native Provider not found.", e); + } + catch (BadImageFormatException e) + { + throw new NotSupportedException("MKL Native Provider found but failed to load. Please verify that the platform matches (x64 vs x32, Windows vs Linux).", e); + } + catch (EntryPointNotFoundException e) + { + 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 < minRevision) + { + throw new NotSupportedException("MKL Native Provider too old. Consider upgrading to a newer version."); + } + } + + public static string Describe() + { + return string.Format("Intel MKL ({1}; revision {0})", + _nativeRevision, + _nativeX86 ? "x86" : _nativeX64 ? "x64" : _nativeIA64 ? "IA64" : "unknown"); + } + } +} diff --git a/src/Numerics/Providers/LinearAlgebra/Mkl/MklProviderCapabilities.cs b/src/Numerics/Providers/Common/Mkl/MklProviderCapabilities.cs similarity index 91% rename from src/Numerics/Providers/LinearAlgebra/Mkl/MklProviderCapabilities.cs rename to src/Numerics/Providers/Common/Mkl/MklProviderCapabilities.cs index 85aa8a43..b1676a65 100644 --- a/src/Numerics/Providers/LinearAlgebra/Mkl/MklProviderCapabilities.cs +++ b/src/Numerics/Providers/Common/Mkl/MklProviderCapabilities.cs @@ -27,7 +27,7 @@ // OTHER DEALINGS IN THE SOFTWARE. // -namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl +namespace MathNet.Numerics.Providers.Common.Mkl { internal enum ProviderPlatform : int { @@ -46,7 +46,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl internal enum ProviderCapability : int { - LinearAlgebra = 128, + LinearAlgebraMajor = 128, LinearAlgebraMinor = 129, + FourierTransformMajor = 384, + FourierTransformMinor = 385 } } diff --git a/src/Numerics/Providers/LinearAlgebra/Mkl/SafeNativeMethods.cs b/src/Numerics/Providers/Common/Mkl/SafeNativeMethods.cs similarity index 95% rename from src/Numerics/Providers/LinearAlgebra/Mkl/SafeNativeMethods.cs rename to src/Numerics/Providers/Common/Mkl/SafeNativeMethods.cs index 6fc00840..287b5c83 100644 --- a/src/Numerics/Providers/LinearAlgebra/Mkl/SafeNativeMethods.cs +++ b/src/Numerics/Providers/Common/Mkl/SafeNativeMethods.cs @@ -2,7 +2,7 @@ // Math.NET Numerics, part of the Math.NET Project // http://mathnet.opensourcedotnet.info // -// Copyright (c) 2009-2014 Math.NET +// Copyright (c) 2009-2016 Math.NET // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -31,8 +31,9 @@ using System.Numerics; using System.Runtime.InteropServices; using System.Security; +using MathNet.Numerics.Providers.LinearAlgebra; -namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl +namespace MathNet.Numerics.Providers.Common.Mkl { /// /// P/Invoke methods to the native math libraries. @@ -367,6 +368,22 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl #endregion Vector Functions + #region FFT + + [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] + internal static extern long z_fft_forward_inplace(long n, double scaling, [In, Out] Complex[] x); + + [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] + internal static extern long c_fft_forward_inplace(long n, float scaling, [In, Out] Complex32[] x); + + [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] + internal static extern long z_fft_backward_inplace(long n, double scaling, [In, Out] Complex[] x); + + [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] + internal static extern long c_fft_backward_inplace(long n, float scaling, [In, Out] Complex32[] x); + + #endregion FFT + // ReSharper restore InconsistentNaming } } diff --git a/src/Numerics/Providers/NativeProviderLoader.cs b/src/Numerics/Providers/Common/NativeProviderLoader.cs similarity index 99% rename from src/Numerics/Providers/NativeProviderLoader.cs rename to src/Numerics/Providers/Common/NativeProviderLoader.cs index 5f1e4193..0b4f19e4 100644 --- a/src/Numerics/Providers/NativeProviderLoader.cs +++ b/src/Numerics/Providers/Common/NativeProviderLoader.cs @@ -3,7 +3,7 @@ // http://numerics.mathdotnet.com // http://github.com/mathnet/mathnet-numerics // -// Copyright (c) 2009-2015 Math.NET +// Copyright (c) 2009-2016 Math.NET // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -37,7 +37,7 @@ using System.Threading; #if NATIVE -namespace MathNet.Numerics.Providers +namespace MathNet.Numerics.Providers.Common { /// /// Helper class to load native libraries depending on the architecture of the OS and process. diff --git a/src/Numerics/Providers/FourierTransform/Mkl/MklFourierTransformProvider.cs b/src/Numerics/Providers/FourierTransform/Mkl/MklFourierTransformProvider.cs index f1fa08c9..50c08ab3 100644 --- a/src/Numerics/Providers/FourierTransform/Mkl/MklFourierTransformProvider.cs +++ b/src/Numerics/Providers/FourierTransform/Mkl/MklFourierTransformProvider.cs @@ -30,6 +30,7 @@ using System; using System.Numerics; +using MathNet.Numerics.Providers.Common.Mkl; namespace MathNet.Numerics.Providers.FourierTransform.Mkl { @@ -37,6 +38,20 @@ namespace MathNet.Numerics.Providers.FourierTransform.Mkl { public void InitializeVerify() { + MklProvider.Load(minRevision: 11); + + // we only support exactly one major version, since major version changes imply a breaking change. + int fftMajor = SafeNativeMethods.query_capability((int)ProviderCapability.FourierTransformMajor); + int fftMinor = SafeNativeMethods.query_capability((int)ProviderCapability.FourierTransformMinor); + if (!(fftMajor == 1 && fftMinor >= 0)) + { + throw new NotSupportedException(string.Format("MKL Native Provider not compatible. Expecting fourier transform v1 but provider implements v{0}.", fftMajor)); + } + } + + public override string ToString() + { + return MklProvider.Describe(); } public void ForwardInplace(Complex[] complex, FourierTransformScaling scaling) diff --git a/src/Numerics/Providers/FourierTransform/Mkl/SafeNativeMethods.cs b/src/Numerics/Providers/FourierTransform/Mkl/SafeNativeMethods.cs deleted file mode 100644 index 02be1430..00000000 --- a/src/Numerics/Providers/FourierTransform/Mkl/SafeNativeMethods.cs +++ /dev/null @@ -1,102 +0,0 @@ -// -// Math.NET Numerics, part of the Math.NET Project -// http://mathnet.opensourcedotnet.info -// -// Copyright (c) 2009-2016 Math.NET -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// 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. -// - -#if NATIVE - -using System.Numerics; -using System.Runtime.InteropServices; -using System.Security; - -namespace MathNet.Numerics.Providers.FourierTransform.Mkl -{ - /// - /// P/Invoke methods to the native math libraries. - /// - [SuppressUnmanagedCodeSecurity] - [SecurityCritical] - internal static class SafeNativeMethods - { - // ReSharper disable InconsistentNaming - - /// - /// Name of the native DLL. - /// - const string _DllName = "MathNet.Numerics.MKL.dll"; - internal static string DllName { get { return _DllName; } } - - [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] - internal static extern int query_capability(int capability); - - [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] - internal static extern void set_consistency_mode(int mode); - - [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] - internal static extern void set_vml_mode(uint mode); - - [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] - internal static extern void set_max_threads(int num_threads); - - #region Memory - [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] - internal static extern void free_buffers(); - - [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] - internal static extern void thread_free_buffers(); - - [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] - internal static extern int disable_fast_mm(); - - [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] - internal static extern long mem_stat([Out]out int allocatedBuffers); - - [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] - internal static extern long peak_mem_usage(int mode); - - #endregion Memory - - #region FFT - - [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] - internal static extern long z_fft_forward_inplace(long n, double scaling, [In, Out] Complex[] x); - - [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] - internal static extern long c_fft_forward_inplace(long n, float scaling, [In, Out] Complex32[] x); - - [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] - internal static extern long z_fft_backward_inplace(long n, double scaling, [In, Out] Complex[] x); - - [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] - internal static extern long c_fft_backward_inplace(long n, float scaling, [In, Out] Complex32[] x); - - #endregion FFT - - // ReSharper restore InconsistentNaming - } -} - -#endif diff --git a/src/Numerics/Providers/LinearAlgebra/Cuda/CudaLinearAlgebraProvider.cs b/src/Numerics/Providers/LinearAlgebra/Cuda/CudaLinearAlgebraProvider.cs index ff93ac97..6c814870 100644 --- a/src/Numerics/Providers/LinearAlgebra/Cuda/CudaLinearAlgebraProvider.cs +++ b/src/Numerics/Providers/LinearAlgebra/Cuda/CudaLinearAlgebraProvider.cs @@ -28,6 +28,7 @@ // using System; +using MathNet.Numerics.Providers.Common; #if NATIVE diff --git a/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Complex.cs b/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Complex.cs index d698d188..880620c4 100644 --- a/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Complex.cs +++ b/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Complex.cs @@ -34,6 +34,7 @@ using System.Numerics; using System.Security; using MathNet.Numerics.LinearAlgebra.Factorization; using MathNet.Numerics.Properties; +using MathNet.Numerics.Providers.Common.Mkl; namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl { diff --git a/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Complex32.cs b/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Complex32.cs index be916438..901020c2 100644 --- a/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Complex32.cs +++ b/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Complex32.cs @@ -34,6 +34,7 @@ using System.Numerics; using System.Security; using MathNet.Numerics.LinearAlgebra.Factorization; using MathNet.Numerics.Properties; +using MathNet.Numerics.Providers.Common.Mkl; namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl { diff --git a/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Double.cs b/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Double.cs index 081ed4ff..f6712217 100644 --- a/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Double.cs +++ b/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Double.cs @@ -34,6 +34,7 @@ using System.Numerics; using System.Security; using MathNet.Numerics.LinearAlgebra.Factorization; using MathNet.Numerics.Properties; +using MathNet.Numerics.Providers.Common.Mkl; namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl { diff --git a/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Single.cs b/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Single.cs index c58d65a8..2a9a2c79 100644 --- a/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Single.cs +++ b/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Single.cs @@ -34,6 +34,7 @@ using System.Numerics; using System.Security; using MathNet.Numerics.LinearAlgebra.Factorization; using MathNet.Numerics.Properties; +using MathNet.Numerics.Providers.Common.Mkl; namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl { diff --git a/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.cs b/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.cs index 8c526e52..a107839a 100644 --- a/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.cs +++ b/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.cs @@ -28,6 +28,8 @@ // using System; +using MathNet.Numerics.Providers.Common; +using MathNet.Numerics.Providers.Common.Mkl; #if NATIVE @@ -105,11 +107,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl /// public partial class MklLinearAlgebraProvider : ManagedLinearAlgebraProvider { - int _nativeRevision; - bool _nativeIX86; - bool _nativeX64; - bool _nativeIA64; - readonly MklConsistency _consistency; readonly MklPrecision _precision; readonly MklAccuracy _accuracy; @@ -144,39 +141,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl /// public override void InitializeVerify() { - int a, b, linearAlgebra; - try - { - // Load the native library - NativeProviderLoader.TryLoad(SafeNativeMethods.DllName); - - a = SafeNativeMethods.query_capability(0); - b = SafeNativeMethods.query_capability(1); - - _nativeIX86 = SafeNativeMethods.query_capability((int)ProviderPlatform.x86) > 0; - _nativeX64 = SafeNativeMethods.query_capability((int)ProviderPlatform.x64) > 0; - _nativeIA64 = SafeNativeMethods.query_capability((int)ProviderPlatform.ia64) > 0; - - _nativeRevision = SafeNativeMethods.query_capability((int)ProviderConfig.Revision); - linearAlgebra = SafeNativeMethods.query_capability((int)ProviderCapability.LinearAlgebra); - } - catch (DllNotFoundException e) - { - throw new NotSupportedException("MKL Native Provider not found.", e); - } - catch (BadImageFormatException e) - { - throw new NotSupportedException("MKL Native Provider found but failed to load. Please verify that the platform matches (x64 vs x32, Windows vs Linux).", e); - } - catch (EntryPointNotFoundException e) - { - throw new NotSupportedException("MKL Native Provider does not support capability querying and is therefore not compatible. Consider upgrading to a newer version.", e); - } + MklProvider.Load(minRevision: 4); - if (a != 0 || b != -1 || _nativeRevision < 4) - { - throw new NotSupportedException("MKL Native Provider too old. Consider upgrading to a newer version."); - } + int linearAlgebra = SafeNativeMethods.query_capability((int)ProviderCapability.LinearAlgebraMajor); // we only support exactly one major version, since major version changes imply a breaking change. if (linearAlgebra != 2) @@ -295,9 +262,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl public override string ToString() { - return string.Format("Intel MKL ({1}; revision {0})", - _nativeRevision, - _nativeIX86 ? "x86" : _nativeX64 ? "x64" : _nativeIA64 ? "IA64" : "unknown"); + return MklProvider.Describe(); } } } diff --git a/src/Numerics/Providers/LinearAlgebra/OpenBlas/OpenBlasLinearAlgebraProvider.cs b/src/Numerics/Providers/LinearAlgebra/OpenBlas/OpenBlasLinearAlgebraProvider.cs index 89e8bb5e..433243cf 100644 --- a/src/Numerics/Providers/LinearAlgebra/OpenBlas/OpenBlasLinearAlgebraProvider.cs +++ b/src/Numerics/Providers/LinearAlgebra/OpenBlas/OpenBlasLinearAlgebraProvider.cs @@ -30,6 +30,7 @@ #if NATIVE using System; +using MathNet.Numerics.Providers.Common; namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas {