diff --git a/src/Numerics/Control.cs b/src/Numerics/Control.cs index 4045a7d4..8cbae11c 100644 --- a/src/Numerics/Control.cs +++ b/src/Numerics/Control.cs @@ -27,10 +27,10 @@ // OTHER DEALINGS IN THE SOFTWARE. // -using MathNet.Numerics.Providers.LinearAlgebra; using System; using System.Threading.Tasks; using MathNet.Numerics.Providers.FourierTransform; +using MathNet.Numerics.Providers.LinearAlgebra; namespace MathNet.Numerics { @@ -39,8 +39,6 @@ namespace MathNet.Numerics /// public static class Control { - const string EnvVarLAProvider = "MathNetNumericsLAProvider"; - static int _maxDegreeOfParallelism; static int _blockSize; static int _parallelizeOrder; @@ -68,54 +66,10 @@ namespace MathNet.Numerics TaskScheduler = TaskScheduler.Default; } - private static void InitializeDefaultProviders() - { - lock (_staticLock) - { - if (_linearAlgebraProvider == null || _fourierTransformProvider == null) - { -#if NATIVE - try - { - var value = Environment.GetEnvironmentVariable(EnvVarLAProvider); - switch (value != null ? value.ToUpperInvariant() : string.Empty) - { - case "MKL": - UseNativeMKL(); - break; - - case "CUDA": - UseNativeCUDA(); - break; - - case "OPENBLAS": - UseNativeOpenBLAS(); - break; - - default: - if (!TryUseNative()) - { - UseManaged(); - } - break; - } - } - catch - { - // We don't care about any failures here at all (because "auto") - UseManaged(); - } -#else - UseManaged(); -#endif - } - } - } - public static void UseManaged() { - LinearAlgebraProvider = new ManagedLinearAlgebraProvider(); - FourierTransformProvider = new ManagedFourierTransformProvider(); + LinearAlgebraControl.UseManaged(); + FourierTransformControl.UseManaged(); } #if NATIVE @@ -126,8 +80,8 @@ namespace MathNet.Numerics /// public static void UseNativeMKL() { - LinearAlgebraProvider = new Providers.LinearAlgebra.Mkl.MklLinearAlgebraProvider(); - FourierTransformProvider = new Providers.FourierTransform.Mkl.MklFourierTransformProvider(); + LinearAlgebraControl.UseNativeMKL(); + FourierTransformControl.UseNativeMKL(); } /// @@ -141,8 +95,11 @@ namespace MathNet.Numerics Providers.LinearAlgebra.Mkl.MklPrecision precision = Providers.LinearAlgebra.Mkl.MklPrecision.Double, Providers.LinearAlgebra.Mkl.MklAccuracy accuracy = Providers.LinearAlgebra.Mkl.MklAccuracy.High) { - LinearAlgebraProvider = new Providers.LinearAlgebra.Mkl.MklLinearAlgebraProvider(consistency, precision, accuracy); - FourierTransformProvider = new Providers.FourierTransform.Mkl.MklFourierTransformProvider(); + LinearAlgebraControl.UseNativeMKL( + (Providers.Common.Mkl.MklConsistency)consistency, + (Providers.Common.Mkl.MklPrecision)precision, + (Providers.Common.Mkl.MklAccuracy)accuracy); + FourierTransformControl.UseNativeMKL(); } /// @@ -155,8 +112,8 @@ namespace MathNet.Numerics Providers.Common.Mkl.MklPrecision precision = Providers.Common.Mkl.MklPrecision.Double, Providers.Common.Mkl.MklAccuracy accuracy = Providers.Common.Mkl.MklAccuracy.High) { - LinearAlgebraProvider = new Providers.LinearAlgebra.Mkl.MklLinearAlgebraProvider(consistency, precision, accuracy); - FourierTransformProvider = new Providers.FourierTransform.Mkl.MklFourierTransformProvider(); + LinearAlgebraControl.UseNativeMKL(consistency, precision, accuracy); + FourierTransformControl.UseNativeMKL(); } /// @@ -177,11 +134,7 @@ namespace MathNet.Numerics /// public static void UseNativeCUDA() { - LinearAlgebraProvider = new Providers.LinearAlgebra.Cuda.CudaLinearAlgebraProvider(); - if (_fourierTransformProvider == null) - { - FourierTransformProvider = new ManagedFourierTransformProvider(); - } + LinearAlgebraControl.UseNativeCUDA(); } /// @@ -202,11 +155,7 @@ namespace MathNet.Numerics /// public static void UseNativeOpenBLAS() { - LinearAlgebraProvider = new Providers.LinearAlgebra.OpenBlas.OpenBlasLinearAlgebraProvider(); - if (_fourierTransformProvider == null) - { - FourierTransformProvider = new ManagedFourierTransformProvider(); - } + LinearAlgebraControl.UseNativeOpenBLAS(); } /// @@ -296,7 +245,15 @@ namespace MathNet.Numerics get { if (_linearAlgebraProvider == null) - InitializeDefaultProviders(); + { + lock (_staticLock) + { + if (_linearAlgebraProvider == null) + { + LinearAlgebraControl.UseDefault(); + } + } + } return _linearAlgebraProvider; } @@ -318,7 +275,15 @@ namespace MathNet.Numerics get { if (_fourierTransformProvider == null) - InitializeDefaultProviders(); + { + lock (_staticLock) + { + if (_fourierTransformProvider == null) + { + FourierTransformControl.UseDefault(); + } + } + } return _fourierTransformProvider; } diff --git a/src/Numerics/Numerics.csproj b/src/Numerics/Numerics.csproj index 842ae7c9..1c546f4c 100644 --- a/src/Numerics/Numerics.csproj +++ b/src/Numerics/Numerics.csproj @@ -175,6 +175,7 @@ + @@ -190,6 +191,7 @@ + diff --git a/src/Numerics/Providers/Common/Mkl/MklProvider.cs b/src/Numerics/Providers/Common/Mkl/MklProvider.cs index 9a0ee156..f9879b83 100644 --- a/src/Numerics/Providers/Common/Mkl/MklProvider.cs +++ b/src/Numerics/Providers/Common/Mkl/MklProvider.cs @@ -40,23 +40,41 @@ namespace MathNet.Numerics.Providers.Common.Mkl static bool _nativeX64; static bool _nativeIA64; + public static bool IsAvailable(int minRevision) + { + try + { + if (!NativeProviderLoader.TryLoad(SafeNativeMethods.DllName)) + { + return false; + } + + 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 >= minRevision; + } + catch + { + return false; + } + } + 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); + _nativeRevision = SafeNativeMethods.query_capability((int)ProviderConfig.Revision); _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); - _mklVersion = new Version( SafeNativeMethods.query_capability((int)ProviderConfig.MklMajorVersion), SafeNativeMethods.query_capability((int)ProviderConfig.MklMinorVersion), diff --git a/src/Numerics/Providers/FourierTransform/FourierTransformControl.cs b/src/Numerics/Providers/FourierTransform/FourierTransformControl.cs new file mode 100644 index 00000000..d989432a --- /dev/null +++ b/src/Numerics/Providers/FourierTransform/FourierTransformControl.cs @@ -0,0 +1,97 @@ +// +// 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.FourierTransform +{ + internal static class FourierTransformControl + { + const string EnvVarFFTProvider = "MathNetNumericsFFTProvider"; + + public static void UseManaged() + { + Control.FourierTransformProvider = new ManagedFourierTransformProvider(); + } + +#if NATIVE + public static void UseNativeMKL() + { + Control.FourierTransformProvider = new Mkl.MklFourierTransformProvider(); + } +#endif + + public static bool TryUse(IFourierTransformProvider provider) + { + try + { + if (!provider.IsAvailable()) + { + return false; + } + + Control.FourierTransformProvider = provider; + return true; + } + catch + { + // intentionally swallow exceptions here - use the explicit variants if you're interested in why + return false; + } + } + + public static void UseBest() + { +#if NATIVE + if (!TryUse(new Mkl.MklFourierTransformProvider())) + { + UseManaged(); + } +#else + UseManaged(); +#endif + } + + public static void UseDefault() + { + var value = Environment.GetEnvironmentVariable(EnvVarFFTProvider); + switch (value != null ? value.ToUpperInvariant() : string.Empty) + { +#if NATIVE + case "MKL": + UseNativeMKL(); + break; +#endif + default: + UseBest(); + break; + } + } + } +} diff --git a/src/Numerics/Providers/FourierTransform/IFourierTransformProvider.cs b/src/Numerics/Providers/FourierTransform/IFourierTransformProvider.cs index 2e4dea88..ec44d664 100644 --- a/src/Numerics/Providers/FourierTransform/IFourierTransformProvider.cs +++ b/src/Numerics/Providers/FourierTransform/IFourierTransformProvider.cs @@ -43,6 +43,12 @@ namespace MathNet.Numerics.Providers.FourierTransform public interface IFourierTransformProvider { + /// + /// Try to find out whether the provider is available, at least in principle. + /// Verification may still fail if available, but it will certainly fail if unavailable. + /// + bool IsAvailable(); + /// /// Initialize and verify that the provided is indeed available. If not, fall back to alternatives like the managed provider /// diff --git a/src/Numerics/Providers/FourierTransform/ManagedFourierTransformProvider.cs b/src/Numerics/Providers/FourierTransform/ManagedFourierTransformProvider.cs index f20ece67..eb2bb5c3 100644 --- a/src/Numerics/Providers/FourierTransform/ManagedFourierTransformProvider.cs +++ b/src/Numerics/Providers/FourierTransform/ManagedFourierTransformProvider.cs @@ -37,6 +37,18 @@ namespace MathNet.Numerics.Providers.FourierTransform public class ManagedFourierTransformProvider : IFourierTransformProvider { + /// + /// Try to find out whether the provider is available, at least in principle. + /// Verification may still fail if available, but it will certainly fail if unavailable. + /// + public virtual bool IsAvailable() + { + return true; + } + + /// + /// Initialize and verify that the provided is indeed available. If not, fall back to alternatives like the managed provider + /// public virtual void InitializeVerify() { } diff --git a/src/Numerics/Providers/FourierTransform/Mkl/MklFourierTransformProvider.cs b/src/Numerics/Providers/FourierTransform/Mkl/MklFourierTransformProvider.cs index afb9ac74..cf033d09 100644 --- a/src/Numerics/Providers/FourierTransform/Mkl/MklFourierTransformProvider.cs +++ b/src/Numerics/Providers/FourierTransform/Mkl/MklFourierTransformProvider.cs @@ -36,6 +36,18 @@ namespace MathNet.Numerics.Providers.FourierTransform.Mkl { public class MklFourierTransformProvider : IFourierTransformProvider { + /// + /// Try to find out whether the provider is available, at least in principle. + /// Verification may still fail if available, but it will certainly fail if unavailable. + /// + public bool IsAvailable() + { + return MklProvider.IsAvailable(minRevision: 11); + } + + /// + /// Initialize and verify that the provided is indeed available. If not, fall back to alternatives like the managed provider + /// public void InitializeVerify() { MklProvider.Load(minRevision: 11); diff --git a/src/Numerics/Providers/LinearAlgebra/Cuda/CudaLinearAlgebraProvider.cs b/src/Numerics/Providers/LinearAlgebra/Cuda/CudaLinearAlgebraProvider.cs index 6c814870..b1c3de28 100644 --- a/src/Numerics/Providers/LinearAlgebra/Cuda/CudaLinearAlgebraProvider.cs +++ b/src/Numerics/Providers/LinearAlgebra/Cuda/CudaLinearAlgebraProvider.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 @@ -46,6 +46,30 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda IntPtr _blasHandle; IntPtr _solverHandle; + /// + /// Try to find out whether the provider is available, at least in principle. + /// Verification may still fail if available, but it will certainly fail if unavailable. + /// + public override bool IsAvailable() + { + try + { + if (!NativeProviderLoader.TryLoad(SafeNativeMethods.DllName)) + { + return false; + } + + 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 >= 1; + } + catch + { + return false; + } + } + /// /// Initialize and verify that the provided is indeed available. /// If calling this method fails, consider to fall back to alternatives like the managed provider. @@ -60,12 +84,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda a = SafeNativeMethods.query_capability(0); b = SafeNativeMethods.query_capability(1); + _nativeRevision = SafeNativeMethods.query_capability((int)ProviderConfig.Revision); _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) diff --git a/src/Numerics/Providers/LinearAlgebra/ILinearAlgebraProvider.cs b/src/Numerics/Providers/LinearAlgebra/ILinearAlgebraProvider.cs index 2298581a..1717dbee 100644 --- a/src/Numerics/Providers/LinearAlgebra/ILinearAlgebraProvider.cs +++ b/src/Numerics/Providers/LinearAlgebra/ILinearAlgebraProvider.cs @@ -93,6 +93,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra ILinearAlgebraProvider, ILinearAlgebraProvider { + /// + /// Try to find out whether the provider is available, at least in principle. + /// Verification may still fail if available, but it will certainly fail if unavailable. + /// + bool IsAvailable(); + /// /// Initialize and verify that the provided is indeed available. If not, fall back to alternatives like the managed provider /// diff --git a/src/Numerics/Providers/LinearAlgebra/LinearAlgebraControl.cs b/src/Numerics/Providers/LinearAlgebra/LinearAlgebraControl.cs new file mode 100644 index 00000000..a4cf8882 --- /dev/null +++ b/src/Numerics/Providers/LinearAlgebra/LinearAlgebraControl.cs @@ -0,0 +1,120 @@ +// +// 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.LinearAlgebra +{ + internal static class LinearAlgebraControl + { + const string EnvVarLAProvider = "MathNetNumericsLAProvider"; + + public static void UseManaged() + { + Control.LinearAlgebraProvider = new ManagedLinearAlgebraProvider(); + } + +#if NATIVE + public static void UseNativeMKL( + Common.Mkl.MklConsistency consistency = Common.Mkl.MklConsistency.Auto, + Common.Mkl.MklPrecision precision = Common.Mkl.MklPrecision.Double, + Common.Mkl.MklAccuracy accuracy = Common.Mkl.MklAccuracy.High) + { + Control.LinearAlgebraProvider = new Mkl.MklLinearAlgebraProvider(consistency, precision, accuracy); + } + + public static void UseNativeCUDA() + { + Control.LinearAlgebraProvider = new Cuda.CudaLinearAlgebraProvider(); + } + + public static void UseNativeOpenBLAS() + { + Control.LinearAlgebraProvider = new OpenBlas.OpenBlasLinearAlgebraProvider(); + } +#endif + + public static bool TryUse(ILinearAlgebraProvider provider) + { + try + { + if (!provider.IsAvailable()) + { + return false; + } + + Control.LinearAlgebraProvider = provider; + return true; + } + catch + { + // intentionally swallow exceptions here - use the explicit variants if you're interested in why + return false; + } + } + + public static void UseBest() + { +#if NATIVE + if (!(TryUse(new Cuda.CudaLinearAlgebraProvider()) + || TryUse(new Mkl.MklLinearAlgebraProvider()) + || TryUse(new OpenBlas.OpenBlasLinearAlgebraProvider()))) + { + UseManaged(); + } +#else + UseManaged(); +#endif + } + + public static void UseDefault() + { + var value = Environment.GetEnvironmentVariable(EnvVarLAProvider); + switch (value != null ? value.ToUpperInvariant() : string.Empty) + { +#if NATIVE + case "MKL": + UseNativeMKL(); + break; + + case "CUDA": + UseNativeCUDA(); + break; + + case "OPENBLAS": + UseNativeOpenBLAS(); + break; +#endif + default: + UseBest(); + break; + } + } + } +} diff --git a/src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.cs b/src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.cs index ac7a3f88..6fbc98a8 100644 --- a/src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.cs +++ b/src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.cs @@ -34,6 +34,15 @@ namespace MathNet.Numerics.Providers.LinearAlgebra /// public partial class ManagedLinearAlgebraProvider : ILinearAlgebraProvider { + /// + /// Try to find out whether the provider is available, at least in principle. + /// Verification may still fail if available, but it will certainly fail if unavailable. + /// + public virtual bool IsAvailable() + { + return true; + } + /// /// Initialize and verify that the provided is indeed available. If not, fall back to alternatives like the managed provider /// diff --git a/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.cs b/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.cs index 92f7a316..f6d1c34a 100644 --- a/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.cs +++ b/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.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 @@ -133,6 +133,15 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl _accuracy = Common.Mkl.MklAccuracy.High; } + /// + /// Try to find out whether the provider is available, at least in principle. + /// Verification may still fail if available, but it will certainly fail if unavailable. + /// + public override bool IsAvailable() + { + return MklProvider.IsAvailable(minRevision: 4); + } + /// /// Initialize and verify that the provided is indeed available. /// If calling this method fails, consider to fall back to alternatives like the managed provider. diff --git a/src/Numerics/Providers/LinearAlgebra/OpenBlas/OpenBlasLinearAlgebraProvider.cs b/src/Numerics/Providers/LinearAlgebra/OpenBlas/OpenBlasLinearAlgebraProvider.cs index 433243cf..18b4cc52 100644 --- a/src/Numerics/Providers/LinearAlgebra/OpenBlas/OpenBlasLinearAlgebraProvider.cs +++ b/src/Numerics/Providers/LinearAlgebra/OpenBlas/OpenBlasLinearAlgebraProvider.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 @@ -63,6 +63,34 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas bool _nativeIA64; bool _nativeARM; + /// + /// Try to find out whether the provider is available, at least in principle. + /// Verification may still fail if available, but it will certainly fail if unavailable. + /// + public override bool IsAvailable() + { + try + { + if (!NativeProviderLoader.TryLoad(SafeNativeMethods.DllName)) + { + return false; + } + + 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 >= 1; + } + catch + { + return false; + } + } + + /// + /// Initialize and verify that the provided is indeed available. + /// If not, fall back to alternatives like the managed provider + /// public override void InitializeVerify() { int a, b, linearAlgebra; @@ -73,13 +101,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas a = SafeNativeMethods.query_capability(0); b = SafeNativeMethods.query_capability(1); + _nativeRevision = SafeNativeMethods.query_capability((int)ProviderConfig.Revision); _nativeIX86 = SafeNativeMethods.query_capability((int)ProviderPlatform.x86) > 0; _nativeX64 = SafeNativeMethods.query_capability((int)ProviderPlatform.x64) > 0; _nativeIA64 = SafeNativeMethods.query_capability((int)ProviderPlatform.ia64) > 0; _nativeARM = SafeNativeMethods.query_capability((int)ProviderPlatform.arm) > 0; - _nativeRevision = SafeNativeMethods.query_capability((int)ProviderConfig.Revision); linearAlgebra = SafeNativeMethods.query_capability((int)ProviderCapability.LinearAlgebra); } catch (DllNotFoundException e)