From 3bef6497ca7af4b3d3cff7886fba8fec34341ae9 Mon Sep 17 00:00:00 2001 From: Christoph Ruegg Date: Tue, 25 Oct 2016 16:30:06 +0200 Subject: [PATCH] LA-MKL: bind dot-power to MKL vector functions --- src/NativeProviders/MKL/capabilities.cpp | 2 + src/NativeProviders/MKL/vector_functions.c | 18 ++++++++ .../Common/Mkl/MklProviderCapabilities.cs | 2 + .../Providers/Common/Mkl/SafeNativeMethods.cs | 12 ++++++ .../Mkl/MklLinearAlgebraProvider.Complex.cs | 41 +++++++++++++++++++ .../Mkl/MklLinearAlgebraProvider.Complex32.cs | 41 +++++++++++++++++++ .../Mkl/MklLinearAlgebraProvider.Double.cs | 41 +++++++++++++++++++ .../Mkl/MklLinearAlgebraProvider.Single.cs | 41 +++++++++++++++++++ 8 files changed, 198 insertions(+) diff --git a/src/NativeProviders/MKL/capabilities.cpp b/src/NativeProviders/MKL/capabilities.cpp index 0c86282e..ae675c6b 100644 --- a/src/NativeProviders/MKL/capabilities.cpp +++ b/src/NativeProviders/MKL/capabilities.cpp @@ -69,6 +69,8 @@ extern "C" { // LINEAR ALGEBRA case 128: return 2; // basic dense linear algebra (major - breaking) case 129: return 0; // basic dense linear algebra (minor - non-breaking) + case 130: return 0; // vector functions (major - breaking) + case 131: return 1; // vector functions (minor - non-breaking) // OPTIMIZATION case 256: return 0; // basic optimization diff --git a/src/NativeProviders/MKL/vector_functions.c b/src/NativeProviders/MKL/vector_functions.c index c1bea343..5c6578aa 100644 --- a/src/NativeProviders/MKL/vector_functions.c +++ b/src/NativeProviders/MKL/vector_functions.c @@ -4,6 +4,7 @@ #if __cplusplus extern "C" { #endif + DLLEXPORT void s_vector_add( const int n, const float x[], const float y[], float result[] ){ vsAdd( n, x, y, result ); } @@ -20,6 +21,10 @@ DLLEXPORT void s_vector_divide( const int n, const float x[], const float y[], f vsDiv( n, x, y, result ); } +DLLEXPORT void s_vector_power(const int n, const float x[], const float y[], float result[]) { + vsPow(n, x, y, result); +} + DLLEXPORT void d_vector_add( const int n, const double x[], const double y[], double result[] ){ vdAdd( n, x, y, result ); } @@ -36,6 +41,10 @@ DLLEXPORT void d_vector_divide( const int n, const double x[], const double y[], vdDiv( n, x, y, result ); } +DLLEXPORT void d_vector_power(const int n, const double x[], const double y[], double result[]) { + vdPow(n, x, y, result); +} + DLLEXPORT void c_vector_add( const int n, const MKL_Complex8 x[], const MKL_Complex8 y[], MKL_Complex8 result[] ){ vcAdd( n, x, y, result ); } @@ -52,6 +61,10 @@ DLLEXPORT void c_vector_divide( const int n, const MKL_Complex8 x[], const MKL_C vcDiv( n, x, y, result ); } +DLLEXPORT void c_vector_power(const int n, const MKL_Complex8 x[], const MKL_Complex8 y[], MKL_Complex8 result[]) { + vcPow(n, x, y, result); +} + DLLEXPORT void z_vector_add( const int n, const MKL_Complex16 x[], const MKL_Complex16 y[], MKL_Complex16 result[] ){ vzAdd( n, x, y, result ); } @@ -67,6 +80,11 @@ DLLEXPORT void z_vector_multiply( const int n, const MKL_Complex16 x[], const MK DLLEXPORT void z_vector_divide( const int n, const MKL_Complex16 x[], const MKL_Complex16 y[], MKL_Complex16 result[] ){ vzDiv( n, x, y, result ); } + +DLLEXPORT void z_vector_power(const int n, const MKL_Complex16 x[], const MKL_Complex16 y[], MKL_Complex16 result[]) { + vzPow(n, x, y, result); +} + #if __cplusplus } #endif diff --git a/src/Numerics/Providers/Common/Mkl/MklProviderCapabilities.cs b/src/Numerics/Providers/Common/Mkl/MklProviderCapabilities.cs index 4e692bab..711c15b4 100644 --- a/src/Numerics/Providers/Common/Mkl/MklProviderCapabilities.cs +++ b/src/Numerics/Providers/Common/Mkl/MklProviderCapabilities.cs @@ -53,6 +53,8 @@ namespace MathNet.Numerics.Providers.Common.Mkl { LinearAlgebraMajor = 128, LinearAlgebraMinor = 129, + VectorFunctionsMajor = 130, + VectorFunctionsMinor = 131, FourierTransformMajor = 384, FourierTransformMinor = 385 } diff --git a/src/Numerics/Providers/Common/Mkl/SafeNativeMethods.cs b/src/Numerics/Providers/Common/Mkl/SafeNativeMethods.cs index 170c74fc..7d84f097 100644 --- a/src/Numerics/Providers/Common/Mkl/SafeNativeMethods.cs +++ b/src/Numerics/Providers/Common/Mkl/SafeNativeMethods.cs @@ -331,6 +331,9 @@ namespace MathNet.Numerics.Providers.Common.Mkl [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] internal static extern void s_vector_divide(int n, float[] x, float[] y, [In, Out] float[] result); + [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] + internal static extern void s_vector_power(int n, float[] x, float[] y, [In, Out] float[] result); + [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] internal static extern void d_vector_add(int n, double[] x, double[] y, [In, Out] double[] result); @@ -343,6 +346,9 @@ namespace MathNet.Numerics.Providers.Common.Mkl [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] internal static extern void d_vector_divide(int n, double[] x, double[] y, [In, Out] double[] result); + [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] + internal static extern void d_vector_power(int n, double[] x, double[] y, [In, Out] double[] result); + [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] internal static extern void c_vector_add(int n, Complex32[] x, Complex32[] y, [In, Out] Complex32[] result); @@ -355,6 +361,9 @@ namespace MathNet.Numerics.Providers.Common.Mkl [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] internal static extern void c_vector_divide(int n, Complex32[] x, Complex32[] y, [In, Out] Complex32[] result); + [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] + internal static extern void c_vector_power(int n, Complex32[] x, Complex32[] y, [In, Out] Complex32[] result); + [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] internal static extern void z_vector_add(int n, Complex[] x, Complex[] y, [In, Out] Complex[] result); @@ -367,6 +376,9 @@ namespace MathNet.Numerics.Providers.Common.Mkl [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] internal static extern void z_vector_divide(int n, Complex[] x, Complex[] y, [In, Out] Complex[] result); + [DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] + internal static extern void z_vector_power(int n, Complex[] x, Complex[] y, [In, Out] Complex[] result); + #endregion Vector Functions #region FFT diff --git a/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Complex.cs b/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Complex.cs index 880620c4..aad6a388 100644 --- a/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Complex.cs +++ b/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Complex.cs @@ -1056,6 +1056,47 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl SafeNativeMethods.z_vector_multiply(x.Length, x, y, result); } + /// + /// Does a point wise power of two arrays z = x ^ y. This can be used + /// to raise elements of vectors or matrices to the powers of another vector or matrix. + /// + /// The array x. + /// The array y. + /// The result of the point wise power. + /// There is no equivalent BLAS routine, but many libraries + /// provide optimized (parallel and/or vectorized) versions of this + /// routine. + public override void PointWisePowerArrays(Complex[] x, Complex[] y, Complex[] result) + { + if (SafeNativeMethods.query_capability((int)ProviderCapability.LinearAlgebraMajor) != 0 || + SafeNativeMethods.query_capability((int)ProviderCapability.LinearAlgebraMinor) < 1) + { + base.PointWisePowerArrays(x, y, result); + } + + if (y == null) + { + throw new ArgumentNullException("y"); + } + + if (x == null) + { + throw new ArgumentNullException("x"); + } + + if (x.Length != y.Length) + { + throw new ArgumentException(Resources.ArgumentArraysSameLength); + } + + if (x.Length != result.Length) + { + throw new ArgumentException(Resources.ArgumentArraysSameLength); + } + + SafeNativeMethods.z_vector_power(x.Length, x, y, result); + } + /// /// Does a point wise division of two arrays z = x / y. This can be used /// to divide elements of vectors or matrices. diff --git a/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Complex32.cs b/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Complex32.cs index 901020c2..58892033 100644 --- a/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Complex32.cs +++ b/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Complex32.cs @@ -1086,6 +1086,47 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl SafeNativeMethods.c_vector_divide(x.Length, x, y, result); } + /// + /// Does a point wise power of two arrays z = x ^ y. This can be used + /// to raise elements of vectors or matrices to the powers of another vector or matrix. + /// + /// The array x. + /// The array y. + /// The result of the point wise power. + /// There is no equivalent BLAS routine, but many libraries + /// provide optimized (parallel and/or vectorized) versions of this + /// routine. + public override void PointWisePowerArrays(Complex32[] x, Complex32[] y, Complex32[] result) + { + if (SafeNativeMethods.query_capability((int)ProviderCapability.LinearAlgebraMajor) != 0 || + SafeNativeMethods.query_capability((int)ProviderCapability.LinearAlgebraMinor) < 1) + { + base.PointWisePowerArrays(x, y, result); + } + + if (y == null) + { + throw new ArgumentNullException("y"); + } + + if (x == null) + { + throw new ArgumentNullException("x"); + } + + if (x.Length != y.Length) + { + throw new ArgumentException(Resources.ArgumentArraysSameLength); + } + + if (x.Length != result.Length) + { + throw new ArgumentException(Resources.ArgumentArraysSameLength); + } + + SafeNativeMethods.c_vector_power(x.Length, x, y, result); + } + /// /// Computes the eigenvalues and eigenvectors of a matrix. /// diff --git a/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Double.cs b/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Double.cs index f6712217..607666d1 100644 --- a/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Double.cs +++ b/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Double.cs @@ -1091,6 +1091,47 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl SafeNativeMethods.d_vector_divide(x.Length, x, y, result); } + /// + /// Does a point wise power of two arrays z = x ^ y. This can be used + /// to raise elements of vectors or matrices to the powers of another vector or matrix. + /// + /// The array x. + /// The array y. + /// The result of the point wise power. + /// There is no equivalent BLAS routine, but many libraries + /// provide optimized (parallel and/or vectorized) versions of this + /// routine. + public override void PointWisePowerArrays(double[] x, double[] y, double[] result) + { + if (SafeNativeMethods.query_capability((int)ProviderCapability.LinearAlgebraMajor) != 0 || + SafeNativeMethods.query_capability((int)ProviderCapability.LinearAlgebraMinor) < 1) + { + base.PointWisePowerArrays(x, y, result); + } + + if (y == null) + { + throw new ArgumentNullException("y"); + } + + if (x == null) + { + throw new ArgumentNullException("x"); + } + + if (x.Length != y.Length) + { + throw new ArgumentException(Resources.ArgumentArraysSameLength); + } + + if (x.Length != result.Length) + { + throw new ArgumentException(Resources.ArgumentArraysSameLength); + } + + SafeNativeMethods.d_vector_power(x.Length, x, y, result); + } + /// /// Computes the eigenvalues and eigenvectors of a matrix. /// diff --git a/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Single.cs b/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Single.cs index 2a9a2c79..2cc0d87a 100644 --- a/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Single.cs +++ b/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Single.cs @@ -1086,6 +1086,47 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl SafeNativeMethods.s_vector_divide(x.Length, x, y, result); } + /// + /// Does a point wise power of two arrays z = x ^ y. This can be used + /// to raise elements of vectors or matrices to the powers of another vector or matrix. + /// + /// The array x. + /// The array y. + /// The result of the point wise power. + /// There is no equivalent BLAS routine, but many libraries + /// provide optimized (parallel and/or vectorized) versions of this + /// routine. + public override void PointWisePowerArrays(float[] x, float[] y, float[] result) + { + if (SafeNativeMethods.query_capability((int)ProviderCapability.LinearAlgebraMajor) != 0 || + SafeNativeMethods.query_capability((int)ProviderCapability.LinearAlgebraMinor) < 1) + { + base.PointWisePowerArrays(x, y, result); + } + + if (y == null) + { + throw new ArgumentNullException("y"); + } + + if (x == null) + { + throw new ArgumentNullException("x"); + } + + if (x.Length != y.Length) + { + throw new ArgumentException(Resources.ArgumentArraysSameLength); + } + + if (x.Length != result.Length) + { + throw new ArgumentException(Resources.ArgumentArraysSameLength); + } + + SafeNativeMethods.s_vector_power(x.Length, x, y, result); + } + /// /// Computes the eigenvalues and eigenvectors of a matrix. ///