diff --git a/src/Numerics/Control.cs b/src/Numerics/Control.cs
index ee2c9d4e..fa1028fc 100644
--- a/src/Numerics/Control.cs
+++ b/src/Numerics/Control.cs
@@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
-// Copyright (c) 2009-2014 Math.NET
+// 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
@@ -138,7 +138,7 @@ namespace MathNet.Numerics
///
/// Gets or sets a value indicating whether to use thread safe random number generators (RNG).
- /// Thread safe RNG about two and half time slower than non-thread safe RNG.
+ /// Thread safe RNG about two and half time slower than non-thread safe RNG.
///
///
/// true to use thread safe random number generators ; otherwise, false.
@@ -148,7 +148,7 @@ namespace MathNet.Numerics
///
/// Optional path to try to load native provider binaries from.
///
- public static DirectoryInfo NativeProviderPath { get; set; }
+ public static string NativeProviderPath { get; set; }
///
/// Gets or sets the linear algebra provider. Consider to use UseNativeMKL or UseManaged instead.
diff --git a/src/Numerics/Providers/NativeProviderLoader.cs b/src/Numerics/Providers/NativeProviderLoader.cs
index f9e19c40..0f4824b4 100644
--- a/src/Numerics/Providers/NativeProviderLoader.cs
+++ b/src/Numerics/Providers/NativeProviderLoader.cs
@@ -34,6 +34,7 @@ using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security;
+using System.Threading;
#if NATIVE
@@ -44,69 +45,29 @@ namespace MathNet.Numerics.Providers
///
internal static class NativeProviderLoader
{
- static Lazy> _ArchitectureDirectories
- = new Lazy>(
- () => new Dictionary(StringComparer.OrdinalIgnoreCase)
- {
- { "x86", "x86" },
- { "AMD64", "x64" },
- { "IA64", "ia64" },
- { "ARM", "arm" }
- },
- true);
-
- ///
- /// Default directories for each architecture.
- ///
- static Dictionary ArchitectureDirectories
- {
- get { return _ArchitectureDirectories.Value; }
- }
+ static readonly object StaticLock = new Object();
- static Lazy> _nativeHandles = new Lazy>(true);
+ const string X86 = "x86";
+ const string X64 = "x64";
+ const string IA64 = "ia64";
+ const string ARM = "arm";
+ const string ARM64 = "arm64";
///
/// Dictionary of handles to previously loaded libraries,
///
- static Dictionary NativeHandles
- {
- get { return _nativeHandles.Value; }
- }
-
- static string _ArchDirectory = null;
+ static readonly Lazy> NativeHandles = new Lazy>(LazyThreadSafetyMode.PublicationOnly);
///
/// Gets a string indicating the architecture and bitness of the current process.
///
- static string ArchDirectory
- {
- get
- {
- if (string.IsNullOrEmpty(_ArchDirectory))
- {
- string architecture;
- if (IsUnix)
- {
- // Only support x86 and amd64 on Unix as there isn't a reliable way to detect the architecture
- architecture = Environment.Is64BitProcess ? "AMD64" : "x86";
- }
- else
- {
- architecture = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE");
- if (!Environment.Is64BitProcess && string.Equals(architecture, "AMD64", StringComparison.OrdinalIgnoreCase))
- {
- architecture = "x86";
- }
- }
-
- // Fallback to using the architecture name if unknown
- if (!ArchitectureDirectories.TryGetValue(architecture, out _ArchDirectory))
- _ArchDirectory = architecture;
- }
+ static readonly Lazy ArchitectureKey = new Lazy(EvaluateArchitectureKey, LazyThreadSafetyMode.PublicationOnly);
- return _ArchDirectory;
- }
- }
+ ///
+ /// If the last native library failed to load then gets the corresponding exception
+ /// which occurred or null if the library was successfully loaded.
+ ///
+ public static Exception LastException { get; private set; }
static bool IsUnix
{
@@ -117,13 +78,40 @@ namespace MathNet.Numerics.Providers
}
}
- ///
- /// If the last native library failed to load then gets the corresponding exception
- /// which occurred or null if the library was successfully loaded.
- ///
- public static Exception LastException { get; private set; }
+ static string EvaluateArchitectureKey()
+ {
+ if (IsUnix)
+ {
+ // Only support x86 and amd64 on Unix as there isn't a reliable way to detect the architecture
+ return Environment.Is64BitProcess ? X64 : X86;
+ }
- static readonly object StaticLock = new Object();
+ var architecture = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE");
+
+ if (string.Equals(architecture, "x86", StringComparison.OrdinalIgnoreCase))
+ {
+ return X86;
+ }
+
+ if (string.Equals(architecture, "amd64", StringComparison.OrdinalIgnoreCase)
+ || string.Equals(architecture, "x64", StringComparison.OrdinalIgnoreCase))
+ {
+ return Environment.Is64BitProcess ? X64 : X86;
+ }
+
+ if (string.Equals(architecture, "ia64", StringComparison.OrdinalIgnoreCase))
+ {
+ return IA64;
+ }
+
+ if (string.Equals(architecture, "arm", StringComparison.OrdinalIgnoreCase))
+ {
+ return Environment.Is64BitProcess ? ARM64 : ARM;
+ }
+
+ // Fallback if unknown
+ return architecture;
+ }
///
/// Load the native library with the given filename.
@@ -138,21 +126,19 @@ namespace MathNet.Numerics.Providers
}
// If we have an extra path provided by the user, look there first
- var userDir = Control.NativeProviderPath;
- if (userDir != null && userDir.Exists && TryLoad(fileName, userDir))
+ if (TryLoad(fileName, Control.NativeProviderPath))
{
return true;
}
// Look under the current AppDomain's base directory
- if (TryLoad(fileName, new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory)))
+ if (TryLoad(fileName, AppDomain.CurrentDomain.BaseDirectory))
{
return true;
}
// Look at this assembly's directory
- var assemblyDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
- if (!string.IsNullOrEmpty(assemblyDir) && TryLoad(fileName, new DirectoryInfo(assemblyDir)))
+ if (TryLoad(fileName, Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)))
{
return true;
}
@@ -166,22 +152,24 @@ namespace MathNet.Numerics.Providers
/// and process mode if there is a matching subfolder.
///
/// True if the library was successfully loaded or if it has already been loaded.
- public static bool TryLoad(string fileName, DirectoryInfo directory)
+ public static bool TryLoad(string fileName, string directory)
{
- if (!directory.Exists)
+ if (!Directory.Exists(directory))
{
return false;
}
+ directory = Path.GetFullPath(directory);
+
// If we have a know architecture, try the matching subdirectory first
- var architecture = ArchDirectory;
- if (!string.IsNullOrEmpty(architecture) && TryLoadFile(new FileInfo(Path.Combine(directory.FullName, architecture, fileName))))
+ var architecture = ArchitectureKey.Value;
+ if (!string.IsNullOrEmpty(architecture) && TryLoadFile(new FileInfo(Path.Combine(directory, architecture, fileName))))
{
return true;
}
// Otherwise try to load directly from the provided directory
- return TryLoadFile(new FileInfo(Path.Combine(directory.FullName, fileName)));
+ return TryLoadFile(new FileInfo(Path.Combine(directory, fileName)));
}
///
@@ -193,7 +181,7 @@ namespace MathNet.Numerics.Providers
lock (StaticLock)
{
IntPtr libraryHandle;
- if (NativeHandles.TryGetValue(file.Name, out libraryHandle))
+ if (NativeHandles.Value.TryGetValue(file.Name, out libraryHandle))
{
return true;
}
@@ -201,7 +189,7 @@ namespace MathNet.Numerics.Providers
if (!file.Exists)
{
// If the library isn't found within an architecture specific folder then return false
- // to allow normal P/Invoke searching behaviour when the library is called
+ // to allow normal P/Invoke searching behavior when the library is called
return false;
}
@@ -216,7 +204,7 @@ namespace MathNet.Numerics.Providers
else
{
LastException = null;
- NativeHandles[file.Name] = libraryHandle;
+ NativeHandles.Value[file.Name] = libraryHandle;
}
return libraryHandle != IntPtr.Zero;