forked from tsai/mathnet-numerics
48 changed files with 1742 additions and 336 deletions
@ -0,0 +1,54 @@ |
|||
#include "wrapper_common.h" |
|||
|
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <math.h> |
|||
#include <float.h> |
|||
#include "mkl_dfti.h" |
|||
|
|||
template<typename Data, typename Precision, typename FFT> |
|||
inline MKL_INT64 fft_1d_inplace(const MKL_INT64 n, Data x[], const Precision forward_scale, const Precision backward_scale, const DFTI_CONFIG_VALUE precision, const DFTI_CONFIG_VALUE domain, FFT fft) |
|||
{ |
|||
MKL_LONG status; |
|||
DFTI_DESCRIPTOR_HANDLE descriptor = nullptr; |
|||
status = DftiCreateDescriptor(&descriptor, precision, domain, 1, static_cast<MKL_LONG>(n)); |
|||
if (0 != status) goto cleanup; |
|||
|
|||
status = DftiSetValue(descriptor, DFTI_FORWARD_SCALE, forward_scale); |
|||
if (0 != status) goto cleanup; |
|||
|
|||
status = DftiSetValue(descriptor, DFTI_BACKWARD_SCALE, backward_scale); |
|||
if (0 != status) goto cleanup; |
|||
|
|||
status = DftiCommitDescriptor(descriptor); |
|||
if (0 != status) goto cleanup; |
|||
|
|||
status = fft(descriptor, x); |
|||
|
|||
cleanup: |
|||
DftiFreeDescriptor(&descriptor); |
|||
return static_cast<MKL_INT64>(status); |
|||
} |
|||
|
|||
extern "C" { |
|||
|
|||
DLLEXPORT MKL_INT64 z_fft_forward_inplace(const MKL_INT64 n, const double scaling, MKL_Complex16 x[]) |
|||
{ |
|||
return fft_1d_inplace(n, x, scaling, 1.0, DFTI_DOUBLE, DFTI_COMPLEX, DftiComputeForward); |
|||
} |
|||
|
|||
DLLEXPORT MKL_INT64 c_fft_forward_inplace(const MKL_INT64 n, const float scaling, MKL_Complex8 x[]) |
|||
{ |
|||
return fft_1d_inplace(n, x, scaling, 1.0f, DFTI_SINGLE, DFTI_COMPLEX, DftiComputeForward); |
|||
} |
|||
|
|||
DLLEXPORT MKL_INT64 z_fft_backward_inplace(const MKL_INT64 n, const double scaling, MKL_Complex16 x[]) |
|||
{ |
|||
return fft_1d_inplace(n, x, 1.0, scaling, DFTI_DOUBLE, DFTI_COMPLEX, DftiComputeBackward); |
|||
} |
|||
|
|||
DLLEXPORT MKL_INT64 c_fft_backward_inplace(const MKL_INT64 n, const float scaling, MKL_Complex8 x[]) |
|||
{ |
|||
return fft_1d_inplace(n, x, 1.0f, scaling, DFTI_SINGLE, DFTI_COMPLEX, DftiComputeBackward); |
|||
} |
|||
} |
|||
@ -0,0 +1,111 @@ |
|||
// <copyright file="CudaProvider.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-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.
|
|||
// </copyright>
|
|||
|
|||
#if NATIVE
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace MathNet.Numerics.Providers.Common.Cuda |
|||
{ |
|||
internal static class CudaProvider |
|||
{ |
|||
static int _nativeRevision; |
|||
static bool _nativeX86; |
|||
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 |
|||
{ |
|||
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; |
|||
} |
|||
catch (DllNotFoundException e) |
|||
{ |
|||
throw new NotSupportedException("Cuda Native Provider not found.", e); |
|||
} |
|||
catch (BadImageFormatException e) |
|||
{ |
|||
throw new NotSupportedException("Cuda 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("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 < minRevision) |
|||
{ |
|||
throw new NotSupportedException("Cuda Native Provider too old. Consider upgrading to a newer version."); |
|||
} |
|||
} |
|||
|
|||
public static string Describe() |
|||
{ |
|||
var parts = new List<string>(); |
|||
if (_nativeX86) parts.Add("x86"); |
|||
if (_nativeX64) parts.Add("x64"); |
|||
if (_nativeIA64) parts.Add("IA64"); |
|||
parts.Add("revision " + _nativeRevision); |
|||
|
|||
return string.Concat("Nvidia CUDA (", string.Join("; ", parts), ")"); |
|||
} |
|||
} |
|||
} |
|||
|
|||
#endif
|
|||
@ -0,0 +1,262 @@ |
|||
// <copyright file="MklProvider.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-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.
|
|||
// </copyright>
|
|||
|
|||
#if NATIVE
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace MathNet.Numerics.Providers.Common.Mkl |
|||
{ |
|||
internal static class MklProvider |
|||
{ |
|||
static Version _mklVersion; |
|||
static int _nativeRevision; |
|||
static bool _nativeX86; |
|||
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 |
|||
{ |
|||
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; |
|||
|
|||
_mklVersion = new Version( |
|||
SafeNativeMethods.query_capability((int)ProviderConfig.MklMajorVersion), |
|||
SafeNativeMethods.query_capability((int)ProviderConfig.MklMinorVersion), |
|||
SafeNativeMethods.query_capability((int)ProviderConfig.MklUpdateVersion)); |
|||
} |
|||
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."); |
|||
} |
|||
|
|||
ConfigureThreading(); |
|||
} |
|||
|
|||
static void ConfigureThreading() |
|||
{ |
|||
// set threading settings, if supported
|
|||
if (SafeNativeMethods.query_capability((int)ProviderConfig.Threading) > 0) |
|||
{ |
|||
SafeNativeMethods.set_max_threads(Control.MaxDegreeOfParallelism); |
|||
} |
|||
} |
|||
|
|||
public static void ConfigurePrecision(MklConsistency consistency, MklPrecision precision, MklAccuracy accuracy) |
|||
{ |
|||
// set numerical consistency, precision and accuracy modes, if supported
|
|||
if (SafeNativeMethods.query_capability((int)ProviderConfig.Precision) > 0) |
|||
{ |
|||
SafeNativeMethods.set_consistency_mode((int)consistency); |
|||
SafeNativeMethods.set_vml_mode((uint)precision | (uint)accuracy); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Frees the memory allocated to the MKL memory pool.
|
|||
/// </summary>
|
|||
public static void FreeBuffers() |
|||
{ |
|||
if (SafeNativeMethods.query_capability((int)ProviderConfig.Memory) < 1) |
|||
{ |
|||
throw new NotSupportedException("MKL Native Provider does not support memory management functions. Consider upgrading to a newer version."); |
|||
} |
|||
|
|||
SafeNativeMethods.free_buffers(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Frees the memory allocated to the MKL memory pool on the current thread.
|
|||
/// </summary>
|
|||
public static void ThreadFreeBuffers() |
|||
{ |
|||
if (SafeNativeMethods.query_capability((int)ProviderConfig.Memory) < 1) |
|||
{ |
|||
throw new NotSupportedException("MKL Native Provider does not support memory management functions. Consider upgrading to a newer version."); |
|||
} |
|||
|
|||
SafeNativeMethods.thread_free_buffers(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Disable the MKL memory pool. May impact performance.
|
|||
/// </summary>
|
|||
public static void DisableMemoryPool() |
|||
{ |
|||
if (SafeNativeMethods.query_capability((int)ProviderConfig.Memory) < 1) |
|||
{ |
|||
throw new NotSupportedException("MKL Native Provider does not support memory management functions. Consider upgrading to a newer version."); |
|||
} |
|||
|
|||
SafeNativeMethods.disable_fast_mm(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves information about the MKL memory pool.
|
|||
/// </summary>
|
|||
/// <param name="allocatedBuffers">On output, returns the number of memory buffers allocated.</param>
|
|||
/// <returns>Returns the number of bytes allocated to all memory buffers.</returns>
|
|||
public static long MemoryStatistics(out int allocatedBuffers) |
|||
{ |
|||
if (SafeNativeMethods.query_capability((int)ProviderConfig.Memory) < 1) |
|||
{ |
|||
throw new NotSupportedException("MKL Native Provider does not support memory management functions. Consider upgrading to a newer version."); |
|||
} |
|||
|
|||
return SafeNativeMethods.mem_stat(out allocatedBuffers); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Enable gathering of peak memory statistics of the MKL memory pool.
|
|||
/// </summary>
|
|||
public static void EnablePeakMemoryStatistics() |
|||
{ |
|||
if (SafeNativeMethods.query_capability((int)ProviderConfig.Memory) < 1) |
|||
{ |
|||
throw new NotSupportedException("MKL Native Provider does not support memory management functions. Consider upgrading to a newer version."); |
|||
} |
|||
|
|||
SafeNativeMethods.peak_mem_usage((int)MklMemoryRequestMode.Enable); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Disable gathering of peak memory statistics of the MKL memory pool.
|
|||
/// </summary>
|
|||
public static void DisablePeakMemoryStatistics() |
|||
{ |
|||
if (SafeNativeMethods.query_capability((int)ProviderConfig.Memory) < 1) |
|||
{ |
|||
throw new NotSupportedException("MKL Native Provider does not support memory management functions. Consider upgrading to a newer version."); |
|||
} |
|||
|
|||
SafeNativeMethods.peak_mem_usage((int)MklMemoryRequestMode.Disable); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Measures peak memory usage of the MKL memory pool.
|
|||
/// </summary>
|
|||
/// <param name="reset">Whether the usage counter should be reset.</param>
|
|||
/// <returns>The peak number of bytes allocated to all memory buffers.</returns>
|
|||
public static long PeakMemoryStatistics(bool reset = true) |
|||
{ |
|||
if (SafeNativeMethods.query_capability((int)ProviderConfig.Memory) < 1) |
|||
{ |
|||
throw new NotSupportedException("MKL Native Provider does not support memory management functions. Consider upgrading to a newer version."); |
|||
} |
|||
|
|||
return SafeNativeMethods.peak_mem_usage((int)(reset ? MklMemoryRequestMode.PeakMemoryReset : MklMemoryRequestMode.PeakMemory)); |
|||
} |
|||
|
|||
public static string Describe() |
|||
{ |
|||
var parts = new List<string>(); |
|||
if (_nativeX86) parts.Add("x86"); |
|||
if (_nativeX64) parts.Add("x64"); |
|||
if (_nativeIA64) parts.Add("IA64"); |
|||
parts.Add("revision " + _nativeRevision); |
|||
if (_mklVersion.Major > 0) |
|||
{ |
|||
parts.Add(_mklVersion.Build == 0 |
|||
? string.Concat("MKL ", _mklVersion.ToString(2)) |
|||
: string.Concat("MKL ", _mklVersion.ToString(2), " Update ", _mklVersion.Build)); |
|||
} |
|||
|
|||
return string.Concat("Intel MKL (", string.Join("; ", parts), ")"); |
|||
} |
|||
|
|||
enum MklMemoryRequestMode : int |
|||
{ |
|||
/// <summary>
|
|||
/// Disable gathering memory usage
|
|||
/// </summary>
|
|||
Disable = 0, |
|||
|
|||
/// <summary>
|
|||
/// Enable gathering memory usage
|
|||
/// </summary>
|
|||
Enable = 1, |
|||
|
|||
/// <summary>
|
|||
/// Return peak memory usage
|
|||
/// </summary>
|
|||
PeakMemory = 2, |
|||
|
|||
/// <summary>
|
|||
/// Return peak memory usage and reset counter
|
|||
/// </summary>
|
|||
PeakMemoryReset = -1 |
|||
} |
|||
} |
|||
} |
|||
|
|||
#endif
|
|||
@ -0,0 +1,66 @@ |
|||
// <copyright file="MklProviderPrecision.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-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.
|
|||
// </copyright>
|
|||
|
|||
using System; |
|||
|
|||
namespace MathNet.Numerics.Providers.Common.Mkl |
|||
{ |
|||
/// <summary>
|
|||
/// Consistency vs. performance trade-off between runs on different machines.
|
|||
/// </summary>
|
|||
public enum MklConsistency : int |
|||
{ |
|||
/// <summary>Consistent on the same CPU only (maximum performance)</summary>
|
|||
Auto = 2, |
|||
/// <summary>Consistent on Intel and compatible CPUs with SSE2 support (maximum compatibility)</summary>
|
|||
Compatible = 3, |
|||
/// <summary>Consistent on Intel CPUs supporting SSE2 or later</summary>
|
|||
SSE2 = 4, |
|||
/// <summary>Consistent on Intel CPUs supporting SSE4.2 or later</summary>
|
|||
SSE4_2 = 8, |
|||
/// <summary>Consistent on Intel CPUs supporting AVX or later</summary>
|
|||
AVX = 9, |
|||
/// <summary>Consistent on Intel CPUs supporting AVX2 or later</summary>
|
|||
AVX2 = 10 |
|||
} |
|||
|
|||
[CLSCompliant(false)] |
|||
public enum MklAccuracy : uint |
|||
{ |
|||
Low = 0x1, |
|||
High = 0x2 |
|||
} |
|||
|
|||
[CLSCompliant(false)] |
|||
public enum MklPrecision : uint |
|||
{ |
|||
Single = 0x10, |
|||
Double = 0x20 |
|||
} |
|||
} |
|||
@ -0,0 +1,125 @@ |
|||
// <copyright file="OpenBlasProvider.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-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.
|
|||
// </copyright>
|
|||
|
|||
#if NATIVE
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace MathNet.Numerics.Providers.Common.OpenBlas |
|||
{ |
|||
internal static class OpenBlasProvider |
|||
{ |
|||
static int _nativeRevision; |
|||
static bool _nativeX86; |
|||
static bool _nativeX64; |
|||
static bool _nativeIA64; |
|||
static bool _nativeARM; |
|||
|
|||
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 |
|||
{ |
|||
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; |
|||
_nativeARM = SafeNativeMethods.query_capability((int)ProviderPlatform.arm) > 0; |
|||
} |
|||
catch (DllNotFoundException e) |
|||
{ |
|||
throw new NotSupportedException("OpenBLAS Native Provider not found.", e); |
|||
} |
|||
catch (BadImageFormatException e) |
|||
{ |
|||
throw new NotSupportedException("OpenBLAS 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("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 < minRevision) |
|||
{ |
|||
throw new NotSupportedException("OpenBLAS Native Provider too old. Consider upgrading to a newer version."); |
|||
} |
|||
|
|||
ConfigureThreading(); |
|||
} |
|||
|
|||
static void ConfigureThreading() |
|||
{ |
|||
// set threading settings, if supported
|
|||
if (SafeNativeMethods.query_capability((int)ProviderConfig.Threading) > 0) |
|||
{ |
|||
SafeNativeMethods.set_max_threads(Control.MaxDegreeOfParallelism); |
|||
} |
|||
} |
|||
|
|||
public static string Describe() |
|||
{ |
|||
var parts = new List<string>(); |
|||
if (_nativeX86) parts.Add("x86"); |
|||
if (_nativeX64) parts.Add("x64"); |
|||
if (_nativeIA64) parts.Add("IA64"); |
|||
if (_nativeARM) parts.Add("ARM"); |
|||
parts.Add("revision " + _nativeRevision); |
|||
|
|||
return string.Concat("OpenBLAS (", string.Join("; ", parts), ")"); |
|||
} |
|||
} |
|||
} |
|||
|
|||
#endif
|
|||
@ -0,0 +1,101 @@ |
|||
// <copyright file="FourierTransformControl.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-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.
|
|||
// </copyright>
|
|||
|
|||
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() |
|||
{ |
|||
#if NATIVE
|
|||
var value = Environment.GetEnvironmentVariable(EnvVarFFTProvider); |
|||
switch (value != null ? value.ToUpperInvariant() : string.Empty) |
|||
{ |
|||
|
|||
case "MKL": |
|||
UseNativeMKL(); |
|||
break; |
|||
|
|||
default: |
|||
UseBest(); |
|||
break; |
|||
} |
|||
#else
|
|||
UseManaged(); |
|||
#endif
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,64 @@ |
|||
// <copyright file="IFourierTransformProvider.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-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.
|
|||
// </copyright>
|
|||
|
|||
namespace MathNet.Numerics.Providers.FourierTransform |
|||
{ |
|||
|
|||
#if !NOSYSNUMERICS
|
|||
using Complex = System.Numerics.Complex; |
|||
#endif
|
|||
|
|||
public enum FourierTransformScaling : int |
|||
{ |
|||
NoScaling = 0, |
|||
SymmetricScaling = 1, |
|||
BackwardScaling = 2, |
|||
ForwardScaling = 3 |
|||
} |
|||
|
|||
public interface IFourierTransformProvider |
|||
{ |
|||
/// <summary>
|
|||
/// 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.
|
|||
/// </summary>
|
|||
bool IsAvailable(); |
|||
|
|||
/// <summary>
|
|||
/// Initialize and verify that the provided is indeed available. If not, fall back to alternatives like the managed provider
|
|||
/// </summary>
|
|||
void InitializeVerify(); |
|||
|
|||
void ForwardInplace(Complex[] complex, FourierTransformScaling scaling); |
|||
void BackwardInplace(Complex[] complex, FourierTransformScaling scaling); |
|||
|
|||
Complex[] Forward(Complex[] complexTimeSpace, FourierTransformScaling scaling); |
|||
Complex[] Backward(Complex[] complexFrequenceSpace, FourierTransformScaling scaling); |
|||
} |
|||
} |
|||
@ -0,0 +1,111 @@ |
|||
// <copyright file="ManagedFourierTransformProvider.cs" company="Math.NET">
|
|||
// 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.
|
|||
// </copyright>
|
|||
|
|||
using System.Collections; |
|||
using MathNet.Numerics.IntegralTransforms; |
|||
|
|||
namespace MathNet.Numerics.Providers.FourierTransform |
|||
{ |
|||
|
|||
#if !NOSYSNUMERICS
|
|||
using Complex = System.Numerics.Complex; |
|||
#endif
|
|||
|
|||
public class ManagedFourierTransformProvider : IFourierTransformProvider |
|||
{ |
|||
/// <summary>
|
|||
/// 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.
|
|||
/// </summary>
|
|||
public bool IsAvailable() |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initialize and verify that the provided is indeed available. If not, fall back to alternatives like the managed provider
|
|||
/// </summary>
|
|||
public void InitializeVerify() |
|||
{ |
|||
} |
|||
|
|||
public string ToString() |
|||
{ |
|||
return "Managed"; |
|||
} |
|||
|
|||
public void ForwardInplace(Complex[] complex, FourierTransformScaling scaling) |
|||
{ |
|||
switch (scaling) |
|||
{ |
|||
case FourierTransformScaling.SymmetricScaling: |
|||
Fourier.BluesteinForward(complex, FourierOptions.Default); |
|||
break; |
|||
case FourierTransformScaling.ForwardScaling: |
|||
// Only backward scaling can be expressed with options, hence the double-inverse
|
|||
Fourier.BluesteinInverse(complex, FourierOptions.AsymmetricScaling | FourierOptions.InverseExponent); |
|||
break; |
|||
default: |
|||
Fourier.BluesteinForward(complex, FourierOptions.NoScaling); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
public void BackwardInplace(Complex[] complex, FourierTransformScaling scaling) |
|||
{ |
|||
switch (scaling) |
|||
{ |
|||
case FourierTransformScaling.SymmetricScaling: |
|||
Fourier.BluesteinInverse(complex, FourierOptions.Default); |
|||
break; |
|||
case FourierTransformScaling.BackwardScaling: |
|||
Fourier.BluesteinInverse(complex, FourierOptions.AsymmetricScaling); |
|||
break; |
|||
default: |
|||
Fourier.BluesteinInverse(complex, FourierOptions.NoScaling); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
public Complex[] Forward(Complex[] complexTimeSpace, FourierTransformScaling scaling) |
|||
{ |
|||
Complex[] work = new Complex[complexTimeSpace.Length]; |
|||
complexTimeSpace.Copy(work); |
|||
ForwardInplace(work, scaling); |
|||
return work; |
|||
} |
|||
|
|||
public Complex[] Backward(Complex[] complexFrequenceSpace, FourierTransformScaling scaling) |
|||
{ |
|||
Complex[] work = new Complex[complexFrequenceSpace.Length]; |
|||
complexFrequenceSpace.Copy(work); |
|||
BackwardInplace(work, scaling); |
|||
return work; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,183 @@ |
|||
// <copyright file="MklFourierTransformProvider.cs" company="Math.NET">
|
|||
// 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.
|
|||
// </copyright>
|
|||
|
|||
#if NATIVE
|
|||
|
|||
using System; |
|||
using System.Numerics; |
|||
using MathNet.Numerics.Providers.Common.Mkl; |
|||
|
|||
namespace MathNet.Numerics.Providers.FourierTransform.Mkl |
|||
{ |
|||
public class MklFourierTransformProvider : IFourierTransformProvider |
|||
{ |
|||
/// <summary>
|
|||
/// 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.
|
|||
/// </summary>
|
|||
public bool IsAvailable() |
|||
{ |
|||
return MklProvider.IsAvailable(minRevision: 11); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initialize and verify that the provided is indeed available. If not, fall back to alternatives like the managed provider
|
|||
/// </summary>
|
|||
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)); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Frees the memory allocated to the MKL memory pool.
|
|||
/// </summary>
|
|||
public void FreeBuffers() |
|||
{ |
|||
MklProvider.FreeBuffers(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Frees the memory allocated to the MKL memory pool on the current thread.
|
|||
/// </summary>
|
|||
public void ThreadFreeBuffers() |
|||
{ |
|||
MklProvider.ThreadFreeBuffers(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Disable the MKL memory pool. May impact performance.
|
|||
/// </summary>
|
|||
public void DisableMemoryPool() |
|||
{ |
|||
MklProvider.DisableMemoryPool(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Retrieves information about the MKL memory pool.
|
|||
/// </summary>
|
|||
/// <param name="allocatedBuffers">On output, returns the number of memory buffers allocated.</param>
|
|||
/// <returns>Returns the number of bytes allocated to all memory buffers.</returns>
|
|||
public long MemoryStatistics(out int allocatedBuffers) |
|||
{ |
|||
return MklProvider.MemoryStatistics(out allocatedBuffers); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Enable gathering of peak memory statistics of the MKL memory pool.
|
|||
/// </summary>
|
|||
public void EnablePeakMemoryStatistics() |
|||
{ |
|||
MklProvider.EnablePeakMemoryStatistics(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Disable gathering of peak memory statistics of the MKL memory pool.
|
|||
/// </summary>
|
|||
public void DisablePeakMemoryStatistics() |
|||
{ |
|||
MklProvider.DisablePeakMemoryStatistics(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Measures peak memory usage of the MKL memory pool.
|
|||
/// </summary>
|
|||
/// <param name="reset">Whether the usage counter should be reset.</param>
|
|||
/// <returns>The peak number of bytes allocated to all memory buffers.</returns>
|
|||
public long PeakMemoryStatistics(bool reset = true) |
|||
{ |
|||
return MklProvider.PeakMemoryStatistics(reset); |
|||
} |
|||
|
|||
public override string ToString() |
|||
{ |
|||
return MklProvider.Describe(); |
|||
} |
|||
|
|||
public void ForwardInplace(Complex[] complex, FourierTransformScaling scaling) |
|||
{ |
|||
SafeNativeMethods.z_fft_forward_inplace(complex.Length, ForwardScaling(scaling, complex.Length), complex); |
|||
} |
|||
|
|||
public void BackwardInplace(Complex[] complex, FourierTransformScaling scaling) |
|||
{ |
|||
SafeNativeMethods.z_fft_backward_inplace(complex.Length, BackwardScaling(scaling, complex.Length), complex); |
|||
} |
|||
|
|||
public Complex[] Forward(Complex[] complexTimeSpace, FourierTransformScaling scaling) |
|||
{ |
|||
Complex[] work = new Complex[complexTimeSpace.Length]; |
|||
complexTimeSpace.Copy(work); |
|||
ForwardInplace(work, scaling); |
|||
return work; |
|||
} |
|||
|
|||
public Complex[] Backward(Complex[] complexFrequenceSpace, FourierTransformScaling scaling) |
|||
{ |
|||
Complex[] work = new Complex[complexFrequenceSpace.Length]; |
|||
complexFrequenceSpace.Copy(work); |
|||
BackwardInplace(work, scaling); |
|||
return work; |
|||
} |
|||
|
|||
static double ForwardScaling(FourierTransformScaling scaling, int length) |
|||
{ |
|||
switch (scaling) |
|||
{ |
|||
case FourierTransformScaling.SymmetricScaling: |
|||
return Math.Sqrt(1.0/length); |
|||
case FourierTransformScaling.ForwardScaling: |
|||
return 1.0/length; |
|||
default: |
|||
return 1.0; |
|||
} |
|||
} |
|||
|
|||
static double BackwardScaling(FourierTransformScaling scaling, int length) |
|||
{ |
|||
switch (scaling) |
|||
{ |
|||
case FourierTransformScaling.SymmetricScaling: |
|||
return Math.Sqrt(1.0/length); |
|||
case FourierTransformScaling.BackwardScaling: |
|||
return 1.0/length; |
|||
default: |
|||
return 1.0; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
#endif
|
|||
@ -0,0 +1,122 @@ |
|||
// <copyright file="LinearAlgebraControl.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-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.
|
|||
// </copyright>
|
|||
|
|||
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() |
|||
{ |
|||
#if NATIVE
|
|||
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: |
|||
UseBest(); |
|||
break; |
|||
} |
|||
#else
|
|||
UseManaged(); |
|||
#endif
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,103 @@ |
|||
// <copyright file="FourierTransformProviderTests.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-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.
|
|||
// </copyright>
|
|||
|
|||
using System; |
|||
using MathNet.Numerics.Distributions; |
|||
using MathNet.Numerics.Providers.FourierTransform; |
|||
using MathNet.Numerics.Statistics; |
|||
using NUnit.Framework; |
|||
|
|||
namespace MathNet.Numerics.UnitTests.FourierTransformProviderTests |
|||
{ |
|||
#if NOSYSNUMERICS
|
|||
using Complex = Numerics.Complex; |
|||
#else
|
|||
using Complex = System.Numerics.Complex; |
|||
#endif
|
|||
|
|||
/// <summary>
|
|||
/// Base class for linear algebra provider tests.
|
|||
/// </summary>
|
|||
[TestFixture, Category("LAProvider")] |
|||
public class LinearAlgebraProviderTests |
|||
{ |
|||
[Test] |
|||
public void ForwardInplaceRealSine() |
|||
{ |
|||
var samples = Generate.PeriodicMap(16, w => new Complex(Math.Sin(w), 0), 16, 1.0, Constants.Pi2); |
|||
var spectrum = new Complex[samples.Length]; |
|||
|
|||
// real-odd transforms to imaginary odd
|
|||
samples.Copy(spectrum); |
|||
Control.FourierTransformProvider.ForwardInplace(spectrum, FourierTransformScaling.BackwardScaling); |
|||
|
|||
// all real components must be zero
|
|||
foreach (var c in spectrum) |
|||
{ |
|||
Assert.AreEqual(0, c.Real, 1e-12, "real"); |
|||
} |
|||
|
|||
// all imaginary components except second and last musth be zero
|
|||
for (var i = 0; i < spectrum.Length; i++) |
|||
{ |
|||
if (i == 1) |
|||
{ |
|||
Assert.AreEqual(-8, spectrum[i].Imaginary, 1e-12, "imag second"); |
|||
} |
|||
else if (i == spectrum.Length - 1) |
|||
{ |
|||
Assert.AreEqual(8, spectrum[i].Imaginary, 1e-12, "imag last"); |
|||
} |
|||
else |
|||
{ |
|||
Assert.AreEqual(0, spectrum[i].Imaginary, 1e-12, "imag"); |
|||
} |
|||
} |
|||
} |
|||
|
|||
[TestCase(0x1000)] |
|||
[TestCase(0x7FF)] |
|||
public void ForwardInplaceParsevalTheorem(int count) |
|||
{ |
|||
var samples = Generate.RandomComplex(count, GetUniform(1)); |
|||
var timeSpaceEnergy = Generate.Map(samples, s => s.MagnitudeSquared()).Mean(); |
|||
|
|||
Control.FourierTransformProvider.ForwardInplace(samples, FourierTransformScaling.SymmetricScaling); |
|||
var frequencySpaceEnergy = Generate.Map(samples, s => s.MagnitudeSquared()).Mean(); |
|||
|
|||
Assert.AreEqual(timeSpaceEnergy, frequencySpaceEnergy, 1e-12); |
|||
} |
|||
|
|||
IContinuousDistribution GetUniform(int seed) |
|||
{ |
|||
return new ContinuousUniform(-1, 1, new System.Random(seed)); |
|||
} |
|||
|
|||
} |
|||
} |
|||
Loading…
Reference in new issue