diff --git a/MathNet.Numerics.NativeProviders.sln b/MathNet.Numerics.NativeProviders.sln index 141b7074..25a8d6e1 100644 --- a/MathNet.Numerics.NativeProviders.sln +++ b/MathNet.Numerics.NativeProviders.sln @@ -20,6 +20,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Numerics", "src\Numerics\Nu EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests-MKL", "src\UnitTests\UnitTests-MKL.csproj", "{3515A344-AB5F-41C7-A14C-04A79B3FFAB1}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenBLAS", "src\NativeProviders\Windows\OpenBLAS\OpenBLASWrapper.vcxproj", "{CB4011B6-E9A7-480B-A7B1-8492039DAAD1}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -111,6 +113,27 @@ Global {3515A344-AB5F-41C7-A14C-04A79B3FFAB1}.Release-Signed|Mixed Platforms.Build.0 = Release|Any CPU {3515A344-AB5F-41C7-A14C-04A79B3FFAB1}.Release-Signed|Win32.ActiveCfg = Release|Any CPU {3515A344-AB5F-41C7-A14C-04A79B3FFAB1}.Release-Signed|x64.ActiveCfg = Release|Any CPU + {CB4011B6-E9A7-480B-A7B1-8492039DAAD1}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {CB4011B6-E9A7-480B-A7B1-8492039DAAD1}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {CB4011B6-E9A7-480B-A7B1-8492039DAAD1}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {CB4011B6-E9A7-480B-A7B1-8492039DAAD1}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB4011B6-E9A7-480B-A7B1-8492039DAAD1}.Debug|Win32.Build.0 = Debug|Win32 + {CB4011B6-E9A7-480B-A7B1-8492039DAAD1}.Debug|x64.ActiveCfg = Debug|x64 + {CB4011B6-E9A7-480B-A7B1-8492039DAAD1}.Debug|x64.Build.0 = Debug|x64 + {CB4011B6-E9A7-480B-A7B1-8492039DAAD1}.Release|Any CPU.ActiveCfg = Release|Win32 + {CB4011B6-E9A7-480B-A7B1-8492039DAAD1}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {CB4011B6-E9A7-480B-A7B1-8492039DAAD1}.Release|Mixed Platforms.Build.0 = Release|Win32 + {CB4011B6-E9A7-480B-A7B1-8492039DAAD1}.Release|Win32.ActiveCfg = Release|Win32 + {CB4011B6-E9A7-480B-A7B1-8492039DAAD1}.Release|Win32.Build.0 = Release|Win32 + {CB4011B6-E9A7-480B-A7B1-8492039DAAD1}.Release|x64.ActiveCfg = Release|x64 + {CB4011B6-E9A7-480B-A7B1-8492039DAAD1}.Release|x64.Build.0 = Release|x64 + {CB4011B6-E9A7-480B-A7B1-8492039DAAD1}.Release-Signed|Any CPU.ActiveCfg = Release|Win32 + {CB4011B6-E9A7-480B-A7B1-8492039DAAD1}.Release-Signed|Mixed Platforms.ActiveCfg = Release|Win32 + {CB4011B6-E9A7-480B-A7B1-8492039DAAD1}.Release-Signed|Mixed Platforms.Build.0 = Release|Win32 + {CB4011B6-E9A7-480B-A7B1-8492039DAAD1}.Release-Signed|Win32.ActiveCfg = Release|Win32 + {CB4011B6-E9A7-480B-A7B1-8492039DAAD1}.Release-Signed|Win32.Build.0 = Release|Win32 + {CB4011B6-E9A7-480B-A7B1-8492039DAAD1}.Release-Signed|x64.ActiveCfg = Release|x64 + {CB4011B6-E9A7-480B-A7B1-8492039DAAD1}.Release-Signed|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/NativeProviders/OpenBLAS/blas.c b/src/NativeProviders/OpenBLAS/blas.c new file mode 100644 index 00000000..cc41f49e --- /dev/null +++ b/src/NativeProviders/OpenBLAS/blas.c @@ -0,0 +1,89 @@ +#include "cblas.h" +#include "wrapper_common.h" + +#if GCC +extern "C" { +#endif +DLLEXPORT void s_axpy(const blasint n, const float alpha, const float x[], float y[]){ + cblas_saxpy(n, alpha, x, 1, y, 1); +} + +DLLEXPORT void d_axpy(const blasint n, const double alpha, const double x[], double y[]){ + cblas_daxpy(n, alpha, x, 1, y, 1); +} + +DLLEXPORT void c_axpy(const blasint n, const openblas_complex_float alpha, const openblas_complex_float x[], openblas_complex_float y[]){ + cblas_caxpy(n, &(alpha.real), &(x->real), 1, &(y->real), 1); +} + +DLLEXPORT void z_axpy(const blasint n, const openblas_complex_double alpha, const openblas_complex_double x[], openblas_complex_double y[]){ + cblas_zaxpy(n, &(alpha.real), &(x->real), 1, &(y->real), 1); +} + +DLLEXPORT void s_scale(const blasint n, const float alpha, float x[]){ + cblas_sscal(n, alpha, x, 1); +} + +DLLEXPORT void d_scale(const blasint n, const double alpha, double x[]){ + cblas_dscal(n, alpha, x, 1); +} + +DLLEXPORT void c_scale(const blasint n, const openblas_complex_float alpha, openblas_complex_float x[]){ + cblas_cscal(n, &(alpha.real), &(x->real), 1); +} + +DLLEXPORT void z_scale(const blasint n, const openblas_complex_double alpha, openblas_complex_double x[]){ + cblas_zscal(n, &(alpha.real), &(x->real), 1); +} + +DLLEXPORT float s_dot_product(const blasint n, const float x[], const float y[]){ + return cblas_sdot(n, x, 1, y, 1); +} + +DLLEXPORT double d_dot_product(const blasint n, const double x[], const double y[]){ + return cblas_ddot(n, x, 1, y, 1); +} + +DLLEXPORT openblas_complex_float c_dot_product(const blasint n, const openblas_complex_float x[], const openblas_complex_float y[]){ + openblas_complex_float ret; + cblas_cdotu_sub(n, &(x->real), 1, &(y->real), 1, &ret); + return ret; +} + +DLLEXPORT openblas_complex_double z_dot_product(const blasint n, const openblas_complex_double x[], const openblas_complex_double y[]){ + openblas_complex_double ret; + cblas_zdotu_sub(n, &(x->real), 1, &(y->real), 1, &ret); + return ret; +} + +DLLEXPORT void s_matrix_multiply(CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB, const blasint m, const blasint n, const blasint k, const float alpha, const float x[], const float y[], const float beta, float c[]){ + blasint lda = transA == CblasNoTrans ? m : k; + blasint ldb = transB == CblasNoTrans ? k : n; + + cblas_sgemm(CblasColMajor, transA, transB, m, n, k, alpha, x, lda, y, ldb, beta, c, m); +} + +DLLEXPORT void d_matrix_multiply(CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB, const blasint m, const blasint n, const blasint k, const double alpha, const double x[], const double y[], const double beta, double c[]){ + blasint lda = transA == CblasNoTrans ? m : k; + blasint ldb = transB == CblasNoTrans ? k : n; + + cblas_dgemm(CblasColMajor, transA, transB, m, n, k, alpha, x, lda, y, ldb, beta, c, m); +} + +DLLEXPORT void c_matrix_multiply(CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB, const blasint m, const blasint n, const blasint k, const openblas_complex_float alpha, const openblas_complex_float x[], const openblas_complex_float y[], const openblas_complex_float beta, openblas_complex_float c[]){ + blasint lda = transA == CblasNoTrans ? m : k; + blasint ldb = transB == CblasNoTrans ? k : n; + + cblas_cgemm(CblasColMajor, transA, transB, m, n, k, &(alpha.real), &(x->real), lda, &(y->real), ldb, &(beta.real), &(c->real), m); +} + +DLLEXPORT void z_matrix_multiply(CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB, const blasint m, const blasint n, const blasint k, const openblas_complex_double alpha, const openblas_complex_double x[], const openblas_complex_double y[], const openblas_complex_double beta, openblas_complex_double c[]){ + blasint lda = transA == CblasNoTrans ? m : k; + blasint ldb = transB == CblasNoTrans ? k : n; + + cblas_zgemm(CblasColMajor, transA, transB, m, n, k, &(alpha.real), &(x->real), lda, &(y->real), ldb, &(beta.real), &(c->real), m); +} + +#if GCC +} +#endif diff --git a/src/NativeProviders/OpenBLAS/lapack.cpp b/src/NativeProviders/OpenBLAS/lapack.cpp new file mode 100644 index 00000000..0f641319 --- /dev/null +++ b/src/NativeProviders/OpenBLAS/lapack.cpp @@ -0,0 +1,752 @@ +#include "cblas.h" + +#define LAPACK_COMPLEX_CUSTOM + +template +struct complex +{ + T real, imag; + + complex(T _real = 0, T _imag = 0) + { + real = _real; + imag = _imag; + } + + complex(const complex& right) + { + real = right.real; + imag = right.imag; + } + + complex& operator=(const complex& right) + { + real = right.real; + imag = right.imag; + return *this; + } + + complex& operator=(const T& right) + { + real = right; + imag = 0; + return *this; + } + + template inline + complex& operator=(const complex<_Other>& right) + { + real = (T)right.real; + imag = (T)right.imag; + return *this; + } +}; + +#define lapack_complex_float complex +#define lapack_complex_double complex + +#include "lapacke.h" +#include "lapack_common.h" +#include "wrapper_common.h" +#include + +template +inline lapack_int lu_factor(lapack_int m, T a[], lapack_int ipiv[], GETRF getrf) +{ + lapack_int info = 0; + getrf(&m, &m, a, &m, ipiv, &info); + shift_ipiv_down(m, ipiv); + return info; +}; + +template +inline lapack_int lu_inverse(lapack_int n, T a[], T work[], lapack_int lwork, GETRF getrf, GETRI getri) +{ + lapack_int* ipiv = new lapack_int[n]; + lapack_int info = 0; + getrf(&n, &n, a, &n, ipiv, &info); + + if (info != 0) + { + delete[] ipiv; + return info; + } + + getri(&n, a, &n, ipiv, work, &lwork, &info); + delete[] ipiv; + return info; +}; + +template +inline lapack_int lu_inverse_factored(lapack_int n, T a[], lapack_int ipiv[], T work[], lapack_int lwork, GETRI getri) +{ + shift_ipiv_up(n, ipiv); + lapack_int info = 0; + getri(&n, a, &n, ipiv, work, &lwork, &info); + shift_ipiv_down(n, ipiv); + return info; +} + +template +inline lapack_int lu_solve_factored(lapack_int n, lapack_int nrhs, T a[], lapack_int ipiv[], T b[], GETRS getrs) +{ + shift_ipiv_up(n, ipiv); + lapack_int info = 0; + char trans ='N'; + getrs(&trans, &n, &nrhs, a, &n, ipiv, b, &n, &info); + shift_ipiv_down(n, ipiv); + return info; +} + +template +inline lapack_int lu_solve(lapack_int n, lapack_int nrhs, T a[], T b[], GETRF getrf, GETRS getrs) +{ + T* clone = Clone(n, n, a); + lapack_int* ipiv = new lapack_int[n]; + lapack_int info = 0; + getrf(&n, &n, clone, &n, ipiv, &info); + + if (info != 0) + { + delete[] ipiv; + delete[] clone; + return info; + } + + char trans ='N'; + getrs(&trans, &n, &nrhs, clone, &n, ipiv, b, &n, &info); + delete[] ipiv; + delete[] clone; + return info; +} + + +template +inline lapack_int cholesky_factor(lapack_int n, T* a, POTRF potrf) +{ + char uplo = 'L'; + lapack_int info = 0; + potrf(&uplo, &n, a, &n, &info); + T zero = T(); + + for (lapack_int i = 0; i < n; ++i) + { + lapack_int index = i * n; + + for (lapack_int j = 0; j < n && i > j; ++j) + { + a[index + j] = zero; + } + } + + return info; +} + +template +inline lapack_int cholesky_solve(lapack_int n, lapack_int nrhs, T a[], T b[], POTRF potrf, POTRS potrs) +{ + T* clone = Clone(n, n, a); + char uplo = 'L'; + lapack_int info = 0; + potrf(&uplo, &n, clone, &n, &info); + + if (info != 0) + { + delete[] clone; + return info; + } + + potrs(&uplo, &n, &nrhs, clone, &n, b, &n, &info); + delete[] clone; + return info; +} + +template +inline lapack_int cholesky_solve_factored(lapack_int n, lapack_int nrhs, T a[], T b[], POTRS potrs) +{ + char uplo = 'L'; + lapack_int info = 0; + potrs(&uplo, &n, &nrhs, a, &n, b, &n, &info); + return info; +} + +template +inline lapack_int qr_factor(lapack_int m, lapack_int n, T r[], T tau[], T q[], T work[], lapack_int len, GEQRF geqrf, ORGQR orgqr) +{ + lapack_int info = 0; + geqrf(&m, &n, r, &m, tau, work, &len, &info); + + for (lapack_int i = 0; i < m; ++i) + { + for (lapack_int j = 0; j < m && j < n; ++j) + { + if (i > j) + { + q[j * m + i] = r[j * m + i]; + } + } + } + + //compute the q elements explicitly + if (m <= n) + { + orgqr(&m, &m, &m, q, &m, tau, work, &len, &info); + } + else + { + orgqr(&m, &m, &n, q, &m, tau, work, &len, &info); + } + + return info; +} + +template +inline lapack_int qr_thin_factor(lapack_int m, lapack_int n, T q[], T tau[], T r[], T work[], lapack_int len, GEQRF geqrf, ORGQR orgqr) +{ + lapack_int info = 0; + geqrf(&m, &n, q, &m, tau, work, &len, &info); + + for (lapack_int i = 0; i < n; ++i) + { + for (lapack_int j = 0; j < n; ++j) + { + if (i <= j) + { + r[j * n + i] = q[j * m + i]; + } + } + } + + orgqr(&m, &n, &n, q, &m, tau, work, &len, &info); + return info; +} + +template +inline lapack_int qr_solve(lapack_int m, lapack_int n, lapack_int bn, T a[], T b[], T x[], T work[], lapack_int len, GELS gels) +{ + T* clone_a = Clone(m, n, a); + T* clone_b = Clone(m, bn, b); + char N = 'N'; + lapack_int info = 0; + gels(&N, &m, &n, &bn, clone_a, &m, clone_b, &m, work, &len, &info); + copyBtoX(m, n, bn, clone_b, x); + delete[] clone_a; + delete[] clone_b; + return info; +} + +template +inline lapack_int qr_solve_factored(lapack_int m, lapack_int n, lapack_int bn, T r[], T b[], T tau[], T x[], T work[], lapack_int len, ORMQR ormqr, TRSM trsm) +{ + T* clone_b = Clone(m, bn, b); + char side ='L'; + char tran = 'T'; + lapack_int info = 0; + ormqr(&side, &tran, &m, &bn, &n, r, &m, tau, clone_b, &m, work, &len, &info); + trsm(CblasColMajor, CblasLeft, CblasUpper, CblasNoTrans, CblasNonUnit, n, bn, 1.0, r, m, clone_b, m); + copyBtoX(m, n, bn, clone_b, x); + delete[] clone_b; + return info; +} + +template +inline lapack_int complex_qr_solve_factored(lapack_int m, lapack_int n, lapack_int bn, T r[], T b[], T tau[], T x[], T work[], lapack_int len, UNMQR unmqr, TRSM trsm) +{ + T* clone_b = Clone(m, bn, b); + char side ='L'; + char tran = 'C'; + lapack_int info = 0; + unmqr(&side, &tran, &m, &bn, &n, r, &m, tau, clone_b, &m, work, &len, &info); + T one = { 1.0f, 0.0f }; + trsm(CblasColMajor, CblasLeft, CblasUpper, CblasNoTrans, CblasNonUnit, n, bn, &(one.real), &(r->real), m, &(clone_b->real), m); + copyBtoX(m, n, bn, clone_b, x); + delete[] clone_b; + return info; +} + +template +inline lapack_int svd_factor(bool compute_vectors, lapack_int m, lapack_int n, T a[], T s[], T u[], T v[], T work[], lapack_int len, GESVD gesvd) +{ + lapack_int info = 0; + char job = compute_vectors ? 'A' : 'N'; + gesvd(&job, &job, &m, &n, a, &m, s, u, &m, v, &n, work, &len, &info); + return info; +} + +template +inline lapack_int complex_svd_factor(bool compute_vectors, lapack_int m, lapack_int n, T a[], T s[], T u[], T v[], T work[], lapack_int len, GESVD gesvd) +{ + lapack_int info = 0; + lapack_int dim_s = std::min(m,n); + R* rwork = new R[5 * dim_s]; + R* s_local = new R[dim_s]; + char job = compute_vectors ? 'A' : 'N'; + gesvd(&job, &job, &m, &n, a, &m, s_local, u, &m, v, &n, work, &len, rwork, &info); + + for (lapack_int index = 0; index < dim_s; ++index) + { + s[index] = s_local[index]; + } + + delete[] rwork; + delete[] s_local; + return info; +} + +template +inline lapack_int eigen_factor(lapack_int n, T a[], T vectors[], R values[], T d[], GEES gees, TREVC trevc) +{ + T* clone_a = Clone(n, n, a); + T* wr = new T[n]; + T* wi = new T[n]; + + lapack_int sdim; + lapack_int info = gees(LAPACK_COL_MAJOR, 'V', 'N', nullptr, n, clone_a, n, &sdim, wr, wi, vectors, n); + if (info != 0) + { + delete[] clone_a; + delete[] wr; + delete[] wi; + return info; + } + + lapack_int m; + info = trevc(LAPACK_COL_MAJOR, 'R', 'B', nullptr, n, clone_a, n, nullptr, n, vectors, n, n, &m); + if (info != 0) + { + delete[] clone_a; + delete[] wr; + delete[] wi; + return info; + } + + for (lapack_int index = 0; index < n; ++index) + { + values[index] = R(wr[index], wi[index]); + } + + for (lapack_int i = 0; i < n; ++i) + { + lapack_int in = i * n; + d[in + i] = wr[i]; + + if (wi[i] > 0) + { + d[in + n + i] = wi[i]; + } + else if (wi[i] < 0) + { + d[in - n + i] = wi[i]; + } + } + + delete[] clone_a; + delete[] wr; + delete[] wi; + return info; +} + +template +inline lapack_int eigen_complex_factor(lapack_int n, T a[], T vectors[], lapack_complex_double values[], T d[], GEES gees, TREVC trevc) +{ + T* clone_a = Clone(n, n, a); + T* w = new T[n]; + + lapack_int sdim; + lapack_int info = gees(LAPACK_COL_MAJOR, 'V', 'N', nullptr, n, clone_a, n, &sdim, w, vectors, n); + if (info != 0) + { + delete[] clone_a; + delete[] w; + return info; + } + + lapack_int m; + info = trevc(LAPACK_COL_MAJOR, 'R', 'B', nullptr, n, clone_a, n, nullptr, n, vectors, n, n, &m); + if (info != 0) + { + delete[] clone_a; + delete[] w; + return info; + } + + for (lapack_int i = 0; i < n; ++i) + { + values[i] = w[i]; + d[i * n + i] = w[i]; + } + + delete[] clone_a; + delete[] w; + return info; +} + +template +inline lapack_int sym_eigen_factor(lapack_int n, T a[], T vectors[], lapack_complex_double values[], T d[], SYEV syev) +{ + T* clone_a = Clone(n, n, a); + R* w = new R[n]; + + lapack_int info = syev(LAPACK_COL_MAJOR, 'V', 'U', n, clone_a, n, w); + if (info != 0) + { + delete[] clone_a; + delete[] w; + return info; + } + + memcpy(vectors, clone_a, n*n*sizeof(T)); + + for (lapack_int index = 0; index < n; ++index) + { + values[index] = lapack_complex_double(w[index]); + } + + for (lapack_int j = 0; j < n; ++j) + { + lapack_int jn = j*n; + + for (lapack_int i = 0; i < n; ++i) + { + if (i == j) + { + d[jn + i] = w[i]; + } + } + } + + delete[] clone_a; + delete[] w; + return info; +} + +extern "C" { + + DLLEXPORT float s_matrix_norm(char norm, lapack_int m, lapack_int n, float a[], float work[]) + { + return LAPACKE_slange_work(CblasColMajor, norm, m, n, a, m, work); + } + + DLLEXPORT double d_matrix_norm(char norm, lapack_int m, lapack_int n, double a[], double work[]) + { + return LAPACKE_dlange_work(CblasColMajor, norm, m, n, a, m, work); + } + + DLLEXPORT float c_matrix_norm(char norm, lapack_int m, lapack_int n, lapack_complex_float a[], float work[]) + { + return LAPACKE_clange_work(CblasColMajor, norm, m, n, a, m, work); + } + + DLLEXPORT double z_matrix_norm(char norm, lapack_int m, lapack_int n, lapack_complex_double a[], double work[]) + { + return LAPACKE_zlange_work(CblasColMajor, norm, m, n, a, m, work); + } + + DLLEXPORT lapack_int s_lu_factor(lapack_int m, float a[], lapack_int ipiv[]) + { + return lu_factor(m, a, ipiv, LAPACK_sgetrf); + } + + DLLEXPORT lapack_int d_lu_factor(lapack_int m, double a[], lapack_int ipiv[]) + { + return lu_factor(m, a, ipiv, LAPACK_dgetrf); + } + + DLLEXPORT lapack_int c_lu_factor(lapack_int m, lapack_complex_float a[], lapack_int ipiv[]) + { + return lu_factor(m, a, ipiv, LAPACK_cgetrf); + } + + DLLEXPORT lapack_int z_lu_factor(lapack_int m, lapack_complex_double a[], lapack_int ipiv[]) + { + return lu_factor(m, a, ipiv, LAPACK_zgetrf); + } + + DLLEXPORT lapack_int s_lu_inverse(lapack_int n, float a[], float work[], lapack_int lwork) + { + return lu_inverse(n, a, work, lwork, LAPACK_sgetrf, LAPACK_sgetri); + } + + DLLEXPORT lapack_int d_lu_inverse(lapack_int n, double a[], double work[], lapack_int lwork) + { + return lu_inverse(n, a, work, lwork, LAPACK_dgetrf, LAPACK_dgetri); + } + + DLLEXPORT lapack_int c_lu_inverse(lapack_int n, lapack_complex_float a[], lapack_complex_float work[], lapack_int lwork) + { + return lu_inverse(n, a, work, lwork, LAPACK_cgetrf, LAPACK_cgetri); + } + + DLLEXPORT lapack_int z_lu_inverse(lapack_int n, lapack_complex_double a[], lapack_complex_double work[], lapack_int lwork) + { + return lu_inverse(n, a, work, lwork, LAPACK_zgetrf, LAPACK_zgetri); + } + + DLLEXPORT lapack_int s_lu_inverse_factored(lapack_int n, float a[], lapack_int ipiv[], float work[], lapack_int lwork) + { + return lu_inverse_factored(n, a, ipiv, work, lwork, LAPACK_sgetri); + } + + DLLEXPORT lapack_int d_lu_inverse_factored(lapack_int n, double a[], lapack_int ipiv[], double work[], lapack_int lwork) + { + return lu_inverse_factored(n, a, ipiv, work, lwork, LAPACK_dgetri); + } + + DLLEXPORT lapack_int c_lu_inverse_factored(lapack_int n, lapack_complex_float a[], lapack_int ipiv[], lapack_complex_float work[], lapack_int lwork) + { + return lu_inverse_factored(n, a, ipiv, work, lwork, LAPACK_cgetri); + } + + DLLEXPORT lapack_int z_lu_inverse_factored(lapack_int n, lapack_complex_double a[], lapack_int ipiv[], lapack_complex_double work[], lapack_int lwork) + { + return lu_inverse_factored(n, a, ipiv, work, lwork, LAPACK_zgetri); + } + + DLLEXPORT lapack_int s_lu_solve_factored(lapack_int n, lapack_int nrhs, float a[], lapack_int ipiv[], float b[]) + { + return lu_solve_factored(n, nrhs, a, ipiv, b, LAPACK_sgetrs); + } + + DLLEXPORT lapack_int d_lu_solve_factored(lapack_int n, lapack_int nrhs, double a[], lapack_int ipiv[], double b[]) + { + return lu_solve_factored(n, nrhs, a, ipiv, b, LAPACK_dgetrs); + } + + DLLEXPORT lapack_int c_lu_solve_factored(lapack_int n, lapack_int nrhs, lapack_complex_float a[], lapack_int ipiv[], lapack_complex_float b[]) + { + return lu_solve_factored(n, nrhs, a, ipiv, b, LAPACK_cgetrs); + } + + DLLEXPORT lapack_int z_lu_solve_factored(lapack_int n, lapack_int nrhs, lapack_complex_double a[], lapack_int ipiv[], lapack_complex_double b[]) + { + return lu_solve_factored(n, nrhs, a, ipiv, b, LAPACK_zgetrs); + } + + DLLEXPORT lapack_int s_lu_solve(lapack_int n, lapack_int nrhs, float a[], float b[]) + { + return lu_solve(n, nrhs, a, b, LAPACK_sgetrf, LAPACK_sgetrs); + } + + DLLEXPORT lapack_int d_lu_solve(lapack_int n, lapack_int nrhs, double a[], double b[]) + { + return lu_solve(n, nrhs, a, b, LAPACK_dgetrf, LAPACK_dgetrs); + } + + DLLEXPORT lapack_int c_lu_solve(lapack_int n, lapack_int nrhs, lapack_complex_float a[], lapack_complex_float b[]) + { + return lu_solve(n, nrhs, a, b, LAPACK_cgetrf, LAPACK_cgetrs); + } + + DLLEXPORT lapack_int z_lu_solve(lapack_int n, lapack_int nrhs, lapack_complex_double a[], lapack_complex_double b[]) + { + return lu_solve(n, nrhs, a, b, LAPACK_zgetrf, LAPACK_zgetrs); + } + + DLLEXPORT lapack_int s_cholesky_factor(lapack_int n, float a[]) + { + return cholesky_factor(n, a, LAPACK_spotrf); + } + + DLLEXPORT lapack_int d_cholesky_factor(lapack_int n, double* a) + { + return cholesky_factor(n, a, LAPACK_dpotrf); + } + + DLLEXPORT lapack_int c_cholesky_factor(lapack_int n, lapack_complex_float a[]) + { + return cholesky_factor(n, a, LAPACK_cpotrf); + } + + DLLEXPORT lapack_int z_cholesky_factor(lapack_int n, lapack_complex_double a[]) + { + return cholesky_factor(n, a, LAPACK_zpotrf); + } + + DLLEXPORT lapack_int s_cholesky_solve(lapack_int n, lapack_int nrhs, float a[], float b[]) + { + return cholesky_solve(n, nrhs, a, b, LAPACK_spotrf, LAPACK_spotrs); + } + + DLLEXPORT lapack_int d_cholesky_solve(lapack_int n, lapack_int nrhs, double a[], double b[]) + { + return cholesky_solve(n, nrhs, a, b, LAPACK_dpotrf, LAPACK_dpotrs); + } + + DLLEXPORT lapack_int c_cholesky_solve(lapack_int n, lapack_int nrhs, lapack_complex_float a[], lapack_complex_float b[]) + { + return cholesky_solve(n, nrhs, a, b, LAPACK_cpotrf, LAPACK_cpotrs); + } + + DLLEXPORT lapack_int z_cholesky_solve(lapack_int n, lapack_int nrhs, lapack_complex_double a[], lapack_complex_double b[]) + { + return cholesky_solve(n, nrhs, a, b, LAPACK_zpotrf, LAPACK_zpotrs); + } + + DLLEXPORT lapack_int s_cholesky_solve_factored(lapack_int n, lapack_int nrhs, float a[], float b[]) + { + return cholesky_solve_factored(n, nrhs, a, b, LAPACK_spotrs); + } + + DLLEXPORT lapack_int d_cholesky_solve_factored(lapack_int n, lapack_int nrhs, double a[], double b[]) + { + return cholesky_solve_factored(n, nrhs, a, b, LAPACK_dpotrs); + } + + DLLEXPORT lapack_int c_cholesky_solve_factored(lapack_int n, lapack_int nrhs, lapack_complex_float a[], lapack_complex_float b[]) + { + return cholesky_solve_factored(n, nrhs, a, b, LAPACK_cpotrs); + } + + DLLEXPORT lapack_int z_cholesky_solve_factored(lapack_int n, lapack_int nrhs, lapack_complex_double a[], lapack_complex_double b[]) + { + return cholesky_solve_factored(n, nrhs, a, b, LAPACK_zpotrs); + } + + DLLEXPORT lapack_int s_qr_factor(lapack_int m, lapack_int n, float r[], float tau[], float q[], float work[], lapack_int len) + { + return qr_factor(m, n, r, tau, q, work, len, LAPACK_sgeqrf, LAPACK_sorgqr); + } + + DLLEXPORT lapack_int s_qr_thin_factor(lapack_int m, lapack_int n, float q[], float tau[], float r[], float work[], lapack_int len) + { + return qr_thin_factor(m, n, q, tau, r, work, len, LAPACK_sgeqrf, LAPACK_sorgqr); + } + + DLLEXPORT lapack_int d_qr_factor(lapack_int m, lapack_int n, double r[], double tau[], double q[], double work[], lapack_int len) + { + return qr_factor(m, n, r, tau, q, work, len, LAPACK_dgeqrf, LAPACK_dorgqr); + } + + DLLEXPORT lapack_int d_qr_thin_factor(lapack_int m, lapack_int n, double q[], double tau[], double r[], double work[], lapack_int len) + { + return qr_thin_factor(m, n, q, tau, r, work, len, LAPACK_dgeqrf, LAPACK_dorgqr); + } + + DLLEXPORT lapack_int c_qr_factor(lapack_int m, lapack_int n, lapack_complex_float r[], lapack_complex_float tau[], lapack_complex_float q[], lapack_complex_float work[], lapack_int len) + { + return qr_factor(m, n, r, tau, q, work, len, LAPACK_cgeqrf, LAPACK_cungqr); + } + + DLLEXPORT lapack_int c_qr_thin_factor(lapack_int m, lapack_int n, lapack_complex_float q[], lapack_complex_float tau[], lapack_complex_float r[], lapack_complex_float work[], lapack_int len) + { + return qr_thin_factor(m, n, q, tau, r, work, len, LAPACK_cgeqrf, LAPACK_cungqr); + } + + DLLEXPORT lapack_int z_qr_factor(lapack_int m, lapack_int n, lapack_complex_double r[], lapack_complex_double tau[], lapack_complex_double q[], lapack_complex_double work[], lapack_int len) + { + return qr_factor(m, n, r, tau, q, work, len, LAPACK_zgeqrf, LAPACK_zungqr); + } + + DLLEXPORT lapack_int z_qr_thin_factor(lapack_int m, lapack_int n, lapack_complex_double q[], lapack_complex_double tau[], lapack_complex_double r[], lapack_complex_double work[], lapack_int len) + { + return qr_thin_factor(m, n, q, tau, r, work, len, LAPACK_zgeqrf, LAPACK_zungqr); + } + + DLLEXPORT lapack_int s_qr_solve(lapack_int m, lapack_int n, lapack_int bn, float a[], float b[], float x[], float work[], lapack_int len) + { + return qr_solve(m, n, bn, a, b, x, work, len, LAPACK_sgels); + } + + DLLEXPORT lapack_int d_qr_solve(lapack_int m, lapack_int n, lapack_int bn, double a[], double b[], double x[], double work[], lapack_int len) + { + return qr_solve(m, n, bn, a, b, x, work, len, LAPACK_dgels); + } + + DLLEXPORT lapack_int c_qr_solve(lapack_int m, lapack_int n, lapack_int bn, lapack_complex_float a[], lapack_complex_float b[], lapack_complex_float x[], lapack_complex_float work[], lapack_int len) + { + return qr_solve(m, n, bn, a, b, x, work, len, LAPACK_cgels); + } + + DLLEXPORT lapack_int z_qr_solve(lapack_int m, lapack_int n, lapack_int bn, lapack_complex_double a[], lapack_complex_double b[], lapack_complex_double x[], lapack_complex_double work[], lapack_int len) + { + return qr_solve(m, n, bn, a, b, x, work, len, LAPACK_zgels); + } + + DLLEXPORT lapack_int s_qr_solve_factored(lapack_int m, lapack_int n, lapack_int bn, float r[], float b[], float tau[], float x[], float work[], lapack_int len) + { + return qr_solve_factored(m, n, bn, r, b, tau, x, work, len, LAPACK_sormqr, cblas_strsm); + } + + DLLEXPORT lapack_int d_qr_solve_factored(lapack_int m, lapack_int n, lapack_int bn, double r[], double b[], double tau[], double x[], double work[], lapack_int len) + { + return qr_solve_factored(m, n, bn, r, b, tau, x, work, len, LAPACK_dormqr, cblas_dtrsm); + } + + DLLEXPORT lapack_int c_qr_solve_factored(lapack_int m, lapack_int n, lapack_int bn, lapack_complex_float r[], lapack_complex_float b[], lapack_complex_float tau[], lapack_complex_float x[], lapack_complex_float work[], lapack_int len) + { + return complex_qr_solve_factored(m, n, bn, r, b, tau, x, work, len, LAPACK_cunmqr, cblas_ctrsm); + } + + DLLEXPORT lapack_int z_qr_solve_factored(lapack_int m, lapack_int n, lapack_int bn, lapack_complex_double r[], lapack_complex_double b[], lapack_complex_double tau[], lapack_complex_double x[], lapack_complex_double work[], lapack_int len) + { + return complex_qr_solve_factored(m, n, bn, r, b, tau, x, work, len, LAPACK_zunmqr, cblas_ztrsm); + } + + DLLEXPORT lapack_int s_svd_factor(bool compute_vectors, lapack_int m, lapack_int n, float a[], float s[], float u[], float v[], float work[], lapack_int len) + { + return svd_factor(compute_vectors, m, n, a, s, u, v, work, len, LAPACK_sgesvd); + } + + DLLEXPORT lapack_int d_svd_factor(bool compute_vectors, lapack_int m, lapack_int n, double a[], double s[], double u[], double v[], double work[], lapack_int len) + { + return svd_factor(compute_vectors, m, n, a, s, u, v, work, len, LAPACK_dgesvd); + } + + DLLEXPORT lapack_int c_svd_factor(bool compute_vectors, lapack_int m, lapack_int n, lapack_complex_float a[], lapack_complex_float s[], lapack_complex_float u[], lapack_complex_float v[], lapack_complex_float work[], lapack_int len) + { + return complex_svd_factor(compute_vectors, m, n, a, s, u, v, work, len, LAPACK_cgesvd); + } + + DLLEXPORT lapack_int z_svd_factor(bool compute_vectors, lapack_int m, lapack_int n, lapack_complex_double a[], lapack_complex_double s[], lapack_complex_double u[], lapack_complex_double v[], lapack_complex_double work[], lapack_int len) + { + return complex_svd_factor(compute_vectors, m, n, a, s, u, v, work, len, LAPACK_zgesvd); + } + + DLLEXPORT lapack_int s_eigen(bool isSymmetric, lapack_int n, float a[], float vectors[], lapack_complex_double values[], float d[]) + { + if (isSymmetric) + { + return sym_eigen_factor(n, a, vectors, values, d, LAPACKE_ssyev); + } + else + { + return eigen_factor(n, a, vectors, values, d, LAPACKE_sgees, LAPACKE_strevc); + } + } + + DLLEXPORT lapack_int d_eigen(bool isSymmetric, lapack_int n, double a[], double vectors[], lapack_complex_double values[], double d[]) + { + if (isSymmetric) + { + return sym_eigen_factor(n, a, vectors, values, d, LAPACKE_dsyev); + } + else + { + return eigen_factor(n, a, vectors, values, d, LAPACKE_dgees, LAPACKE_dtrevc); + } + } + + DLLEXPORT lapack_int c_eigen(bool isSymmetric, lapack_int n, lapack_complex_float a[], lapack_complex_float vectors[], lapack_complex_double values[], lapack_complex_float d[]) + { + if (isSymmetric) + { + return sym_eigen_factor(n, a, vectors, values, d, LAPACKE_cheev); + } + else + { + return eigen_complex_factor(n, a, vectors, values, d, LAPACKE_cgees, LAPACKE_ctrevc); + } + } + + DLLEXPORT lapack_int z_eigen(bool isSymmetric, lapack_int n, lapack_complex_double a[], lapack_complex_double vectors[], lapack_complex_double values[], lapack_complex_double d[]) + { + if (isSymmetric) + { + return sym_eigen_factor(n, a, vectors, values, d, LAPACKE_zheev); + } + else + { + return eigen_complex_factor(n, a, vectors, values, d, LAPACKE_zgees, LAPACKE_ztrevc); + } + } +} diff --git a/src/NativeProviders/Windows/OpenBLAS/OpenBLASWrapper.vcxproj b/src/NativeProviders/Windows/OpenBLAS/OpenBLASWrapper.vcxproj new file mode 100644 index 00000000..540a55f0 --- /dev/null +++ b/src/NativeProviders/Windows/OpenBLAS/OpenBLASWrapper.vcxproj @@ -0,0 +1,219 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {CB4011B6-E9A7-480B-A7B1-8492039DAAD1} + OpenBLASWrapper + OpenBLAS + + + + DynamicLibrary + v120 + MultiByte + true + + + DynamicLibrary + v120 + MultiByte + + + DynamicLibrary + v120 + MultiByte + true + + + DynamicLibrary + v120 + MultiByte + + + + + + + + + + + + + + + + + + $(ProjectDir)..\..\..\..\..\libs\OpenBLAS\include + $(ProjectDir)..\..\..\..\..\libs\OpenBLAS\x86 + $(ProjectDir)..\..\..\..\..\libs\OpenBLAS\x64 + + + <_ProjectFileVersion>11.0.50727.1 + + + $(ProjectDir)..\..\..\..\out\OpenBLAS\Windows\x86\ + $(Platform)\$(Configuration)\ + MathNet.Numerics.OpenBLAS + $(OpenBLASIncludeDir);$(IncludePath) + + + $(ProjectDir)..\..\..\..\out\OpenBLAS\Windows\x64\ + $(Platform)\$(Configuration)\ + MathNet.Numerics.OpenBLAS + $(OpenBLASIncludeDir);$(IncludePath) + + + $(ProjectDir)..\..\..\..\out\OpenBLAS\Windows\x86\ + $(Platform)\$(Configuration)\ + MathNet.Numerics.OpenBLAS + $(OpenBLASIncludeDir);$(IncludePath) + + + $(ProjectDir)..\..\..\..\out\OpenBLAS\Windows\x64\ + $(Platform)\$(Configuration)\ + MathNet.Numerics.OpenBLAS + $(OpenBLASIncludeDir);$(IncludePath) + + + + Disabled + $(ProjectDir)..\..\Common;$(ProjectDir)..\..\OpenBLAS;$(OpenBLASIncludeDir);%(AdditionalIncludeDirectories) + _WINDOWS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + Level3 + EditAndContinue + Default + + + libopenblas.dll.a;%(AdditionalDependencies) + $(OutDir)$(TargetName)$(TargetExt) + true + MachineX86 + $(OutDir)$(TargetName).lib + $(OpenBLASLibDir);%(AdditionalLibraryDirectories) + + + + + + + + + X64 + + + Disabled + $(ProjectDir)..\..\Common;$(ProjectDir)..\..\OpenBLAS;$(OpenBLASIncludeDir);%(AdditionalIncludeDirectories) + _WINDOWS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + Level3 + ProgramDatabase + Default + + + libopenblas.dll.a;%(AdditionalDependencies) + $(OutDir)$(TargetName)$(TargetExt) + true + MachineX64 + $(OutDir)$(TargetName).lib + $(OpenBLASLibDir_x64);%(AdditionalLibraryDirectories) + + + + + + + + + MaxSpeed + true + $(ProjectDir)..\..\Common;$(ProjectDir)..\..\OpenBLAS;$(OpenBLASIncludeDir);%(AdditionalIncludeDirectories) + _WINDOWS;%(PreprocessorDefinitions) + MultiThreaded + true + Level3 + ProgramDatabase + Default + /Qvec-report:1 %(AdditionalOptions) + + + libopenblas.dll.a;%(AdditionalDependencies) + $(OutDir)$(TargetName)$(TargetExt) + true + true + true + MachineX86 + $(OutDir)$(TargetName).lib + $(OpenBLASLibDir);%(AdditionalLibraryDirectories) + + + + + + + + + X64 + + + MaxSpeed + true + $(ProjectDir)..\..\Common;$(ProjectDir)..\..\OpenBLAS;$(OpenBLASIncludeDir);%(AdditionalIncludeDirectories) + _WINDOWS;%(PreprocessorDefinitions) + MultiThreaded + true + Level3 + ProgramDatabase + Default + /Qvec-report:1 %(AdditionalOptions) + + + libopenblas.dll.a;%(AdditionalDependencies) + $(OutDir)$(TargetName)$(TargetExt) + true + true + true + MachineX64 + $(OutDir)$(TargetName).lib + $(OpenBLASLibDir_x64);%(AdditionalLibraryDirectories) + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/NativeProviders/Windows/OpenBLAS/OpenBLASWrapper.vcxproj.filters b/src/NativeProviders/Windows/OpenBLAS/OpenBLASWrapper.vcxproj.filters new file mode 100644 index 00000000..62e1f976 --- /dev/null +++ b/src/NativeProviders/Windows/OpenBLAS/OpenBLASWrapper.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + + + Source Files + + + Source Files + + + Source Files + + + + + Resource Files + + + \ No newline at end of file