Browse Source

Merge pull request #338 from cuda/memory

Cleaning up native memory usage and other minor issues
truncatednormal
Christoph Ruegg 11 years ago
parent
commit
d2b87616b3
  1. 1
      .gitignore
  2. 44
      MathNet.Numerics.NativeProviders.sln
  3. 89
      src/NativeProviders/Common/blas.c
  4. 744
      src/NativeProviders/Common/lapack.cpp
  5. 54
      src/NativeProviders/Common/lapack_common.h
  6. 89
      src/NativeProviders/MKL/blas.c
  7. 7
      src/NativeProviders/MKL/blas.h
  8. 713
      src/NativeProviders/MKL/lapack.cpp
  9. 32
      src/NativeProviders/MKL/lapack.h
  10. 89
      src/NativeProviders/OpenBLAS/blas.c
  11. 7
      src/NativeProviders/OpenBLAS/blas.h
  12. 39
      src/NativeProviders/OpenBLAS/complex.h
  13. 712
      src/NativeProviders/OpenBLAS/lapack.cpp
  14. 11
      src/NativeProviders/OpenBLAS/lapack.h
  15. 7
      src/NativeProviders/Windows/MKL/MKLWrapper.vcxproj
  16. 25
      src/NativeProviders/Windows/MKL/MKLWrapper.vcxproj.filters
  17. 8
      src/NativeProviders/Windows/OpenBLAS/OpenBLASWrapper.vcxproj
  18. 18
      src/NativeProviders/Windows/OpenBLAS/OpenBLASWrapper.vcxproj.filters
  19. 2
      src/Numerics/Control.cs
  20. 106
      src/Numerics/Exceptions.cs
  21. 270
      src/Numerics/Properties/Resources.Designer.cs
  22. 15
      src/Numerics/Properties/Resources.resx
  23. 136
      src/Numerics/Providers/LinearAlgebra/Cuda/CudaLinearAlgebraProvider.Complex.cs
  24. 137
      src/Numerics/Providers/LinearAlgebra/Cuda/CudaLinearAlgebraProvider.Complex32.cs
  25. 135
      src/Numerics/Providers/LinearAlgebra/Cuda/CudaLinearAlgebraProvider.Double.cs
  26. 137
      src/Numerics/Providers/LinearAlgebra/Cuda/CudaLinearAlgebraProvider.Single.cs
  27. 112
      src/Numerics/Providers/LinearAlgebra/ILinearAlgebraProvider.cs
  28. 291
      src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Complex.cs
  29. 293
      src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Complex32.cs
  30. 298
      src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Double.cs
  31. 291
      src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Single.cs
  32. 477
      src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Complex.cs
  33. 478
      src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Complex32.cs
  34. 481
      src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Double.cs
  35. 472
      src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Single.cs
  36. 11
      src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.cs
  37. 64
      src/Numerics/Providers/LinearAlgebra/Mkl/SafeNativeMethods.cs
  38. 493
      src/Numerics/Providers/LinearAlgebra/OpenBlas/OpenBlasLinearAlgebraProvider.Complex.cs
  39. 486
      src/Numerics/Providers/LinearAlgebra/OpenBlas/OpenBlasLinearAlgebraProvider.Complex32.cs
  40. 505
      src/Numerics/Providers/LinearAlgebra/OpenBlas/OpenBlasLinearAlgebraProvider.Double.cs
  41. 500
      src/Numerics/Providers/LinearAlgebra/OpenBlas/OpenBlasLinearAlgebraProvider.Single.cs
  42. 11
      src/Numerics/Providers/LinearAlgebra/OpenBlas/OpenBlasLinearAlgebraProvider.cs
  43. 100
      src/Numerics/Providers/LinearAlgebra/OpenBlas/SafeNativeMethods.cs
  44. 588
      src/UnitTests/LinearAlgebraProviderTests/Complex/LinearAlgebraProviderTests.cs
  45. 558
      src/UnitTests/LinearAlgebraProviderTests/Complex32/LinearAlgebraProviderTests.cs
  46. 558
      src/UnitTests/LinearAlgebraProviderTests/Double/LinearAlgebraProviderTests.cs
  47. 558
      src/UnitTests/LinearAlgebraProviderTests/Single/LinearAlgebraProviderTests.cs
  48. 4
      src/UnitTests/UnitTests-CUDA.csproj
  49. 329
      src/UnitTests/UnitTests-MKL.csproj
  50. 4
      src/UnitTests/UnitTests-OpenBLAS.csproj

1
.gitignore

@ -21,6 +21,7 @@ coverage.*
*.psess
*.vsp
*.vspx
*.lnt
# Caches
_ReSharper*

44
MathNet.Numerics.NativeProviders.sln

@ -26,6 +26,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenBLAS", "src\NativeProvi
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests-OpenBLAS", "src\UnitTests\UnitTests-OpenBLAS.csproj", "{96B903EF-3EE1-4569-803C-0482D2F5ED37}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestData", "src\TestData\TestData.csproj", "{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -344,6 +346,48 @@ Global
{96B903EF-3EE1-4569-803C-0482D2F5ED37}.Release-Signed|Mixed Platforms.Build.0 = Release|Any CPU
{96B903EF-3EE1-4569-803C-0482D2F5ED37}.Release-Signed|Win32.ActiveCfg = Release|Any CPU
{96B903EF-3EE1-4569-803C-0482D2F5ED37}.Release-Signed|x64.ActiveCfg = Release|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Debug|Win32.ActiveCfg = Debug|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Debug|x64.ActiveCfg = Debug|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release|Any CPU.Build.0 = Release|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release|Win32.ActiveCfg = Release|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release|x64.ActiveCfg = Release|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-CUDA|Any CPU.ActiveCfg = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-CUDA|Any CPU.Build.0 = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-CUDA|Mixed Platforms.ActiveCfg = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-CUDA|Mixed Platforms.Build.0 = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-CUDA|Win32.ActiveCfg = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-CUDA|Win32.Build.0 = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-CUDA|x64.ActiveCfg = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-CUDA|x64.Build.0 = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-MKL|Any CPU.ActiveCfg = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-MKL|Any CPU.Build.0 = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-MKL|Mixed Platforms.ActiveCfg = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-MKL|Mixed Platforms.Build.0 = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-MKL|Win32.ActiveCfg = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-MKL|Win32.Build.0 = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-MKL|x64.ActiveCfg = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-MKL|x64.Build.0 = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-OpenBLAS|Any CPU.ActiveCfg = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-OpenBLAS|Any CPU.Build.0 = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-OpenBLAS|Mixed Platforms.ActiveCfg = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-OpenBLAS|Mixed Platforms.Build.0 = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-OpenBLAS|Win32.ActiveCfg = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-OpenBLAS|Win32.Build.0 = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-OpenBLAS|x64.ActiveCfg = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-OpenBLAS|x64.Build.0 = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-Signed|Any CPU.ActiveCfg = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-Signed|Any CPU.Build.0 = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-Signed|Mixed Platforms.ActiveCfg = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-Signed|Mixed Platforms.Build.0 = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-Signed|Win32.ActiveCfg = Release-Signed|Any CPU
{AF3253C9-4DB5-45A0-98CF-C105FDA9DA47}.Release-Signed|x64.ActiveCfg = Release-Signed|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

89
src/NativeProviders/Common/blas.c

@ -0,0 +1,89 @@
#include "wrapper_common.h"
#include "blas.h"
#if __cplusplus
extern "C" {
#endif
DLLEXPORT void s_axpy(const blas_int n, const float alpha, const float x[], float y[]){
cblas_saxpy(n, alpha, x, 1, y, 1);
}
DLLEXPORT void d_axpy(const blas_int n, const double alpha, const double x[], double y[]){
cblas_daxpy(n, alpha, x, 1, y, 1);
}
DLLEXPORT void c_axpy(const blas_int n, const blas_complex_float alpha, const blas_complex_float x[], blas_complex_float y[]){
cblas_caxpy(n, (float*)&alpha, (float*)x, 1, (float*)y, 1);
}
DLLEXPORT void z_axpy(const blas_int n, const blas_complex_double alpha, const blas_complex_double x[], blas_complex_double y[]){
cblas_zaxpy(n, (double*)&alpha, (double*)x, 1, (double*)y, 1);
}
DLLEXPORT void s_scale(const blas_int n, const float alpha, float x[]){
cblas_sscal(n, alpha, x, 1);
}
DLLEXPORT void d_scale(const blas_int n, const double alpha, double x[]){
cblas_dscal(n, alpha, x, 1);
}
DLLEXPORT void c_scale(const blas_int n, const blas_complex_float alpha, blas_complex_float x[]){
cblas_cscal(n, (float*)&alpha, (float*)x, 1);
}
DLLEXPORT void z_scale(const blas_int n, const blas_complex_double alpha, blas_complex_double x[]){
cblas_zscal(n, (double*)&alpha, (double*)x, 1);
}
DLLEXPORT float s_dot_product(const blas_int n, const float x[], const float y[]){
return cblas_sdot(n, x, 1, y, 1);
}
DLLEXPORT double d_dot_product(const blas_int n, const double x[], const double y[]){
return cblas_ddot(n, x, 1, y, 1);
}
DLLEXPORT blas_complex_float c_dot_product(const blas_int n, const blas_complex_float x[], const blas_complex_float y[]){
blas_complex_float ret;
cblas_cdotu_sub(n, (float*)x, 1, (float*)y, 1, &ret);
return ret;
}
DLLEXPORT blas_complex_double z_dot_product(const blas_int n, const blas_complex_double x[], const blas_complex_double y[]){
blas_complex_double ret;
cblas_zdotu_sub(n, (double*)x, 1, (double*)y, 1, &ret);
return ret;
}
DLLEXPORT void s_matrix_multiply(CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB, const blas_int m, const blas_int n, const blas_int k, const float alpha, const float x[], const float y[], const float beta, float c[]){
blas_int lda = transA == CblasNoTrans ? m : k;
blas_int 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 blas_int m, const blas_int n, const blas_int k, const double alpha, const double x[], const double y[], const double beta, double c[]){
blas_int lda = transA == CblasNoTrans ? m : k;
blas_int 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 blas_int m, const blas_int n, const blas_int k, const blas_complex_float alpha, const blas_complex_float x[], const blas_complex_float y[], const blas_complex_float beta, blas_complex_float c[]){
blas_int lda = transA == CblasNoTrans ? m : k;
blas_int ldb = transB == CblasNoTrans ? k : n;
cblas_cgemm(CblasColMajor, transA, transB, m, n, k, (float*)&alpha, (float*)x, lda, (float*)y, ldb, (float*)&beta, (float*)c, m);
}
DLLEXPORT void z_matrix_multiply(CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB, const blas_int m, const blas_int n, const blas_int k, const blas_complex_double alpha, const blas_complex_double x[], const blas_complex_double y[], const blas_complex_double beta, blas_complex_double c[]){
blas_int lda = transA == CblasNoTrans ? m : k;
blas_int ldb = transB == CblasNoTrans ? k : n;
cblas_zgemm(CblasColMajor, transA, transB, m, n, k, (double*)&alpha, (double*)x, lda, (double*)y, ldb, (double*)&beta, (double*)c, m);
}
#if __cplusplus
}
#endif

744
src/NativeProviders/Common/lapack.cpp

@ -0,0 +1,744 @@
#include "wrapper_common.h"
#include "lapack.h"
#include "lapack_common.h"
#include <algorithm>
template<typename T, typename GETRF>
inline lapack_int lu_factor(lapack_int m, T a[], lapack_int ipiv[], GETRF getrf)
{
auto info = getrf(LAPACK_COL_MAJOR, m, m, a, m, ipiv);
shift_ipiv_down(m, ipiv);
return info;
}
template<typename T, typename GETRF, typename GETRI>
inline lapack_int lu_inverse(lapack_int n, T a[], GETRF getrf, GETRI getri)
{
try
{
auto ipiv = array_new<lapack_int>(n);
auto info = getrf(LAPACK_COL_MAJOR, n, n, a, n, ipiv.get());
if (info != 0)
{
return info;
}
info = getri(LAPACK_COL_MAJOR, n, a, n, ipiv.get());
return info;
}
catch (std::bad_alloc&)
{
return INSUFFICIENT_MEMORY;
}
}
template<typename T, typename GETRI>
inline lapack_int lu_inverse_factored(lapack_int n, T a[], lapack_int ipiv[], GETRI getri)
{
shift_ipiv_up(n, ipiv);
auto info = getri(LAPACK_COL_MAJOR, n, a, n, ipiv);
shift_ipiv_down(n, ipiv);
return info;
}
template<typename T, typename GETRS>
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);
auto info = getrs(LAPACK_COL_MAJOR, 'N', n, nrhs, a, n, ipiv, b, n);
shift_ipiv_down(n, ipiv);
return info;
}
template<typename T, typename GETRF, typename GETRS>
inline lapack_int lu_solve(lapack_int n, lapack_int nrhs, T a[], T b[], GETRF getrf, GETRS getrs)
{
try
{
auto clone = array_clone(n * n, a);
auto ipiv = array_new<lapack_int>(n);
auto info = getrf(LAPACK_COL_MAJOR, n, n, clone.get(), n, ipiv.get());
if (info != 0)
{
return info;
}
return getrs(LAPACK_COL_MAJOR, 'N', n, nrhs, clone.get(), n, ipiv.get(), b, n);
}
catch (std::bad_alloc&)
{
return INSUFFICIENT_MEMORY;
}
}
template<typename T, typename POTRF>
inline lapack_int cholesky_factor(lapack_int n, T* a, POTRF potrf)
{
auto info = potrf(LAPACK_COL_MAJOR, 'L', n, a, n);
auto zero = T();
for (auto i = 0; i < n; ++i)
{
auto index = i * n;
for (auto j = 0; j < n && i > j; ++j)
{
a[index + j] = zero;
}
}
return info;
}
template<typename T, typename POTRF, typename POTRS>
inline lapack_int cholesky_solve(lapack_int n, lapack_int nrhs, T a[], T b[], POTRF potrf, POTRS potrs)
{
try
{
auto clone = array_clone(n * n, a);
auto info = potrf(LAPACK_COL_MAJOR, 'L', n, clone.get(), n);
if (info != 0)
{
return info;
}
return potrs(LAPACK_COL_MAJOR, 'L', n, nrhs, clone.get(), n, b, n);
}
catch (std::bad_alloc&)
{
return INSUFFICIENT_MEMORY;
}
}
template<typename T, typename GEQRF, typename ORGQR>
inline lapack_int qr_factor(lapack_int m, lapack_int n, T r[], T tau[], T q[], GEQRF geqrf, ORGQR orgqr)
{
auto info = geqrf(LAPACK_COL_MAJOR, m, n, r, m, tau);
for (auto i = 0; i < m; ++i)
{
for (auto j = 0; j < m && j < n; ++j)
{
if (i > j)
{
q[j * m + i] = r[j * m + i];
}
}
}
if (info != 0)
{
return info;
}
//compute the q elements explicitly
if (m <= n)
{
info = orgqr(LAPACK_COL_MAJOR, m, m, m, q, m, tau);
}
else
{
info = orgqr(LAPACK_COL_MAJOR, m, m, n, q, m, tau);
}
return info;
}
template<typename T, typename GEQRF, typename ORGQR>
inline lapack_int qr_thin_factor(lapack_int m, lapack_int n, T q[], T tau[], T r[], GEQRF geqrf, ORGQR orgqr)
{
auto info = geqrf(LAPACK_COL_MAJOR, m, n, q, m, tau);
for (auto i = 0; i < n; ++i)
{
for (auto j = 0; j < n; ++j)
{
if (i <= j)
{
r[j * n + i] = q[j * m + i];
}
}
}
if (info != 0)
{
return info;
}
info = orgqr(LAPACK_COL_MAJOR, m, n, n, q, m, tau);
return info;
}
template<typename T, typename GELS>
inline lapack_int qr_solve(lapack_int m, lapack_int n, lapack_int bn, T a[], T b[], T x[], GELS gels)
{
try
{
auto clone_a = array_clone(m * n, a);
auto clone_b = array_clone(m * bn, b);
auto info = gels(LAPACK_COL_MAJOR, 'N', m, n, bn, clone_a.get(), m, clone_b.get(), m);
if (info != 0)
{
return info;
}
copyBtoX(m, n, bn, clone_b.get(), x);
return info;
}
catch (std::bad_alloc&)
{
return INSUFFICIENT_MEMORY;
}
}
template<typename T, typename ORMQR, typename TRSM>
inline lapack_int qr_solve_factored(lapack_int m, lapack_int n, lapack_int bn, T r[], T b[], T tau[], T x[], ORMQR ormqr, TRSM trsm)
{
try
{
auto clone_b = array_clone(m * bn, b);
auto info = ormqr(LAPACK_COL_MAJOR, 'L', 'T', m, bn, n, r, m, tau, clone_b.get(), m);
if (info != 0)
{
return info;
}
trsm(CblasColMajor, CblasLeft, CblasUpper, CblasNoTrans, CblasNonUnit, n, bn, 1.0, r, m, clone_b.get(), m);
copyBtoX(m, n, bn, clone_b.get(), x);
return info;
}
catch (std::bad_alloc&)
{
return INSUFFICIENT_MEMORY;
}
}
template<typename T, typename R, typename UNMQR, typename TRSM>
inline lapack_int complex_qr_solve_factored(lapack_int m, lapack_int n, lapack_int bn, T r[], T b[], T tau[], T x[], UNMQR unmqr, TRSM trsm)
{
try
{
auto clone_b = array_clone(m * bn, b);
auto info = unmqr(LAPACK_COL_MAJOR, 'L', 'C', m, bn, n, r, m, tau, clone_b.get(), m);
if (info != 0)
{
return info;
}
T one = 1.0f;
trsm(CblasColMajor, CblasLeft, CblasUpper, CblasNoTrans, CblasNonUnit, n, bn, reinterpret_cast<R*>(&one), reinterpret_cast<R*>(r), m, reinterpret_cast<R*>(clone_b.get()), m);
copyBtoX(m, n, bn, clone_b.get(), x);
return info;
}
catch (std::bad_alloc&)
{
return INSUFFICIENT_MEMORY;
}
}
template<typename T, typename GESVD>
inline lapack_int svd_factor(bool compute_vectors, lapack_int m, lapack_int n, T a[], T s[], T u[], T v[], GESVD gesvd)
{
try
{
auto job = compute_vectors ? 'A' : 'N';
auto dim_s = std::min(m, n);
auto superb = array_new<T>(std::max(2, dim_s) - 1);
return gesvd(LAPACK_COL_MAJOR, job, job, m, n, a, m, s, u, m, v, n, superb.get());
}
catch (std::bad_alloc&)
{
return INSUFFICIENT_MEMORY;
}
}
template<typename T, typename R, typename GESVD>
inline lapack_int complex_svd_factor(bool compute_vectors, lapack_int m, lapack_int n, T a[], T s[], T u[], T v[], GESVD gesvd)
{
try
{
auto dim_s = std::min(m, n);
auto s_local = array_new<R>(dim_s);
auto superb = array_new<R>(std::max(2, dim_s) - 1);
auto job = compute_vectors ? 'A' : 'N';
auto info = gesvd(LAPACK_COL_MAJOR, job, job, m, n, a, m, s_local.get(), u, m, v, n, superb.get());
for (auto index = 0; index < dim_s; ++index)
{
s[index] = s_local.get()[index];
}
return info;
}
catch (std::bad_alloc&)
{
return INSUFFICIENT_MEMORY;
}
}
template<typename T, typename R, typename GEES, typename TREVC>
inline lapack_int eigen_factor(lapack_int n, T a[], T vectors[], R values[], T d[], GEES gees, TREVC trevc)
{
try
{
auto clone_a = array_clone(n * n, a);
auto wr = array_new<T>(n);
auto wi = array_new<T>(n);
lapack_int sdim;
lapack_int info = gees(LAPACK_COL_MAJOR, 'V', 'N', nullptr, n, clone_a.get(), n, &sdim, wr.get(), wi.get(), vectors, n);
if (info != 0)
{
return info;
}
lapack_int m;
info = trevc(LAPACK_COL_MAJOR, 'R', 'B', nullptr, n, clone_a.get(), n, nullptr, n, vectors, n, n, &m);
if (info != 0)
{
return info;
}
for (auto index = 0; index < n; ++index)
{
values[index] = R(wr.get()[index], wi.get()[index]);
}
for (auto i = 0; i < n; ++i)
{
auto in = i * n;
d[in + i] = wr.get()[i];
if (wi.get()[i] > 0)
{
d[in + n + i] = wi.get()[i];
}
else if (wi.get()[i] < 0)
{
d[in - n + i] = wi.get()[i];
}
}
return info;
}
catch (std::bad_alloc&)
{
return INSUFFICIENT_MEMORY;
}
}
template<typename T, typename GEES, typename TREVC>
inline lapack_int eigen_complex_factor(lapack_int n, T a[], T vectors[], lapack_complex_double values[], T d[], GEES gees, TREVC trevc)
{
try
{
auto clone_a = array_clone(n * n, a);
auto w = array_new<T>(n);
lapack_int sdim;
lapack_int info = gees(LAPACK_COL_MAJOR, 'V', 'N', nullptr, n, clone_a.get(), n, &sdim, w.get(), vectors, n);
if (info != 0)
{
return info;
}
lapack_int m;
info = trevc(LAPACK_COL_MAJOR, 'R', 'B', nullptr, n, clone_a.get(), n, nullptr, n, vectors, n, n, &m);
if (info != 0)
{
return info;
}
for (auto i = 0; i < n; ++i)
{
values[i] = w.get()[i];
d[i * n + i] = w.get()[i];
}
return info;
}
catch (std::bad_alloc&)
{
return INSUFFICIENT_MEMORY;
}
}
template<typename R, typename T, typename SYEV>
inline lapack_int sym_eigen_factor(lapack_int n, T a[], T vectors[], lapack_complex_double values[], T d[], SYEV syev)
{
try
{
auto clone_a = array_clone(n * n, a);
auto w = array_new<R>(n);
lapack_int info = syev(LAPACK_COL_MAJOR, 'V', 'U', n, clone_a.get(), n, w.get());
if (info != 0)
{
return info;
}
memcpy(vectors, clone_a.get(), n*n*sizeof(T));
for (auto index = 0; index < n; ++index)
{
values[index] = lapack_complex_double(w.get()[index]);
}
for (auto j = 0; j < n; ++j)
{
auto jn = j*n;
for (auto i = 0; i < n; ++i)
{
if (i == j)
{
d[jn + i] = w.get()[i];
}
}
}
return info;
}
catch (std::bad_alloc&)
{
return INSUFFICIENT_MEMORY;
}
}
extern "C" {
DLLEXPORT float s_matrix_norm(char norm, lapack_int m, lapack_int n, float a[])
{
return LAPACKE_slange(LAPACK_COL_MAJOR, norm, m, n, a, m);
}
DLLEXPORT double d_matrix_norm(char norm, lapack_int m, lapack_int n, double a[])
{
return LAPACKE_dlange(LAPACK_COL_MAJOR, norm, m, n, a, m);
}
DLLEXPORT float c_matrix_norm(char norm, lapack_int m, lapack_int n, lapack_complex_float a[])
{
return LAPACKE_clange(LAPACK_COL_MAJOR, norm, m, n, a, m);
}
DLLEXPORT double z_matrix_norm(char norm, lapack_int m, lapack_int n, lapack_complex_double a[])
{
return LAPACKE_zlange(LAPACK_COL_MAJOR, norm, m, n, a, m);
}
DLLEXPORT lapack_int s_lu_factor(lapack_int m, float a[], lapack_int ipiv[])
{
return lu_factor(m, a, ipiv, LAPACKE_sgetrf);
}
DLLEXPORT lapack_int d_lu_factor(lapack_int m, double a[], lapack_int ipiv[])
{
return lu_factor(m, a, ipiv, LAPACKE_dgetrf);
}
DLLEXPORT lapack_int c_lu_factor(lapack_int m, lapack_complex_float a[], lapack_int ipiv[])
{
return lu_factor(m, a, ipiv, LAPACKE_cgetrf);
}
DLLEXPORT lapack_int z_lu_factor(lapack_int m, lapack_complex_double a[], lapack_int ipiv[])
{
return lu_factor(m, a, ipiv, LAPACKE_zgetrf);
}
DLLEXPORT lapack_int s_lu_inverse(lapack_int n, float a[], float work[], lapack_int lwork)
{
return lu_inverse(n, a, LAPACKE_sgetrf, LAPACKE_sgetri);
}
DLLEXPORT lapack_int d_lu_inverse(lapack_int n, double a[], double work[], lapack_int lwork)
{
return lu_inverse(n, a, LAPACKE_dgetrf, LAPACKE_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, LAPACKE_cgetrf, LAPACKE_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, LAPACKE_zgetrf, LAPACKE_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, LAPACKE_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, LAPACKE_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, LAPACKE_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, LAPACKE_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, LAPACKE_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, LAPACKE_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, LAPACKE_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, LAPACKE_zgetrs);
}
DLLEXPORT lapack_int s_lu_solve(lapack_int n, lapack_int nrhs, float a[], float b[])
{
return lu_solve(n, nrhs, a, b, LAPACKE_sgetrf, LAPACKE_sgetrs);
}
DLLEXPORT lapack_int d_lu_solve(lapack_int n, lapack_int nrhs, double a[], double b[])
{
return lu_solve(n, nrhs, a, b, LAPACKE_dgetrf, LAPACKE_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, LAPACKE_cgetrf, LAPACKE_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, LAPACKE_zgetrf, LAPACKE_zgetrs);
}
DLLEXPORT lapack_int s_cholesky_factor(lapack_int n, float a[])
{
return cholesky_factor(n, a, LAPACKE_spotrf);
}
DLLEXPORT lapack_int d_cholesky_factor(lapack_int n, double* a)
{
return cholesky_factor(n, a, LAPACKE_dpotrf);
}
DLLEXPORT lapack_int c_cholesky_factor(lapack_int n, lapack_complex_float a[])
{
return cholesky_factor(n, a, LAPACKE_cpotrf);
}
DLLEXPORT lapack_int z_cholesky_factor(lapack_int n, lapack_complex_double a[])
{
return cholesky_factor(n, a, LAPACKE_zpotrf);
}
DLLEXPORT lapack_int s_cholesky_solve(lapack_int n, lapack_int nrhs, float a[], float b[])
{
return cholesky_solve(n, nrhs, a, b, LAPACKE_spotrf, LAPACKE_spotrs);
}
DLLEXPORT lapack_int d_cholesky_solve(lapack_int n, lapack_int nrhs, double a[], double b[])
{
return cholesky_solve(n, nrhs, a, b, LAPACKE_dpotrf, LAPACKE_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, LAPACKE_cpotrf, LAPACKE_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, LAPACKE_zpotrf, LAPACKE_zpotrs);
}
DLLEXPORT lapack_int s_cholesky_solve_factored(lapack_int n, lapack_int nrhs, float a[], float b[])
{
return LAPACKE_spotrs(LAPACK_COL_MAJOR, 'L', n, nrhs, a, n, b, n);
}
DLLEXPORT lapack_int d_cholesky_solve_factored(lapack_int n, lapack_int nrhs, double a[], double b[])
{
return LAPACKE_dpotrs(LAPACK_COL_MAJOR, 'L', n, nrhs, a, n, b, n);
}
DLLEXPORT lapack_int c_cholesky_solve_factored(lapack_int n, lapack_int nrhs, lapack_complex_float a[], lapack_complex_float b[])
{
return LAPACKE_cpotrs(LAPACK_COL_MAJOR, 'L', n, nrhs, a, n, b, n);
}
DLLEXPORT lapack_int z_cholesky_solve_factored(lapack_int n, lapack_int nrhs, lapack_complex_double a[], lapack_complex_double b[])
{
return LAPACKE_zpotrs(LAPACK_COL_MAJOR, 'L', n, nrhs, a, n, b, n);
}
DLLEXPORT lapack_int s_qr_factor(lapack_int m, lapack_int n, float r[], float tau[], float q[])
{
return qr_factor(m, n, r, tau, q, LAPACKE_sgeqrf, LAPACKE_sorgqr);
}
DLLEXPORT lapack_int s_qr_thin_factor(lapack_int m, lapack_int n, float q[], float tau[], float r[])
{
return qr_thin_factor(m, n, q, tau, r, LAPACKE_sgeqrf, LAPACKE_sorgqr);
}
DLLEXPORT lapack_int d_qr_factor(lapack_int m, lapack_int n, double r[], double tau[], double q[])
{
return qr_factor(m, n, r, tau, q, LAPACKE_dgeqrf, LAPACKE_dorgqr);
}
DLLEXPORT lapack_int d_qr_thin_factor(lapack_int m, lapack_int n, double q[], double tau[], double r[])
{
return qr_thin_factor(m, n, q, tau, r, LAPACKE_dgeqrf, LAPACKE_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[])
{
return qr_factor(m, n, r, tau, q, LAPACKE_cgeqrf, LAPACKE_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[])
{
return qr_thin_factor(m, n, q, tau, r, LAPACKE_cgeqrf, LAPACKE_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[])
{
return qr_factor(m, n, r, tau, q, LAPACKE_zgeqrf, LAPACKE_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[])
{
return qr_thin_factor(m, n, q, tau, r, LAPACKE_zgeqrf, LAPACKE_zungqr);
}
DLLEXPORT lapack_int s_qr_solve(lapack_int m, lapack_int n, lapack_int bn, float a[], float b[], float x[])
{
return qr_solve(m, n, bn, a, b, x, LAPACKE_sgels);
}
DLLEXPORT lapack_int d_qr_solve(lapack_int m, lapack_int n, lapack_int bn, double a[], double b[], double x[])
{
return qr_solve(m, n, bn, a, b, x, LAPACKE_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[])
{
return qr_solve(m, n, bn, a, b, x, LAPACKE_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[])
{
return qr_solve(m, n, bn, a, b, x, LAPACKE_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[])
{
return qr_solve_factored(m, n, bn, r, b, tau, x, LAPACKE_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[])
{
return qr_solve_factored(m, n, bn, r, b, tau, x, LAPACKE_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[])
{
return complex_qr_solve_factored<lapack_complex_float, float>(m, n, bn, r, b, tau, x, LAPACKE_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[])
{
return complex_qr_solve_factored<lapack_complex_double, double>(m, n, bn, r, b, tau, x, LAPACKE_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[])
{
return svd_factor(compute_vectors, m, n, a, s, u, v, LAPACKE_sgesvd);
}
DLLEXPORT lapack_int d_svd_factor(bool compute_vectors, lapack_int m, lapack_int n, double a[], double s[], double u[], double v[])
{
return svd_factor(compute_vectors, m, n, a, s, u, v, LAPACKE_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[])
{
return complex_svd_factor<lapack_complex_float, float>(compute_vectors, m, n, a, s, u, v, LAPACKE_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[])
{
return complex_svd_factor<lapack_complex_double, double>(compute_vectors, m, n, a, s, u, v, LAPACKE_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<float>(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<double>(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<float>(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<double>(n, a, vectors, values, d, LAPACKE_zheev);
}
else
{
return eigen_complex_factor(n, a, vectors, values, d, LAPACKE_zgees, LAPACKE_ztrevc);
}
}
}

54
src/NativeProviders/Common/lapack_common.h

@ -1,38 +1,62 @@
#ifndef LAPACK_COMMON_H
#define LAPACK_COMMON_H
#pragma once
#include <string.h>
const int INSUFFICIENT_MEMORY = -999999;
void shift_ipiv_down(int m, int ipiv[]);
inline void shift_ipiv_down(int m, int ipiv[]){
for(int i = 0; i < m; ++i ){
#ifndef LAPACK_MEMORY
#define LAPACK_MEMORY
#include <memory>
template <typename T> using array_ptr = std::unique_ptr<T[]>;
template<typename T>
inline array_ptr<T> array_new(const int size)
{
return array_ptr<T>(new T[size]);
}
#endif
template<typename T>
inline array_ptr<T> array_clone(const int size, const T* array)
{
auto clone = array_new<T>(size);
memcpy(clone.get(), array, size * sizeof(T));
return clone;
}
inline void shift_ipiv_down(int m, int ipiv[])
{
for(auto i = 0; i < m; ++i )
{
ipiv[i] -= 1;
}
}
void shift_ipiv_up(int m, int ipiv[]);
inline void shift_ipiv_up(int m, int ipiv[]){
for(int i = 0; i < m; ++i ){
inline void shift_ipiv_up(int m, int ipiv[])
{
for(auto i = 0; i < m; ++i )
{
ipiv[i] += 1;
}
}
template<typename T>
inline T* Clone(const int m, const int n, const T* a){
T* clone = new T[m*n];
inline T* Clone(const int m, const int n, const T* a)
{
auto clone = new T[m*n];
memcpy(clone, a, m*n*sizeof(T));
return clone;
}
template<typename T>
inline void copyBtoX (int m, int n, int bn, T b[], T x[]){
for (int i = 0; i < n; ++i)
inline void copyBtoX (int m, int n, int bn, T b[], T x[])
{
for (auto i = 0; i < n; ++i)
{
for (int j = 0; j < bn; ++j)
for (auto j = 0; j < bn; ++j)
{
x[j * n + i] = b[j * m + i];
}
}
}
#endif

89
src/NativeProviders/MKL/blas.c

@ -1,89 +0,0 @@
#include "mkl_cblas.h"
#include "wrapper_common.h"
#if __cplusplus
extern "C" {
#endif
DLLEXPORT void s_axpy(const MKL_INT n, const float alpha, const float x[], float y[]){
cblas_saxpy(n, alpha, x, 1, y, 1);
}
DLLEXPORT void d_axpy(const MKL_INT n, const double alpha, const double x[], double y[]){
cblas_daxpy(n, alpha, x, 1, y, 1);
}
DLLEXPORT void c_axpy(const MKL_INT n, const MKL_Complex8 alpha, const MKL_Complex8 x[], MKL_Complex8 y[]){
cblas_caxpy(n, &alpha, x, 1, y, 1);
}
DLLEXPORT void z_axpy(const MKL_INT n, const MKL_Complex16 alpha, const MKL_Complex16 x[], MKL_Complex16 y[]){
cblas_zaxpy(n, &alpha, x, 1, y, 1);
}
DLLEXPORT void s_scale(const MKL_INT n, const float alpha, float x[]){
cblas_sscal(n, alpha, x, 1);
}
DLLEXPORT void d_scale(const MKL_INT n, const double alpha, double x[]){
cblas_dscal(n, alpha, x, 1);
}
DLLEXPORT void c_scale(const MKL_INT n, const MKL_Complex8 alpha, MKL_Complex8 x[]){
cblas_cscal(n, &alpha, x, 1);
}
DLLEXPORT void z_scale(const MKL_INT n, const MKL_Complex16 alpha, MKL_Complex16 x[]){
cblas_zscal(n, &alpha, x, 1);
}
DLLEXPORT float s_dot_product(const MKL_INT n, const float x[], const float y[]){
return cblas_sdot(n, x, 1, y, 1);
}
DLLEXPORT double d_dot_product(const MKL_INT n, const double x[], const double y[]){
return cblas_ddot(n, x, 1, y, 1);
}
DLLEXPORT MKL_Complex8 c_dot_product(const MKL_INT n, const MKL_Complex8 x[], const MKL_Complex8 y[]){
MKL_Complex8 ret;
cblas_cdotu_sub(n, x, 1, y, 1, &ret);
return ret;
}
DLLEXPORT MKL_Complex16 z_dot_product(const MKL_INT n, const MKL_Complex16 x[], const MKL_Complex16 y[]){
MKL_Complex16 ret;
cblas_zdotu_sub(n, x, 1, y, 1, &ret);
return ret;
}
DLLEXPORT void s_matrix_multiply(CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB, const MKL_INT m, const MKL_INT n, const MKL_INT k, const float alpha, const float x[], const float y[], const float beta, float c[]){
MKL_INT lda = transA == CblasNoTrans ? m : k;
MKL_INT 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 MKL_INT m, const MKL_INT n, const MKL_INT k, const double alpha, const double x[], const double y[], const double beta, double c[]){
MKL_INT lda = transA == CblasNoTrans ? m : k;
MKL_INT 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 MKL_INT m, const MKL_INT n, const MKL_INT k, const MKL_Complex8 alpha, const MKL_Complex8 x[], const MKL_Complex8 y[], const MKL_Complex8 beta, MKL_Complex8 c[]){
MKL_INT lda = transA == CblasNoTrans ? m : k;
MKL_INT ldb = transB == CblasNoTrans ? k : n;
cblas_cgemm(CblasColMajor, transA, transB, m, n, k, &alpha, x, lda, y, ldb, &beta, c, m);
}
DLLEXPORT void z_matrix_multiply(CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB, const MKL_INT m, const MKL_INT n, const MKL_INT k, const MKL_Complex16 alpha, const MKL_Complex16 x[], const MKL_Complex16 y[], const MKL_Complex16 beta, MKL_Complex16 c[]){
MKL_INT lda = transA == CblasNoTrans ? m : k;
MKL_INT ldb = transB == CblasNoTrans ? k : n;
cblas_zgemm(CblasColMajor, transA, transB, m, n, k, &alpha, x, lda, y, ldb, &beta, c, m);
}
#if __cplusplus
}
#endif

7
src/NativeProviders/MKL/blas.h

@ -0,0 +1,7 @@
#pragma once
#include "mkl_cblas.h"
#define blas_int MKL_INT
#define blas_complex_float MKL_Complex8
#define blas_complex_double MKL_Complex16

713
src/NativeProviders/MKL/lapack.cpp

@ -1,713 +0,0 @@
#include <algorithm>
#include <complex>
#define MKL_Complex8 std::complex<float>
#define MKL_Complex16 std::complex<double>
#include "mkl_lapack.h"
#include "mkl_cblas.h"
#include "lapack_common.h"
#include "wrapper_common.h"
#include "mkl_lapacke.h"
#include "mkl.h"
#include "mkl_trans.h"
template<typename T, typename GETRF>
inline MKL_INT lu_factor(MKL_INT m, T a[], MKL_INT ipiv[], GETRF getrf)
{
MKL_INT info = 0;
getrf(&m, &m, a, &m, ipiv, &info);
shift_ipiv_down(m, ipiv);
return info;
}
template<typename T, typename GETRF, typename GETRI>
inline MKL_INT lu_inverse(MKL_INT n, T a[], T work[], MKL_INT lwork, GETRF getrf, GETRI getri)
{
MKL_INT* ipiv = new MKL_INT[n];
MKL_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<typename T, typename GETRI>
inline MKL_INT lu_inverse_factored(MKL_INT n, T a[], MKL_INT ipiv[], T work[], MKL_INT lwork, GETRI getri)
{
shift_ipiv_up(n, ipiv);
MKL_INT info = 0;
getri(&n, a, &n, ipiv, work, &lwork, &info);
shift_ipiv_down(n, ipiv);
return info;
}
template<typename T, typename GETRS>
inline MKL_INT lu_solve_factored(MKL_INT n, MKL_INT nrhs, T a[], MKL_INT ipiv[], T b[], GETRS getrs)
{
shift_ipiv_up(n, ipiv);
MKL_INT info = 0;
char trans ='N';
getrs(&trans, &n, &nrhs, a, &n, ipiv, b, &n, &info);
shift_ipiv_down(n, ipiv);
return info;
}
template<typename T, typename GETRF, typename GETRS>
inline MKL_INT lu_solve(MKL_INT n, MKL_INT nrhs, T a[], T b[], GETRF getrf, GETRS getrs)
{
T* clone = Clone(n, n, a);
MKL_INT* ipiv = new MKL_INT[n];
MKL_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<typename T, typename POTRF>
inline MKL_INT cholesky_factor(MKL_INT n, T* a, POTRF potrf)
{
char uplo = 'L';
MKL_INT info = 0;
potrf(&uplo, &n, a, &n, &info);
T zero = T();
for (MKL_INT i = 0; i < n; ++i)
{
MKL_INT index = i * n;
for (MKL_INT j = 0; j < n && i > j; ++j)
{
a[index + j] = zero;
}
}
return info;
}
template<typename T, typename POTRF, typename POTRS>
inline MKL_INT cholesky_solve(MKL_INT n, MKL_INT nrhs, T a[], T b[], POTRF potrf, POTRS potrs)
{
T* clone = Clone(n, n, a);
char uplo = 'L';
MKL_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<typename T, typename POTRS>
inline MKL_INT cholesky_solve_factored(MKL_INT n, MKL_INT nrhs, T a[], T b[], POTRS potrs)
{
char uplo = 'L';
MKL_INT info = 0;
potrs(&uplo, &n, &nrhs, a, &n, b, &n, &info);
return info;
}
template<typename T, typename GEQRF, typename ORGQR>
inline MKL_INT qr_factor(MKL_INT m, MKL_INT n, T r[], T tau[], T q[], T work[], MKL_INT len, GEQRF geqrf, ORGQR orgqr)
{
MKL_INT info = 0;
geqrf(&m, &n, r, &m, tau, work, &len, &info);
for (MKL_INT i = 0; i < m; ++i)
{
for (MKL_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<typename T, typename GEQRF, typename ORGQR>
inline MKL_INT qr_thin_factor(MKL_INT m, MKL_INT n, T q[], T tau[], T r[], T work[], MKL_INT len, GEQRF geqrf, ORGQR orgqr)
{
MKL_INT info = 0;
geqrf(&m, &n, q, &m, tau, work, &len, &info);
for (MKL_INT i = 0; i < n; ++i)
{
for (MKL_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<typename T, typename GELS>
inline MKL_INT qr_solve(MKL_INT m, MKL_INT n, MKL_INT bn, T a[], T b[], T x[], T work[], MKL_INT len, GELS gels)
{
T* clone_a = Clone(m, n, a);
T* clone_b = Clone(m, bn, b);
char N = 'N';
MKL_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<typename T, typename ORMQR, typename TRSM>
inline MKL_INT qr_solve_factored(MKL_INT m, MKL_INT n, MKL_INT bn, T r[], T b[], T tau[], T x[], T work[], MKL_INT len, ORMQR ormqr, TRSM trsm)
{
T* clone_b = Clone(m, bn, b);
char side ='L';
char tran = 'T';
MKL_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<typename T, typename UNMQR, typename TRSM>
inline MKL_INT complex_qr_solve_factored(MKL_INT m, MKL_INT n, MKL_INT bn, T r[], T b[], T tau[], T x[], T work[], MKL_INT len, UNMQR unmqr, TRSM trsm)
{
T* clone_b = Clone(m, bn, b);
char side ='L';
char tran = 'C';
MKL_INT info = 0;
unmqr(&side, &tran, &m, &bn, &n, r, &m, tau, clone_b, &m, work, &len, &info);
T one = 1.0f;
trsm(CblasColMajor, CblasLeft, CblasUpper, CblasNoTrans, CblasNonUnit, n, bn, &one, r, m, clone_b, m);
copyBtoX(m, n, bn, clone_b, x);
delete[] clone_b;
return info;
}
template<typename T, typename GESVD>
inline MKL_INT svd_factor(bool compute_vectors, MKL_INT m, MKL_INT n, T a[], T s[], T u[], T v[], T work[], MKL_INT len, GESVD gesvd)
{
MKL_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<typename T, typename R, typename GESVD>
inline MKL_INT complex_svd_factor(bool compute_vectors, MKL_INT m, MKL_INT n, T a[], T s[], T u[], T v[], T work[], MKL_INT len, GESVD gesvd)
{
MKL_INT info = 0;
MKL_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 (MKL_INT index = 0; index < dim_s; ++index)
{
s[index] = s_local[index];
}
delete[] rwork;
delete[] s_local;
return info;
}
template<typename T, typename R, typename GEES, typename TREVC>
inline MKL_INT eigen_factor(MKL_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];
MKL_INT sdim;
MKL_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;
}
MKL_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 (MKL_INT index = 0; index < n; ++index)
{
values[index] = R(wr[index], wi[index]);
}
for (MKL_INT i = 0; i < n; ++i)
{
MKL_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<typename T, typename GEES, typename TREVC>
inline MKL_INT eigen_complex_factor(MKL_INT n, T a[], T vectors[], MKL_Complex16 values[], T d[], GEES gees, TREVC trevc)
{
T* clone_a = Clone(n, n, a);
T* w = new T[n];
MKL_INT sdim;
MKL_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;
}
MKL_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 (MKL_INT i = 0; i < n; ++i)
{
values[i] = w[i];
d[i * n + i] = w[i];
}
delete[] clone_a;
delete[] w;
return info;
}
template<typename R, typename T, typename SYEV>
inline MKL_INT sym_eigen_factor(MKL_INT n, T a[], T vectors[], MKL_Complex16 values[], T d[], SYEV syev)
{
T* clone_a = Clone(n, n, a);
R* w = new R[n];
MKL_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 (MKL_INT index = 0; index < n; ++index)
{
values[index] = MKL_Complex16(w[index]);
}
for (MKL_INT j = 0; j < n; ++j)
{
MKL_INT jn = j*n;
for (MKL_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, MKL_INT m, MKL_INT n, float a[], float work[])
{
return slange(&norm, &m, &n, a, &m, work);
}
DLLEXPORT double d_matrix_norm(char norm, MKL_INT m, MKL_INT n, double a[], double work[])
{
return dlange(&norm, &m, &n, a, &m, work);
}
DLLEXPORT float c_matrix_norm(char norm, MKL_INT m, MKL_INT n, MKL_Complex8 a[], float work[])
{
return clange(&norm, &m, &n, a, &m, work);
}
DLLEXPORT double z_matrix_norm(char norm, MKL_INT m, MKL_INT n, MKL_Complex16 a[], double work[])
{
return zlange(&norm, &m, &n, a, &m, work);
}
DLLEXPORT MKL_INT s_lu_factor(MKL_INT m, float a[], MKL_INT ipiv[])
{
return lu_factor(m, a, ipiv, sgetrf);
}
DLLEXPORT MKL_INT d_lu_factor(MKL_INT m, double a[], MKL_INT ipiv[])
{
return lu_factor(m, a, ipiv, dgetrf);
}
DLLEXPORT MKL_INT c_lu_factor(MKL_INT m, MKL_Complex8 a[], MKL_INT ipiv[])
{
return lu_factor(m, a, ipiv, cgetrf);
}
DLLEXPORT MKL_INT z_lu_factor(MKL_INT m, MKL_Complex16 a[], MKL_INT ipiv[])
{
return lu_factor(m, a, ipiv, zgetrf);
}
DLLEXPORT MKL_INT s_lu_inverse(MKL_INT n, float a[], float work[], MKL_INT lwork)
{
return lu_inverse(n, a, work, lwork, sgetrf, sgetri);
}
DLLEXPORT MKL_INT d_lu_inverse(MKL_INT n, double a[], double work[], MKL_INT lwork)
{
return lu_inverse(n, a, work, lwork, dgetrf, dgetri);
}
DLLEXPORT MKL_INT c_lu_inverse(MKL_INT n, MKL_Complex8 a[], MKL_Complex8 work[], MKL_INT lwork)
{
return lu_inverse(n, a, work, lwork, cgetrf, cgetri);
}
DLLEXPORT MKL_INT z_lu_inverse(MKL_INT n, MKL_Complex16 a[], MKL_Complex16 work[], MKL_INT lwork)
{
return lu_inverse(n, a, work, lwork, zgetrf, zgetri);
}
DLLEXPORT MKL_INT s_lu_inverse_factored(MKL_INT n, float a[], MKL_INT ipiv[], float work[], MKL_INT lwork)
{
return lu_inverse_factored(n, a, ipiv, work, lwork, sgetri);
}
DLLEXPORT MKL_INT d_lu_inverse_factored(MKL_INT n, double a[], MKL_INT ipiv[], double work[], MKL_INT lwork)
{
return lu_inverse_factored(n, a, ipiv, work, lwork, dgetri);
}
DLLEXPORT MKL_INT c_lu_inverse_factored(MKL_INT n, MKL_Complex8 a[], MKL_INT ipiv[], MKL_Complex8 work[], MKL_INT lwork)
{
return lu_inverse_factored(n, a, ipiv, work, lwork, cgetri);
}
DLLEXPORT MKL_INT z_lu_inverse_factored(MKL_INT n, MKL_Complex16 a[], MKL_INT ipiv[], MKL_Complex16 work[], MKL_INT lwork)
{
return lu_inverse_factored(n, a, ipiv, work, lwork, zgetri);
}
DLLEXPORT MKL_INT s_lu_solve_factored(MKL_INT n, MKL_INT nrhs, float a[], MKL_INT ipiv[], float b[])
{
return lu_solve_factored(n, nrhs, a, ipiv, b, sgetrs);
}
DLLEXPORT MKL_INT d_lu_solve_factored(MKL_INT n, MKL_INT nrhs, double a[], MKL_INT ipiv[], double b[])
{
return lu_solve_factored(n, nrhs, a, ipiv, b, dgetrs);
}
DLLEXPORT MKL_INT c_lu_solve_factored(MKL_INT n, MKL_INT nrhs, MKL_Complex8 a[], MKL_INT ipiv[], MKL_Complex8 b[])
{
return lu_solve_factored(n, nrhs, a, ipiv, b, cgetrs);
}
DLLEXPORT MKL_INT z_lu_solve_factored(MKL_INT n, MKL_INT nrhs, MKL_Complex16 a[], MKL_INT ipiv[], MKL_Complex16 b[])
{
return lu_solve_factored(n, nrhs, a, ipiv, b, zgetrs);
}
DLLEXPORT MKL_INT s_lu_solve(MKL_INT n, MKL_INT nrhs, float a[], float b[])
{
return lu_solve(n, nrhs, a, b, sgetrf, sgetrs);
}
DLLEXPORT MKL_INT d_lu_solve(MKL_INT n, MKL_INT nrhs, double a[], double b[])
{
return lu_solve(n, nrhs, a, b, dgetrf, dgetrs);
}
DLLEXPORT MKL_INT c_lu_solve(MKL_INT n, MKL_INT nrhs, MKL_Complex8 a[], MKL_Complex8 b[])
{
return lu_solve(n, nrhs, a, b, cgetrf, cgetrs);
}
DLLEXPORT MKL_INT z_lu_solve(MKL_INT n, MKL_INT nrhs, MKL_Complex16 a[], MKL_Complex16 b[])
{
return lu_solve(n, nrhs, a, b, zgetrf, zgetrs);
}
DLLEXPORT MKL_INT s_cholesky_factor(MKL_INT n, float a[])
{
return cholesky_factor(n, a, spotrf);
}
DLLEXPORT MKL_INT d_cholesky_factor(MKL_INT n, double* a)
{
return cholesky_factor(n, a, dpotrf);
}
DLLEXPORT MKL_INT c_cholesky_factor(MKL_INT n, MKL_Complex8 a[])
{
return cholesky_factor(n, a, cpotrf);
}
DLLEXPORT MKL_INT z_cholesky_factor(MKL_INT n, MKL_Complex16 a[])
{
return cholesky_factor(n, a, zpotrf);
}
DLLEXPORT MKL_INT s_cholesky_solve(MKL_INT n, MKL_INT nrhs, float a[], float b[])
{
return cholesky_solve(n, nrhs, a, b, spotrf, spotrs);
}
DLLEXPORT MKL_INT d_cholesky_solve(MKL_INT n, MKL_INT nrhs, double a[], double b[])
{
return cholesky_solve(n, nrhs, a, b, dpotrf, dpotrs);
}
DLLEXPORT MKL_INT c_cholesky_solve(MKL_INT n, MKL_INT nrhs, MKL_Complex8 a[], MKL_Complex8 b[])
{
return cholesky_solve(n, nrhs, a, b, cpotrf, cpotrs);
}
DLLEXPORT MKL_INT z_cholesky_solve(MKL_INT n, MKL_INT nrhs, MKL_Complex16 a[], MKL_Complex16 b[])
{
return cholesky_solve(n, nrhs, a, b, zpotrf, zpotrs);
}
DLLEXPORT MKL_INT s_cholesky_solve_factored(MKL_INT n, MKL_INT nrhs, float a[], float b[])
{
return cholesky_solve_factored(n, nrhs, a, b, spotrs);
}
DLLEXPORT MKL_INT d_cholesky_solve_factored(MKL_INT n, MKL_INT nrhs, double a[], double b[])
{
return cholesky_solve_factored(n, nrhs, a, b, dpotrs);
}
DLLEXPORT MKL_INT c_cholesky_solve_factored(MKL_INT n, MKL_INT nrhs, MKL_Complex8 a[], MKL_Complex8 b[])
{
return cholesky_solve_factored(n, nrhs, a, b, cpotrs);
}
DLLEXPORT MKL_INT z_cholesky_solve_factored(MKL_INT n, MKL_INT nrhs, MKL_Complex16 a[], MKL_Complex16 b[])
{
return cholesky_solve_factored(n, nrhs, a, b, zpotrs);
}
DLLEXPORT MKL_INT s_qr_factor(MKL_INT m, MKL_INT n, float r[], float tau[], float q[], float work[], MKL_INT len)
{
return qr_factor(m, n, r, tau, q, work, len, sgeqrf, sorgqr);
}
DLLEXPORT MKL_INT s_qr_thin_factor(MKL_INT m, MKL_INT n, float q[], float tau[], float r[], float work[], MKL_INT len)
{
return qr_thin_factor(m, n, q, tau, r, work, len, sgeqrf, sorgqr);
}
DLLEXPORT MKL_INT d_qr_factor(MKL_INT m, MKL_INT n, double r[], double tau[], double q[], double work[], MKL_INT len)
{
return qr_factor(m, n, r, tau, q, work, len, dgeqrf, dorgqr);
}
DLLEXPORT MKL_INT d_qr_thin_factor(MKL_INT m, MKL_INT n, double q[], double tau[], double r[], double work[], MKL_INT len)
{
return qr_thin_factor(m, n, q, tau, r, work, len, dgeqrf, dorgqr);
}
DLLEXPORT MKL_INT c_qr_factor(MKL_INT m, MKL_INT n, MKL_Complex8 r[], MKL_Complex8 tau[], MKL_Complex8 q[], MKL_Complex8 work[], MKL_INT len)
{
return qr_factor(m, n, r, tau, q, work, len, cgeqrf, cungqr);
}
DLLEXPORT MKL_INT c_qr_thin_factor(MKL_INT m, MKL_INT n, MKL_Complex8 q[], MKL_Complex8 tau[], MKL_Complex8 r[], MKL_Complex8 work[], MKL_INT len)
{
return qr_thin_factor(m, n, q, tau, r, work, len, cgeqrf, cungqr);
}
DLLEXPORT MKL_INT z_qr_factor(MKL_INT m, MKL_INT n, MKL_Complex16 r[], MKL_Complex16 tau[], MKL_Complex16 q[], MKL_Complex16 work[], MKL_INT len)
{
return qr_factor(m, n, r, tau, q, work, len, zgeqrf, zungqr);
}
DLLEXPORT MKL_INT z_qr_thin_factor(MKL_INT m, MKL_INT n, MKL_Complex16 q[], MKL_Complex16 tau[], MKL_Complex16 r[], MKL_Complex16 work[], MKL_INT len)
{
return qr_thin_factor(m, n, q, tau, r, work, len, zgeqrf, zungqr);
}
DLLEXPORT MKL_INT s_qr_solve(MKL_INT m, MKL_INT n, MKL_INT bn, float a[], float b[], float x[], float work[], MKL_INT len)
{
return qr_solve(m, n, bn, a, b, x, work, len, sgels);
}
DLLEXPORT MKL_INT d_qr_solve(MKL_INT m, MKL_INT n, MKL_INT bn, double a[], double b[], double x[], double work[], MKL_INT len)
{
return qr_solve(m, n, bn, a, b, x, work, len, dgels);
}
DLLEXPORT MKL_INT c_qr_solve(MKL_INT m, MKL_INT n, MKL_INT bn, MKL_Complex8 a[], MKL_Complex8 b[], MKL_Complex8 x[], MKL_Complex8 work[], MKL_INT len)
{
return qr_solve(m, n, bn, a, b, x, work, len, cgels);
}
DLLEXPORT MKL_INT z_qr_solve(MKL_INT m, MKL_INT n, MKL_INT bn, MKL_Complex16 a[], MKL_Complex16 b[], MKL_Complex16 x[], MKL_Complex16 work[], MKL_INT len)
{
return qr_solve(m, n, bn, a, b, x, work, len, zgels);
}
DLLEXPORT MKL_INT s_qr_solve_factored(MKL_INT m, MKL_INT n, MKL_INT bn, float r[], float b[], float tau[], float x[], float work[], MKL_INT len)
{
return qr_solve_factored(m, n, bn, r, b, tau, x, work, len, sormqr, cblas_strsm);
}
DLLEXPORT MKL_INT d_qr_solve_factored(MKL_INT m, MKL_INT n, MKL_INT bn, double r[], double b[], double tau[], double x[], double work[], MKL_INT len)
{
return qr_solve_factored(m, n, bn, r, b, tau, x, work, len, dormqr, cblas_dtrsm);
}
DLLEXPORT MKL_INT c_qr_solve_factored(MKL_INT m, MKL_INT n, MKL_INT bn, MKL_Complex8 r[], MKL_Complex8 b[], MKL_Complex8 tau[], MKL_Complex8 x[], MKL_Complex8 work[], MKL_INT len)
{
return complex_qr_solve_factored(m, n, bn, r, b, tau, x, work, len, cunmqr, cblas_ctrsm);
}
DLLEXPORT MKL_INT z_qr_solve_factored(MKL_INT m, MKL_INT n, MKL_INT bn, MKL_Complex16 r[], MKL_Complex16 b[], MKL_Complex16 tau[], MKL_Complex16 x[], MKL_Complex16 work[], MKL_INT len)
{
return complex_qr_solve_factored(m, n, bn, r, b, tau, x, work, len, zunmqr, cblas_ztrsm);
}
DLLEXPORT MKL_INT s_svd_factor(bool compute_vectors, MKL_INT m, MKL_INT n, float a[], float s[], float u[], float v[], float work[], MKL_INT len)
{
return svd_factor(compute_vectors, m, n, a, s, u, v, work, len, sgesvd);
}
DLLEXPORT MKL_INT d_svd_factor(bool compute_vectors, MKL_INT m, MKL_INT n, double a[], double s[], double u[], double v[], double work[], MKL_INT len)
{
return svd_factor(compute_vectors, m, n, a, s, u, v, work, len, dgesvd);
}
DLLEXPORT MKL_INT c_svd_factor(bool compute_vectors, MKL_INT m, MKL_INT n, MKL_Complex8 a[], MKL_Complex8 s[], MKL_Complex8 u[], MKL_Complex8 v[], MKL_Complex8 work[], MKL_INT len)
{
return complex_svd_factor<MKL_Complex8, float>(compute_vectors, m, n, a, s, u, v, work, len, cgesvd);
}
DLLEXPORT MKL_INT z_svd_factor(bool compute_vectors, MKL_INT m, MKL_INT n, MKL_Complex16 a[], MKL_Complex16 s[], MKL_Complex16 u[], MKL_Complex16 v[], MKL_Complex16 work[], MKL_INT len)
{
return complex_svd_factor<MKL_Complex16, double>(compute_vectors, m, n, a, s, u, v, work, len, zgesvd);
}
DLLEXPORT MKL_INT s_eigen(bool isSymmetric, MKL_INT n, float a[], float vectors[], MKL_Complex16 values[], float d[])
{
if (isSymmetric)
{
return sym_eigen_factor<float>(n, a, vectors, values, d, LAPACKE_ssyev);
}
else
{
return eigen_factor(n, a, vectors, values, d, LAPACKE_sgees, LAPACKE_strevc);
}
}
DLLEXPORT MKL_INT d_eigen(bool isSymmetric, MKL_INT n, double a[], double vectors[], MKL_Complex16 values[], double d[])
{
if (isSymmetric)
{
return sym_eigen_factor<double>(n, a, vectors, values, d, LAPACKE_dsyev);
}
else
{
return eigen_factor(n, a, vectors, values, d, LAPACKE_dgees, LAPACKE_dtrevc);
}
}
DLLEXPORT MKL_INT c_eigen(bool isSymmetric, MKL_INT n, MKL_Complex8 a[], MKL_Complex8 vectors[], MKL_Complex16 values[], MKL_Complex8 d[])
{
if (isSymmetric)
{
return sym_eigen_factor<float>(n, a, vectors, values, d, LAPACKE_cheev);
}
else
{
return eigen_complex_factor(n, a, vectors, values, d, LAPACKE_cgees, LAPACKE_ctrevc);
}
}
DLLEXPORT MKL_INT z_eigen(bool isSymmetric, MKL_INT n, MKL_Complex16 a[], MKL_Complex16 vectors[], MKL_Complex16 values[], MKL_Complex16 d[])
{
if (isSymmetric)
{
return sym_eigen_factor<double>(n, a, vectors, values, d, LAPACKE_zheev);
}
else
{
return eigen_complex_factor(n, a, vectors, values, d, LAPACKE_zgees, LAPACKE_ztrevc);
}
}
}

32
src/NativeProviders/MKL/lapack.h

@ -0,0 +1,32 @@
#pragma once
#include <complex>
#include <memory>
#define MKL_Complex8 std::complex<float>
#define MKL_Complex16 std::complex<double>
#define LAPACK_MEMORY
#include "mkl.h"
const int ALIGNMENT = 64;
struct array_free
{
void operator()(void* x) { mkl_free(x); }
};
template <typename T> using array_ptr = std::unique_ptr<T[], array_free>;
template<typename T>
inline array_ptr<T> array_new(const int size)
{
auto ret = static_cast<T*>(mkl_malloc(size * sizeof(T), ALIGNMENT));
if (!ret)
{
throw new std::bad_alloc();
}
return array_ptr<T>(ret);
}

89
src/NativeProviders/OpenBLAS/blas.c

@ -1,89 +0,0 @@
#include "cblas.h"
#include "wrapper_common.h"
#if __cplusplus
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, (float*)&alpha, (float*)x, 1, (float*)y, 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, (double*)&alpha, (double*)x, 1, (double*)y, 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, (float*)&alpha, (float*)x, 1);
}
DLLEXPORT void z_scale(const blasint n, const openblas_complex_double alpha, openblas_complex_double x[]){
cblas_zscal(n, (double*)&alpha, (double*)x, 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, (float*)x, 1, (float*)y, 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, (double*)x, 1, (double*)y, 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, (float*)&alpha, (float*)x, lda, (float*)y, ldb, (float*)&beta, (float*)c, 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, (double*)&alpha, (double*)x, lda, (double*)y, ldb, (double*)&beta, (double*)c, m);
}
#if __cplusplus
}
#endif

7
src/NativeProviders/OpenBLAS/blas.h

@ -0,0 +1,7 @@
#pragma once
#include "cblas.h"
#define blas_int blasint
#define blas_complex_float openblas_complex_float
#define blas_complex_double openblas_complex_double

39
src/NativeProviders/OpenBLAS/complex.h

@ -1,39 +0,0 @@
template <typename _T>
struct complex
{
_T real, imag;
complex(_T _real = 0, _T _imag = 0)
{
real = _real;
imag = _imag;
}
complex(const complex<_T>& 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<typename _Other> inline
complex& operator=(const complex<_Other>& right)
{
real = (_T)right.real;
imag = (_T)right.imag;
return *this;
}
};

712
src/NativeProviders/OpenBLAS/lapack.cpp

@ -1,712 +0,0 @@
#include "cblas.h"
#include "complex.h"
#define LAPACK_COMPLEX_CUSTOM
#define lapack_complex_float complex<float>
#define lapack_complex_double complex<double>
#include "lapacke.h"
#include "lapack_common.h"
#include "wrapper_common.h"
#include <algorithm>
template<typename T, typename GETRF>
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<typename T, typename GETRF, typename GETRI>
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<typename T, typename GETRI>
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<typename T, typename GETRS>
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<typename T, typename GETRF, typename GETRS>
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<typename T, typename POTRF>
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<typename T, typename POTRF, typename POTRS>
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<typename T, typename POTRS>
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<typename T, typename GEQRF, typename ORGQR>
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<typename T, typename GEQRF, typename ORGQR>
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<typename T, typename GELS>
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<typename T, typename ORMQR, typename TRSM>
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<typename T, typename R, typename UNMQR, typename TRSM>
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, reinterpret_cast<R*>(&one), reinterpret_cast<R*>(r), m, reinterpret_cast<R*>(clone_b), m);
copyBtoX(m, n, bn, clone_b, x);
delete[] clone_b;
return info;
}
template<typename T, typename GESVD>
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<typename T, typename R, typename GESVD>
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<typename T, typename R, typename GEES, typename TREVC>
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<typename T, typename GEES, typename TREVC>
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<typename R, typename T, typename SYEV>
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<lapack_complex_float, float>(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<lapack_complex_double, double>(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<lapack_complex_float, float>(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<lapack_complex_double, double>(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<float>(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<double>(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<float>(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<double>(n, a, vectors, values, d, LAPACKE_zheev);
}
else
{
return eigen_complex_factor(n, a, vectors, values, d, LAPACKE_zgees, LAPACKE_ztrevc);
}
}
}

11
src/NativeProviders/OpenBLAS/lapack.h

@ -0,0 +1,11 @@
#pragma once
#define LAPACK_COMPLEX_CUSTOM
#include <complex>
#define lapack_complex_float std::complex<float>
#define lapack_complex_double std::complex<double>
#include "cblas.h"
#include "lapacke.h"

7
src/NativeProviders/Windows/MKL/MKLWrapper.vcxproj

@ -289,10 +289,10 @@
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\Common\blas.c" />
<ClCompile Include="..\..\Common\lapack.cpp" />
<ClCompile Include="..\..\Common\WindowsDLL.cpp" />
<ClCompile Include="..\..\MKL\capabilities.cpp" />
<ClCompile Include="..\..\MKL\blas.c" />
<ClCompile Include="..\..\MKL\lapack.cpp" />
<ClCompile Include="..\..\MKL\memory.c" />
<ClCompile Include="..\..\MKL\vector_functions.c" />
</ItemGroup>
@ -300,6 +300,9 @@
<ResourceCompile Include="..\..\MKL\resource.rc" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\Common\lapack_common.h" />
<ClInclude Include="..\..\MKL\blas.h" />
<ClInclude Include="..\..\MKL\lapack.h" />
<ClInclude Include="..\..\MKL\resource.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

25
src/NativeProviders/Windows/MKL/MKLWrapper.vcxproj.filters

@ -9,18 +9,12 @@
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<Filter Include="Source Files\Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\MKL\blas.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\MKL\lapack.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\MKL\vector_functions.c">
<Filter>Source Files</Filter>
</ClCompile>
@ -33,15 +27,30 @@
<ClCompile Include="..\..\MKL\memory.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\Common\lapack.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\Common\blas.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\MKL\resource.rc">
<Filter>Resource Files</Filter>
<Filter>Source Files\Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\MKL\resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\MKL\lapack.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\Common\lapack_common.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\MKL\blas.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

8
src/NativeProviders/Windows/OpenBLAS/OpenBLASWrapper.vcxproj

@ -203,16 +203,18 @@
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\Common\blas.c" />
<ClCompile Include="..\..\Common\lapack.cpp" />
<ClCompile Include="..\..\Common\WindowsDLL.cpp" />
<ClCompile Include="..\..\OpenBLAS\blas.c" />
<ClCompile Include="..\..\OpenBLAS\capabilities.cpp" />
<ClCompile Include="..\..\OpenBLAS\lapack.cpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\OpenBLAS\resource.rc" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\OpenBLAS\complex.h" />
<ClInclude Include="..\..\Common\lapack_common.h" />
<ClInclude Include="..\..\OpenBLAS\blas.h" />
<ClInclude Include="..\..\OpenBLAS\lapack.h" />
<ClInclude Include="..\..\OpenBLAS\resource.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

18
src/NativeProviders/Windows/OpenBLAS/OpenBLASWrapper.vcxproj.filters

@ -15,16 +15,16 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\OpenBLAS\blas.c">
<ClCompile Include="..\..\Common\WindowsDLL.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\OpenBLAS\lapack.cpp">
<ClCompile Include="..\..\OpenBLAS\capabilities.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\Common\WindowsDLL.cpp">
<ClCompile Include="..\..\Common\lapack.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\OpenBLAS\capabilities.cpp">
<ClCompile Include="..\..\Common\blas.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
@ -34,10 +34,16 @@
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\OpenBLAS\complex.h">
<ClInclude Include="..\..\OpenBLAS\resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\OpenBLAS\resource.h">
<ClInclude Include="..\..\Common\lapack_common.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\OpenBLAS\lapack.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\OpenBLAS\blas.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>

2
src/Numerics/Control.cs

@ -88,7 +88,9 @@ namespace MathNet.Numerics
break;
default:
#if NATIVE
if (!TryUseNative())
#endif
{
UseManaged();
}

106
src/Numerics/Exceptions.cs

@ -53,6 +53,112 @@ namespace MathNet.Numerics
: base(info, context)
{
}
#endif
}
/// <summary>
/// An error occured calling native provider function.
/// </summary>
[Serializable]
public abstract class NativeInterfaceException : Exception
{
protected NativeInterfaceException()
{
}
protected NativeInterfaceException(string message)
: base(message)
{
}
protected NativeInterfaceException(string message, Exception innerException)
: base(message, innerException)
{
}
#if !PORTABLE
protected NativeInterfaceException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
: base(info, context)
{
}
#endif
}
/// <summary>
/// An error occured calling native provider function.
/// </summary>
[Serializable]
public class InvalidParameterException : NativeInterfaceException
{
public InvalidParameterException()
: base(Resources.InvalidParameter)
{
}
public InvalidParameterException(int parameter)
: base(string.Format(Resources.InvalidParameterWithNumber, parameter))
{
}
public InvalidParameterException(int parameter, Exception innerException)
: base(string.Format(Resources.InvalidParameterWithNumber, parameter), innerException)
{
}
#if !PORTABLE
protected InvalidParameterException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
: base(info, context)
{
}
#endif
}
/// <summary>
/// Native provider was unable to allocate sufficent memory.
/// </summary>
[Serializable]
public class MemoryAllocationException : NativeInterfaceException
{
public MemoryAllocationException()
: base(Resources.MemoryAllocation)
{
}
public MemoryAllocationException(Exception innerException)
: base(Resources.MemoryAllocation, innerException)
{
}
#if !PORTABLE
protected MemoryAllocationException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
: base(info, context)
{
}
#endif
}
/// <summary>
/// Native provider failed LU inversion do to a singular U matrix.
/// </summary>
[Serializable]
public class SingularUMatrixException : NativeInterfaceException
{
public SingularUMatrixException()
: base(Resources.SingularUMatrix)
{
}
public SingularUMatrixException(int element)
: base(string.Format(Resources.SingularUMatrixWithElement, element))
{
}
public SingularUMatrixException(int element, Exception innerException)
: base(string.Format(Resources.SingularUMatrixWithElement, element), innerException)
{
}
#if !PORTABLE
protected SingularUMatrixException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
: base(info, context)
{
}
#endif
}
}

270
src/Numerics/Properties/Resources.Designer.cs

@ -8,12 +8,10 @@
// </auto-generated>
//------------------------------------------------------------------------------
using System.Reflection;
namespace MathNet.Numerics.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
@ -25,38 +23,29 @@ namespace MathNet.Numerics.Properties {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Resources.ResourceManager ResourceManager {
get {
#if NET45REFLECTION
if (object.ReferenceEquals(resourceMan, null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MathNet.Numerics.Properties.Resources", typeof(Resources).GetTypeInfo().Assembly);
resourceMan = temp;
}
#else
if (object.ReferenceEquals(resourceMan, null))
{
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MathNet.Numerics.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
#endif
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
@ -70,7 +59,7 @@ namespace MathNet.Numerics.Properties {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to The accuracy couldn&apos;t be reached with the specified number of iterations..
/// </summary>
@ -79,7 +68,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("AccuracyNotReached", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The array arguments must have the same length..
/// </summary>
@ -88,7 +77,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentArraysSameLength", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The given array is the wrong length. Should be {0}..
/// </summary>
@ -97,7 +86,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentArrayWrongLength", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The argument must be between 0 and 1..
/// </summary>
@ -106,7 +95,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentBetween0And1", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Value cannot be in the range -1 &lt; x &lt; 1..
/// </summary>
@ -115,7 +104,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentCannotBeBetweenOneAndNegativeOne", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Value must be even..
/// </summary>
@ -124,7 +113,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentEven", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The histogram does not contain the value..
/// </summary>
@ -133,7 +122,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentHistogramContainsNot", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Value is expected to be between {0} and {1} (including {0} and {1})..
/// </summary>
@ -142,7 +131,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentInIntervalXYInclusive", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to At least one item of {0} is a null reference (Nothing in Visual Basic)..
/// </summary>
@ -151,7 +140,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentItemNull", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Value must be greater than or equal to one..
/// </summary>
@ -160,7 +149,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentLessThanOne", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Matrix dimensions must agree..
/// </summary>
@ -169,7 +158,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentMatrixDimensions", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Matrix dimensions must agree: {0}..
/// </summary>
@ -178,7 +167,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentMatrixDimensions1", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Matrix dimensions must agree: op1 is {0}, op2 is {1}..
/// </summary>
@ -187,7 +176,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentMatrixDimensions2", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Matrix dimensions must agree: op1 is {0}, op2 is {1}, op3 is {2}..
/// </summary>
@ -196,7 +185,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentMatrixDimensions3", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The requested matrix does not exist..
/// </summary>
@ -205,7 +194,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentMatrixDoesNotExist", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The matrix indices must not be out of range of the given matrix..
/// </summary>
@ -214,7 +203,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentMatrixIndexOutOfRange", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Matrix must not be rank deficient..
/// </summary>
@ -223,7 +212,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentMatrixNotRankDeficient", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Matrix must not be singular..
/// </summary>
@ -232,7 +221,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentMatrixNotSingular", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Matrix must be positive definite..
/// </summary>
@ -241,7 +230,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentMatrixPositiveDefinite", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Matrix column dimensions must agree..
/// </summary>
@ -250,7 +239,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentMatrixSameColumnDimension", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Matrix row dimensions must agree..
/// </summary>
@ -259,7 +248,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentMatrixSameRowDimension", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Matrix must have exactly one column..
/// </summary>
@ -268,7 +257,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentMatrixSingleColumn", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Matrix must have exactly one column and row, thus have only one cell..
/// </summary>
@ -277,7 +266,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentMatrixSingleColumnRow", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Matrix must have exactly one row..
/// </summary>
@ -286,7 +275,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentMatrixSingleRow", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Matrix must be square..
/// </summary>
@ -295,7 +284,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentMatrixSquare", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Matrix must be symmetric..
/// </summary>
@ -304,7 +293,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentMatrixSymmetric", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Matrix must be symmetric positive definite..
/// </summary>
@ -313,7 +302,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentMatrixSymmetricPositiveDefinite", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to In the specified range, the minimum is greater than maximum..
/// </summary>
@ -322,7 +311,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentMinValueGreaterThanMaxValue", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Value must be positive..
/// </summary>
@ -331,7 +320,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentMustBePositive", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Value must neither be infinite nor NaN..
/// </summary>
@ -340,7 +329,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentNotInfinityNaN", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Value must not be negative (zero is ok)..
/// </summary>
@ -349,7 +338,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentNotNegative", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0} is a null reference (Nothing in Visual Basic)..
/// </summary>
@ -358,7 +347,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentNull", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Value must be odd..
/// </summary>
@ -367,7 +356,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentOdd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0} must be greater than {1}..
/// </summary>
@ -376,7 +365,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentOutOfRangeGreater", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0} must be greater than or equal to {1}..
/// </summary>
@ -385,7 +374,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentOutOfRangeGreaterEqual", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0} must be smaller than {1}..
/// </summary>
@ -412,7 +401,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentParameterSetInvalid", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The given expression does not represent a complex number..
/// </summary>
@ -421,7 +410,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentParseComplexNumber", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Value must be positive (and not zero)..
/// </summary>
@ -430,7 +419,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentPositive", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Size must be a Power of Two..
/// </summary>
@ -439,7 +428,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentPowerOfTwo", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Size must be a Power of Two in every dimension..
/// </summary>
@ -448,7 +437,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentPowerOfTwoEveryDimension", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The range between {0} and {1} must be less than or equal to {2}..
/// </summary>
@ -457,7 +446,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentRangeLessEqual", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Arguments must be different objects..
/// </summary>
@ -466,7 +455,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentReferenceDifferent", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Array must have exactly one dimension (and not be null)..
/// </summary>
@ -475,7 +464,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentSingleDimensionArray", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Value is too large..
/// </summary>
@ -484,7 +473,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentTooLarge", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Value is too large for the current iteration limit..
/// </summary>
@ -493,7 +482,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentTooLargeForIterationLimit", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Type mismatch..
/// </summary>
@ -502,7 +491,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentTypeMismatch", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The upper bound must be strictly larger than the lower bound..
/// </summary>
@ -511,7 +500,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentUpperBoundMustBeLargerThanLowerBound", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The upper bound must be at least as large as the lower bound..
/// </summary>
@ -520,7 +509,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentUpperBoundMustBeLargerThanOrEqualToLowerBound", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Array length must be a multiple of {0}..
/// </summary>
@ -529,7 +518,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentVectorLengthsMultipleOf", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to All vectors must have the same dimensionality..
/// </summary>
@ -538,7 +527,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentVectorsSameLength", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The vector must have 3 dimensions..
/// </summary>
@ -547,7 +536,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArgumentVectorThreeDimensional", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The given array is too small. It must be at least {0} long..
/// </summary>
@ -556,7 +545,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ArrayTooSmall", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Big endian files are not supported..
/// </summary>
@ -565,7 +554,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("BigEndianNotSupported", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The supplied collection is empty..
/// </summary>
@ -574,7 +563,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("CollectionEmpty", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Complex matrices are not supported..
/// </summary>
@ -583,7 +572,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ComplexMatricesNotSupported", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An algorithm failed to converge..
/// </summary>
@ -592,7 +581,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ConvergenceFailed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to This feature is not implemented yet (but is planned)..
/// </summary>
@ -601,7 +590,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("FeaturePlannedButNotImplementedYet", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The given file doesn&apos;t exist..
/// </summary>
@ -610,7 +599,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("FileDoesNotExist", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Sample points should be sorted in strictly ascending order.
/// </summary>
@ -619,7 +608,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("Interpolation_Initialize_SamplePointsNotStrictlyAscendingOrder", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to All sample points should be unique..
/// </summary>
@ -628,7 +617,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("Interpolation_Initialize_SamplePointsNotUnique", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Invalid parameterization for the distribution..
/// </summary>
@ -637,7 +626,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("InvalidDistributionParameters", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Invalid Left Boundary Condition..
/// </summary>
@ -646,7 +635,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("InvalidLeftBoundaryCondition", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The operation could not be performed because the accumulator is empty..
/// </summary>
@ -655,7 +644,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("InvalidOperationAccumulatorEmpty", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The operation could not be performed because the histogram is empty..
/// </summary>
@ -664,7 +653,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("InvalidOperationHistogramEmpty", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Not enough points in the distribution..
/// </summary>
@ -673,7 +662,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("InvalidOperationHistogramNotEnoughPoints", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to No Samples Provided. Preparation Required..
/// </summary>
@ -682,7 +671,25 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("InvalidOperationNoSamplesProvided", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An invalid parameter was passed to a native method..
/// </summary>
public static string InvalidParameter {
get {
return ResourceManager.GetString("InvalidParameter", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An invalid parameter was passed to a native method, parameter number : {0}.
/// </summary>
public static string InvalidParameterWithNumber {
get {
return ResourceManager.GetString("InvalidParameterWithNumber", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Invalid Right Boundary Condition..
/// </summary>
@ -691,7 +698,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("InvalidRightBoundaryCondition", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Lag must be positive.
/// </summary>
@ -700,7 +707,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("LagMustBePositive", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Lag must be smaller than the sample size.
/// </summary>
@ -709,7 +716,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("LagMustBeSmallerThanTheSampleSize", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ddd MMM dd HH:mm:ss yyyy.
/// </summary>
@ -718,7 +725,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("MatlabDateHeaderFormat", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Matrices can not be empty and must have at least one row and column..
/// </summary>
@ -727,7 +734,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("MatrixCanNotBeEmpty", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The number of columns of a matrix must be positive..
/// </summary>
@ -736,7 +743,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("MatrixColumnsMustBePositive", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Matrix must be in sparse storage format.
/// </summary>
@ -745,7 +752,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("MatrixMustBeSparse", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The number of rows of a matrix must be positive..
/// </summary>
@ -754,7 +761,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("MatrixRowsMustBePositive", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The number of rows or columns of a matrix must be positive..
/// </summary>
@ -763,7 +770,16 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("MatrixRowsOrColumnsMustBePositive", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Unable to allocate native memory..
/// </summary>
public static string MemoryAllocation {
get {
return ResourceManager.GetString("MemoryAllocation", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Only 1 and 2 dimensional arrays are supported..
/// </summary>
@ -772,7 +788,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("MoreThan2D", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Data must contain at least {0} values..
/// </summary>
@ -781,7 +797,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("MustContainAtLeast", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Name cannot contain a space. name: {0}.
/// </summary>
@ -790,7 +806,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("NameCannotContainASpace", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0} is not a supported type..
/// </summary>
@ -799,7 +815,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("NotSupportedType", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Algorithm experience a numerical break down
///.
@ -809,7 +825,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("NumericalBreakdown", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The two arguments can&apos;t be compared (maybe they are part of a partial ordering?).
/// </summary>
@ -818,7 +834,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("PartialOrderException", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The integer array does not represent a valid permutation..
/// </summary>
@ -827,7 +843,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("PermutationAsIntArrayInvalid", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The sampler&apos;s proposal distribution is not upper bounding the target density..
/// </summary>
@ -836,7 +852,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("ProposalDistributionNoUpperBound", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The algorithm has failed, exceeded the number of iterations allowed or there is no root within the provided bounds..
/// </summary>
@ -845,7 +861,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("RootFindingFailed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The algorithm has failed, exceeded the number of iterations allowed or there is no root within the provided bounds. Consider to use RobustNewtonRaphson instead..
/// </summary>
@ -854,7 +870,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("RootFindingFailedRecommendRobustNewtonRaphson", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The lower and upper bounds must bracket a single root..
/// </summary>
@ -863,7 +879,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("RootMustBeBracketedByBounds", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The algorithm ended without root in the range..
/// </summary>
@ -872,7 +888,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("RootNotFound", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The number of rows must greater than or equal to the number of columns..
/// </summary>
@ -881,7 +897,25 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("RowsLessThanColumns", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to U is singular, and the inversion could not be completed..
/// </summary>
public static string SingularUMatrix {
get {
return ResourceManager.GetString("SingularUMatrix", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to U is singular, and the inversion could not be completed. The {0}-th diagonal element of the factor U is zero..
/// </summary>
public static string SingularUMatrixWithElement {
get {
return ResourceManager.GetString("SingularUMatrixWithElement", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The singular vectors were not computed..
/// </summary>
@ -890,7 +924,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("SingularVectorsNotComputed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to This special case is not supported yet (but is planned)..
/// </summary>
@ -899,7 +933,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("SpecialCasePlannedButNotImplementedYet", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The given stop criterion already exist in the collection..
/// </summary>
@ -908,7 +942,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("StopCriterionDuplicate", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to There is no stop criterion in the collection..
/// </summary>
@ -917,7 +951,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("StopCriterionMissing", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to String parameter cannot be empty or null..
/// </summary>
@ -926,7 +960,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("StringNullOrEmpty", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to We only support sparse matrix with less than int.MaxValue elements..
/// </summary>
@ -935,7 +969,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("TooManyElements", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The moment of the distribution is undefined..
/// </summary>
@ -944,7 +978,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("UndefinedMoment", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to A user defined provider has not been specified..
/// </summary>
@ -953,7 +987,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("UserDefinedProviderNotSpecified", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to User work buffers are not supported by this provider..
/// </summary>
@ -962,7 +996,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("UserWorkBufferNotSupported", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Vectors can not be empty and must have at least one element..
/// </summary>
@ -971,7 +1005,7 @@ namespace MathNet.Numerics.Properties {
return ResourceManager.GetString("VectorCanNotBeEmpty", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The given work array is too small. Check work[0] for the corret size..
/// </summary>

15
src/Numerics/Properties/Resources.resx

@ -421,4 +421,19 @@
<data name="UserWorkBufferNotSupported" xml:space="preserve">
<value>User work buffers are not supported by this provider.</value>
</data>
<data name="InvalidParameter" xml:space="preserve">
<value>An invalid parameter was passed to a native method.</value>
</data>
<data name="InvalidParameterWithNumber" xml:space="preserve">
<value>An invalid parameter was passed to a native method, parameter number : {0}</value>
</data>
<data name="MemoryAllocation" xml:space="preserve">
<value>Unable to allocate native memory.</value>
</data>
<data name="SingularUMatrix" xml:space="preserve">
<value>U is singular, and the inversion could not be completed.</value>
</data>
<data name="SingularUMatrixWithElement" xml:space="preserve">
<value>U is singular, and the inversion could not be completed. The {0}-th diagonal element of the factor U is zero.</value>
</data>
</root>

136
src/Numerics/Providers/LinearAlgebra/Cuda/CudaLinearAlgebraProvider.Complex.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
// Copyright (c) 2009-2015 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -33,7 +33,6 @@
using System;
using System.Numerics;
using System.Security;
using MathNet.Numerics.LinearAlgebra.Factorization;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
@ -295,73 +294,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
BLAS(SafeNativeMethods.z_lu_inverse_factored(_blasHandle, order, a, ipiv));
}
/// <summary>
/// Computes the inverse of matrix using LU factorization.
/// </summary>
/// <param name="a">The N by N matrix to invert. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="work">Not supported. Should be left null.</param>
/// <remarks>This is equivalent to the GETRF and GETRI LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void LUInverse(Complex[] a, int order, Complex[] work)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
if (work != null)
{
throw new ArgumentException(Resources.UserWorkBufferNotSupported);
}
Solver(SafeNativeMethods.z_lu_inverse(_solverHandle, _blasHandle, order, a));
}
/// <summary>
/// Computes the inverse of a previously factored matrix.
/// </summary>
/// <param name="a">The LU factored N by N matrix. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="ipiv">The pivot indices of <paramref name="a"/>.</param>
/// <param name="work">Not supported. Should be left null.</param>
/// <remarks>This is equivalent to the GETRI LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void LUInverseFactored(Complex[] a, int order, int[] ipiv, Complex[] work)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (ipiv == null)
{
throw new ArgumentNullException("ipiv");
}
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
if (ipiv.Length != order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
if (work != null)
{
throw new ArgumentException(Resources.UserWorkBufferNotSupported);
}
BLAS(SafeNativeMethods.z_lu_inverse_factored(_blasHandle, order, a, ipiv));
}
/// <summary>
/// Solves A*X=B for X using LU factorization.
/// </summary>
@ -538,60 +470,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
Solver(SafeNativeMethods.z_cholesky_solve_factored(_solverHandle, orderA, columnsB, a, b));
}
/// <summary>
/// Computes the singular value decomposition of A.
/// </summary>
/// <param name="computeVectors">Compute the singular U and VT vectors or not.</param>
/// <param name="a">On entry, the M by N matrix to decompose. On exit, A may be overwritten.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="s">The singular values of A in ascending value.</param>
/// <param name="u">If <paramref name="computeVectors"/> is <c>true</c>, on exit U contains the left
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void SingularValueDecomposition(bool computeVectors, Complex[] a, int rowsA, int columnsA, Complex[] s, Complex[] u, Complex[] vt)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (s == null)
{
throw new ArgumentNullException("s");
}
if (u == null)
{
throw new ArgumentNullException("u");
}
if (vt == null)
{
throw new ArgumentNullException("vt");
}
if (u.Length != rowsA*rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
if (vt.Length != columnsA*columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
if (s.Length != Math.Min(rowsA, columnsA))
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, null);
}
/// <summary>
/// Solves A*X=B for X using the singular value decomposition of A.
/// </summary>
@ -634,7 +512,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
var clone = new Complex[a.Length];
a.Copy(clone);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt, null);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt);
SvdSolveFactored(rowsA, columnsA, s, u, vt, b, columnsB, x);
}
@ -650,10 +528,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <param name="work">User work buffers are not supported. Should be null.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void SingularValueDecomposition(bool computeVectors, Complex[] a, int rowsA, int columnsA, Complex[] s, Complex[] u, Complex[] vt, Complex[] work)
public override void SingularValueDecomposition(bool computeVectors, Complex[] a, int rowsA, int columnsA, Complex[] s, Complex[] u, Complex[] vt)
{
if (a == null)
{
@ -675,11 +552,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
throw new ArgumentNullException("vt");
}
if (work != null)
{
throw new ArgumentException(Resources.UserWorkBufferNotSupported);
}
if (u.Length != rowsA*rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
@ -696,7 +568,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
}
if (columnsA > rowsA || !computeVectors) // see remarks http://docs.nvidia.com/cuda/cusolver/index.html#cuds-lt-t-gt-gesvd
base.SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, new Complex[rowsA]);
base.SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt);
else Solver(SafeNativeMethods.z_svd_factor(_solverHandle, computeVectors, rowsA, columnsA, a, s, u, vt));
}
}

137
src/Numerics/Providers/LinearAlgebra/Cuda/CudaLinearAlgebraProvider.Complex32.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
// Copyright (c) 2009-2015 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -31,9 +31,7 @@
#if NATIVE
using System;
using System.Numerics;
using System.Security;
using MathNet.Numerics.LinearAlgebra.Factorization;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
@ -295,73 +293,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
BLAS(SafeNativeMethods.c_lu_inverse_factored(_blasHandle, order, a, ipiv));
}
/// <summary>
/// Computes the inverse of matrix using LU factorization.
/// </summary>
/// <param name="a">The N by N matrix to invert. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="work">Not supported. Should be left null.</param>
/// <remarks>This is equivalent to the GETRF and GETRI LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void LUInverse(Complex32[] a, int order, Complex32[] work)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
if (work != null)
{
throw new ArgumentException(Resources.UserWorkBufferNotSupported);
}
Solver(SafeNativeMethods.c_lu_inverse(_solverHandle, _blasHandle, order, a));
}
/// <summary>
/// Computes the inverse of a previously factored matrix.
/// </summary>
/// <param name="a">The LU factored N by N matrix. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="ipiv">The pivot indices of <paramref name="a"/>.</param>
/// <param name="work">Not supported. Should be left null.</param>
/// <remarks>This is equivalent to the GETRI LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void LUInverseFactored(Complex32[] a, int order, int[] ipiv, Complex32[] work)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (ipiv == null)
{
throw new ArgumentNullException("ipiv");
}
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
if (ipiv.Length != order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
if (work != null)
{
throw new ArgumentException(Resources.UserWorkBufferNotSupported);
}
BLAS(SafeNativeMethods.c_lu_inverse_factored(_blasHandle, order, a, ipiv));
}
/// <summary>
/// Solves A*X=B for X using LU factorization.
/// </summary>
@ -538,60 +469,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
Solver(SafeNativeMethods.c_cholesky_solve_factored(_solverHandle, orderA, columnsB, a, b));
}
/// <summary>
/// Computes the singular value decomposition of A.
/// </summary>
/// <param name="computeVectors">Compute the singular U and VT vectors or not.</param>
/// <param name="a">On entry, the M by N matrix to decompose. On exit, A may be overwritten.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="s">The singular values of A in ascending value.</param>
/// <param name="u">If <paramref name="computeVectors"/> is <c>true</c>, on exit U contains the left
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void SingularValueDecomposition(bool computeVectors, Complex32[] a, int rowsA, int columnsA, Complex32[] s, Complex32[] u, Complex32[] vt)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (s == null)
{
throw new ArgumentNullException("s");
}
if (u == null)
{
throw new ArgumentNullException("u");
}
if (vt == null)
{
throw new ArgumentNullException("vt");
}
if (u.Length != rowsA*rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
if (vt.Length != columnsA*columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
if (s.Length != Math.Min(rowsA, columnsA))
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, null);
}
/// <summary>
/// Solves A*X=B for X using the singular value decomposition of A.
/// </summary>
@ -634,7 +511,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
var clone = new Complex32[a.Length];
a.Copy(clone);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt, null);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt);
SvdSolveFactored(rowsA, columnsA, s, u, vt, b, columnsB, x);
}
@ -650,10 +527,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <param name="work">Not supported. Should be left null.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void SingularValueDecomposition(bool computeVectors, Complex32[] a, int rowsA, int columnsA, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] work)
public override void SingularValueDecomposition(bool computeVectors, Complex32[] a, int rowsA, int columnsA, Complex32[] s, Complex32[] u, Complex32[] vt)
{
if (a == null)
{
@ -675,11 +551,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
throw new ArgumentNullException("vt");
}
if (work != null)
{
throw new ArgumentException(Resources.UserWorkBufferNotSupported);
}
if (u.Length != rowsA*rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
@ -696,7 +567,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
}
if (columnsA > rowsA || !computeVectors) // see remarks http://docs.nvidia.com/cuda/cusolver/index.html#cuds-lt-t-gt-gesvd
base.SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, new Complex32[rowsA]);
base.SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt);
else Solver(SafeNativeMethods.c_svd_factor(_solverHandle, computeVectors, rowsA, columnsA, a, s, u, vt));
}
}

135
src/Numerics/Providers/LinearAlgebra/Cuda/CudaLinearAlgebraProvider.Double.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
// Copyright (c) 2009-2015 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -31,9 +31,7 @@
#if NATIVE
using System;
using System.Numerics;
using System.Security;
using MathNet.Numerics.LinearAlgebra.Factorization;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
@ -295,73 +293,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
BLAS(SafeNativeMethods.d_lu_inverse_factored(_blasHandle, order, a, ipiv));
}
/// <summary>
/// Computes the inverse of matrix using LU factorization.
/// </summary>
/// <param name="a">The N by N matrix to invert. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="work">Not supported. Should be left null.</param>
/// <remarks>This is equivalent to the GETRF and GETRI LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void LUInverse(double[] a, int order, double[] work)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
if (work != null)
{
throw new ArgumentException(Resources.UserWorkBufferNotSupported);
}
Solver(SafeNativeMethods.d_lu_inverse(_solverHandle, _blasHandle, order, a));
}
/// <summary>
/// Computes the inverse of a previously factored matrix.
/// </summary>
/// <param name="a">The LU factored N by N matrix. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="ipiv">The pivot indices of <paramref name="a"/>.</param>
/// <param name="work">Not supported. Should be left null.</param>
/// <remarks>This is equivalent to the GETRI LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void LUInverseFactored(double[] a, int order, int[] ipiv, double[] work)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (ipiv == null)
{
throw new ArgumentNullException("ipiv");
}
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
if (ipiv.Length != order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
if (work != null)
{
throw new ArgumentException(Resources.UserWorkBufferNotSupported);
}
BLAS(SafeNativeMethods.d_lu_inverse_factored(_blasHandle, order, a, ipiv));
}
/// <summary>
/// Solves A*X=B for X using LU factorization.
/// </summary>
@ -538,60 +469,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
Solver(SafeNativeMethods.d_cholesky_solve_factored(_solverHandle, orderA, columnsB, a, b));
}
/// <summary>
/// Computes the singular value decomposition of A.
/// </summary>
/// <param name="computeVectors">Compute the singular U and VT vectors or not.</param>
/// <param name="a">On entry, the M by N matrix to decompose. On exit, A may be overwritten.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="s">The singular values of A in ascending value.</param>
/// <param name="u">If <paramref name="computeVectors"/> is <c>true</c>, on exit U contains the left
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void SingularValueDecomposition(bool computeVectors, double[] a, int rowsA, int columnsA, double[] s, double[] u, double[] vt)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (s == null)
{
throw new ArgumentNullException("s");
}
if (u == null)
{
throw new ArgumentNullException("u");
}
if (vt == null)
{
throw new ArgumentNullException("vt");
}
if (u.Length != rowsA*rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
if (vt.Length != columnsA*columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
if (s.Length != Math.Min(rowsA, columnsA))
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, null);
}
/// <summary>
/// Solves A*X=B for X using the singular value decomposition of A.
/// </summary>
@ -650,10 +527,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <param name="work">Not supported. Should be left null.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void SingularValueDecomposition(bool computeVectors, double[] a, int rowsA, int columnsA, double[] s, double[] u, double[] vt, double[] work)
public override void SingularValueDecomposition(bool computeVectors, double[] a, int rowsA, int columnsA, double[] s, double[] u, double[] vt)
{
if (a == null)
{
@ -675,11 +551,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
throw new ArgumentNullException("vt");
}
if (work != null)
{
throw new ArgumentException(Resources.UserWorkBufferNotSupported);
}
if (u.Length != rowsA*rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
@ -696,7 +567,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
}
if (columnsA > rowsA || !computeVectors) // see remarks http://docs.nvidia.com/cuda/cusolver/index.html#cuds-lt-t-gt-gesvd
base.SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, new double[rowsA]);
base.SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt);
else Solver (SafeNativeMethods.d_svd_factor(_solverHandle, computeVectors, rowsA, columnsA, a, s, u, vt));
}
}

137
src/Numerics/Providers/LinearAlgebra/Cuda/CudaLinearAlgebraProvider.Single.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
// Copyright (c) 2009-2015 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -31,9 +31,7 @@
#if NATIVE
using System;
using System.Numerics;
using System.Security;
using MathNet.Numerics.LinearAlgebra.Factorization;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
@ -295,73 +293,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
BLAS(SafeNativeMethods.s_lu_inverse_factored(_blasHandle, order, a, ipiv));
}
/// <summary>
/// Computes the inverse of matrix using LU factorization.
/// </summary>
/// <param name="a">The N by N matrix to invert. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="work">Not supported. Should be left null.</param>
/// <remarks>This is equivalent to the GETRF and GETRI LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void LUInverse(float[] a, int order, float[] work)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
if (work != null)
{
throw new ArgumentException(Resources.UserWorkBufferNotSupported);
}
Solver(SafeNativeMethods.s_lu_inverse(_solverHandle, _blasHandle, order, a));
}
/// <summary>
/// Computes the inverse of a previously factored matrix.
/// </summary>
/// <param name="a">The LU factored N by N matrix. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="ipiv">The pivot indices of <paramref name="a"/>.</param>
/// <param name="work">Not supported. This should be left null.</param>
/// <remarks>This is equivalent to the GETRI LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void LUInverseFactored(float[] a, int order, int[] ipiv, float[] work)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (ipiv == null)
{
throw new ArgumentNullException("ipiv");
}
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
if (ipiv.Length != order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
if (work != null)
{
throw new ArgumentException(Resources.UserWorkBufferNotSupported);
}
BLAS(SafeNativeMethods.s_lu_inverse_factored(_blasHandle, order, a, ipiv));
}
/// <summary>
/// Solves A*X=B for X using LU factorization.
/// </summary>
@ -538,60 +469,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
Solver(SafeNativeMethods.s_cholesky_solve_factored(_solverHandle, orderA, columnsB, a, b));
}
/// <summary>
/// Computes the singular value decomposition of A.
/// </summary>
/// <param name="computeVectors">Compute the singular U and VT vectors or not.</param>
/// <param name="a">On entry, the M by N matrix to decompose. On exit, A may be overwritten.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="s">The singular values of A in ascending value.</param>
/// <param name="u">If <paramref name="computeVectors"/> is <c>true</c>, on exit U contains the left
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void SingularValueDecomposition(bool computeVectors, float[] a, int rowsA, int columnsA, float[] s, float[] u, float[] vt)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (s == null)
{
throw new ArgumentNullException("s");
}
if (u == null)
{
throw new ArgumentNullException("u");
}
if (vt == null)
{
throw new ArgumentNullException("vt");
}
if (u.Length != rowsA*rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
if (vt.Length != columnsA*columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
if (s.Length != Math.Min(rowsA, columnsA))
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, null);
}
/// <summary>
/// Solves A*X=B for X using the singular value decomposition of A.
/// </summary>
@ -634,7 +511,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
var clone = new float[a.Length];
a.Copy(clone);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt, null);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt);
SvdSolveFactored(rowsA, columnsA, s, u, vt, b, columnsB, x);
}
@ -650,10 +527,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <param name="work">Not supported. Should be left null.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void SingularValueDecomposition(bool computeVectors, float[] a, int rowsA, int columnsA, float[] s, float[] u, float[] vt, float[] work)
public override void SingularValueDecomposition(bool computeVectors, float[] a, int rowsA, int columnsA, float[] s, float[] u, float[] vt)
{
if (a == null)
{
@ -675,11 +551,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
throw new ArgumentNullException("vt");
}
if (work != null)
{
throw new ArgumentException(Resources.UserWorkBufferNotSupported);
}
if (u.Length != rowsA*rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
@ -696,7 +567,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
}
if (columnsA > rowsA || !computeVectors) // see remarks http://docs.nvidia.com/cuda/cusolver/index.html#cuds-lt-t-gt-gesvd
base.SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, new float[rowsA]);
base.SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt);
else Solver(SafeNativeMethods.s_svd_factor(_solverHandle, computeVectors, rowsA, columnsA, a, s, u, vt));
}
}

112
src/Numerics/Providers/LinearAlgebra/ILinearAlgebraProvider.cs

@ -269,29 +269,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
/// <remarks>This is equivalent to the GETRI LAPACK routine.</remarks>
void LUInverseFactored(T[] a, int order, int[] ipiv);
/// <summary>
/// Computes the inverse of matrix using LU factorization.
/// </summary>
/// <param name="a">The N by N matrix to invert. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is equivalent to the GETRF and GETRI LAPACK routines.</remarks>
void LUInverse(T[] a, int order, T[] work);
/// <summary>
/// Computes the inverse of a previously factored matrix.
/// </summary>
/// <param name="a">The LU factored N by N matrix. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="ipiv">The pivot indices of <paramref name="a"/>.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is equivalent to the GETRI LAPACK routine.</remarks>
void LUInverseFactored(T[] a, int order, int[] ipiv, T[] work);
/// <summary>
/// Solves A*X=B for X using LU factorization.
/// </summary>
@ -356,23 +333,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
void QRFactor(T[] a, int rowsA, int columnsA, T[] q, T[] tau);
/// <summary>
/// Computes the full QR factorization of A.
/// </summary>
/// <param name="a">On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
void QRFactor(T[] a, int rowsA, int columnsA, T[] q, T[] tau, T[] work);
/// <summary>
/// Computes the thin QR factorization of A where M &gt; N.
/// </summary>
@ -387,23 +347,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
void ThinQRFactor(T[] a, int rowsA, int columnsA, T[] r, T[] tau);
/// <summary>
/// Computes the thin QR factorization of A where M &gt; N.
/// </summary>
/// <param name="a">On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the Q matrix of the QR factorization.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="r">On exit, A N by N matrix that holds the R matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
void ThinQRFactor(T[] a, int rowsA, int columnsA, T[] r, T[] tau, T[] work);
/// <summary>
/// Solves A*X=B for X using QR factorization of A.
/// </summary>
@ -417,22 +360,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
/// <remarks>Rows must be greater or equal to columns.</remarks>
void QRSolve(T[] a, int rows, int columns, T[] b, int columnsB, T[] x, QRMethod method = QRMethod.Full);
/// <summary>
/// Solves A*X=B for X using QR factorization of A.
/// </summary>
/// <param name="a">The A matrix.</param>
/// <param name="rows">The number of rows in the A matrix.</param>
/// <param name="columns">The number of columns in the A matrix.</param>
/// <param name="b">On entry the B matrix; on exit the X matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
void QRSolve(T[] a, int rows, int columns, T[] b, int columnsB, T[] x, T[] work, QRMethod method = QRMethod.Full);
/// <summary>
/// Solves A*X=B for X using a previously QR factored matrix.
/// </summary>
@ -450,26 +377,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
void QRSolveFactored(T[] q, T[] r, int rowsA, int columnsA, T[] tau, T[] b, int columnsB, T[] x, QRMethod method = QRMethod.Full);
/// <summary>
/// Solves A*X=B for X using a previously QR factored matrix.
/// </summary>
/// <param name="q">The Q matrix obtained by QR factor. This is only used for the managed provider and can be
/// <c>null</c> for the native provider. The native provider uses the Q portion stored in the R matrix.</param>
/// <param name="r">The R matrix obtained by calling <see cref="QRFactor(T[],int,int,T[],T[])"/>. </param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="tau">Contains additional information on Q. Only used for the native solver
/// and can be <c>null</c> for the managed provider.</param>
/// <param name="b">On entry the B matrix; on exit the X matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="work">The work array - only used in the native provider. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
void QRSolveFactored(T[] q, T[] r, int rowsA, int columnsA, T[] tau, T[] b, int columnsB, T[] x, T[] work, QRMethod method = QRMethod.Full);
/// <summary>
/// Computes the singular value decomposition of A.
/// </summary>
@ -485,23 +392,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
void SingularValueDecomposition(bool computeVectors, T[] a, int rowsA, int columnsA, T[] s, T[] u, T[] vt);
/// <summary>
/// Computes the singular value decomposition of A.
/// </summary>
/// <param name="computeVectors">Compute the singular U and VT vectors or not.</param>
/// <param name="a">On entry, the M by N matrix to decompose. On exit, A may be overwritten.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="s">The singular values of A in ascending value. </param>
/// <param name="u">If <paramref name="computeVectors"/> is <c>true</c>, on exit U contains the left
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <param name="work">The work array. On exit, work[0] contains the optimal work size value.
/// </param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
void SingularValueDecomposition(bool computeVectors, T[] a, int rowsA, int columnsA, T[] s, T[] u, T[] vt, T[] work);
/// <summary>
/// Solves A*X=B for X using the singular value decomposition of A.
/// </summary>
@ -520,7 +410,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="s">The s values returned by <see cref="SingularValueDecomposition(bool,T[],int,int,T[],T[],T[])"/>.</param>
/// <param name="u">The left singular vectors returned by <see cref="SingularValueDecomposition(bool,T[],int,int, T[],T[],T[])"/>.</param>
/// <param name="vt">The right singular vectors returned by <see cref="SingularValueDecomposition(bool,T[],int,int,T[],T[],T[],T[])"/>.</param>
/// <param name="vt">The right singular vectors returned by <see cref="SingularValueDecomposition(bool,T[],int,int,T[],T[],T[])"/>.</param>
/// <param name="b">The B matrix</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>

291
src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Complex.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
// Copyright (c) 2009-2015 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -1058,35 +1058,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
inverse.Copy(a);
}
/// <summary>
/// Computes the inverse of matrix using LU factorization.
/// </summary>
/// <param name="a">The N by N matrix to invert. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is equivalent to the GETRF and GETRI LAPACK routines.</remarks>
public virtual void LUInverse(Complex[] a, int order, Complex[] work)
{
LUInverse(a, order);
}
/// <summary>
/// Computes the inverse of a previously factored matrix.
/// </summary>
/// <param name="a">The LU factored N by N matrix. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="ipiv">The pivot indices of <paramref name="a"/>.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is equivalent to the GETRI LAPACK routine.</remarks>
public virtual void LUInverseFactored(Complex[] a, int order, int[] ipiv, Complex[] work)
{
LUInverseFactored(a, order, ipiv);
}
/// <summary>
/// Solves A*X=B for X using LU factorization.
/// </summary>
@ -1469,72 +1440,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
}
var work = columnsR > rowsR ? new Complex[rowsR*rowsR] : new Complex[rowsR*columnsR];
QRFactor(r, rowsR, columnsR, q, tau, work);
}
/// <summary>
/// Computes the QR factorization of A.
/// </summary>
/// <param name="r">On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
public virtual void QRFactor(Complex[] r, int rowsR, int columnsR, Complex[] q, Complex[] tau, Complex[] work)
{
if (r == null)
{
throw new ArgumentNullException("r");
}
if (q == null)
{
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("q");
}
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r");
}
if (tau.Length < Math.Min(rowsR, columnsR))
{
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
if (q.Length != rowsR*rowsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * rowsR"), "q");
}
if (columnsR > rowsR)
{
if (work.Length < rowsR*rowsR)
{
work[0] = rowsR*rowsR;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
}
else
{
if (work.Length < rowsR*columnsR)
{
work[0] = rowsR*columnsR;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
}
CommonParallel.For(0, rowsR, (a, b) =>
{
@ -1555,8 +1460,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
{
ComputeQR(work, i, q, i, rowsR, i, rowsR, Control.MaxDegreeOfParallelism);
}
work[0] = columnsR > rowsR ? rowsR*rowsR : rowsR*columnsR;
}
/// <summary>
@ -1599,61 +1502,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
}
var work = new Complex[rowsA*columnsA];
ThinQRFactor(a, rowsA, columnsA, r, tau, work);
}
/// <summary>
/// Computes the QR factorization of A where M &gt; N.
/// </summary>
/// <param name="a">On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the Q matrix of the QR factorization.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="r">On exit, A N by N matrix that holds the R matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
public virtual void ThinQRFactor(Complex[] a, int rowsA, int columnsA, Complex[] r, Complex[] tau, Complex[] work)
{
if (r == null)
{
throw new ArgumentNullException("r");
}
if (a == null)
{
throw new ArgumentNullException("a");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (a.Length != rowsA*columnsA)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "a");
}
if (tau.Length < Math.Min(rowsA, columnsA))
{
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
if (r.Length != columnsA*columnsA)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "columnsA * columnsA"), "r");
}
if (work.Length < rowsA*columnsA)
{
work[0] = rowsA*columnsA;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
var minmn = Math.Min(rowsA, columnsA);
for (var i = 0; i < minmn; i++)
@ -1684,8 +1532,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
{
ComputeQR(work, i, a, i, rowsA, i, columnsA, Control.MaxDegreeOfParallelism);
}
work[0] = rowsA*columnsA;
}
@ -1815,26 +1661,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
public virtual void QRSolve(Complex[] a, int rows, int columns, Complex[] b, int columnsB, Complex[] x, QRMethod method = QRMethod.Full)
{
var work = new Complex[rows*columns];
QRSolve(a, rows, columns, b, columnsB, x, work, method);
}
/// <summary>
/// Solves A*X=B for X using QR factorization of A.
/// </summary>
/// <param name="a">The A matrix.</param>
/// <param name="rows">The number of rows in the A matrix.</param>
/// <param name="columns">The number of columns in the A matrix.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
public virtual void QRSolve(Complex[] a, int rows, int columns, Complex[] b, int columnsB, Complex[] x, Complex[] work, QRMethod method = QRMethod.Full)
{
if (a == null)
{
@ -1851,10 +1677,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentNullException("x");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (a.Length != rows*columns)
{
@ -1876,11 +1699,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentException(Resources.ArgumentArraysSameLength, "x");
}
if (work.Length < rows*columns)
{
work[0] = rows*columns;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
var work = new Complex[rows * columns];
var clone = new Complex[a.Length];
a.Copy(clone);
@ -1897,31 +1716,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
ThinQRFactor(clone, rows, columns, r, work);
QRSolveFactored(clone, r, rows, columns, null, b, columnsB, x, method);
}
work[0] = rows*columns;
}
/// <summary>
/// Solves A*X=B for X using a previously QR factored matrix.
/// </summary>
/// <param name="q">The Q matrix obtained by QR factor. This is only used for the managed provider and can be
/// <c>null</c> for the native provider. The native provider uses the Q portion stored in the R matrix.</param>
/// <param name="r">The R matrix obtained by calling <see cref="QRFactor(Complex[],int,int,Complex[],Complex[])"/>. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="tau">Contains additional information on Q. Only used for the native solver
/// and can be <c>null</c> for the managed provider.</param>
/// <param name="b">On entry the B matrix; on exit the X matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="work">The work array - only used in the native provider. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
public virtual void QRSolveFactored(Complex[] q, Complex[] r, int rowsR, int columnsR, Complex[] tau, Complex[] b, int columnsB, Complex[] x, Complex[] work, QRMethod method = QRMethod.Full)
{
QRSolveFactored(q, r, rowsR, columnsR, tau, b, columnsB, x, method);
}
/// <summary>
@ -2102,77 +1896,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
}
var work = new Complex[rowsA];
SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, work);
}
/// <summary>
/// Computes the singular value decomposition of A.
/// </summary>
/// <param name="computeVectors">Compute the singular U and VT vectors or not.</param>
/// <param name="a">On entry, the M by N matrix to decompose. On exit, A may be overwritten.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="s">The singular values of A in ascending value.</param>
/// <param name="u">If <paramref name="computeVectors"/> is <c>true</c>, on exit U contains the left
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <param name="work">The work array. Length should be at least <paramref name="rowsA"/>.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
/// <exception cref="NonConvergenceException"></exception>
public virtual void SingularValueDecomposition(bool computeVectors, Complex[] a, int rowsA, int columnsA, Complex[] s, Complex[] u, Complex[] vt, Complex[] work)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (s == null)
{
throw new ArgumentNullException("s");
}
if (u == null)
{
throw new ArgumentNullException("u");
}
if (vt == null)
{
throw new ArgumentNullException("vt");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (u.Length != rowsA*rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
if (vt.Length != columnsA*columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
if (s.Length != Math.Min(rowsA, columnsA))
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
if (work.Length == 0)
{
throw new ArgumentException(Resources.ArgumentSingleDimensionArray, "work");
}
if (work.Length < rowsA)
{
work[0] = rowsA;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
const int maxiter = 1000;
var e = new Complex[columnsA];
@ -2784,10 +2508,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
// a singular vector of length rows+1 when rows < columns. The last element is not used and needs to be removed.
// We should port lapack's svd routine to remove this problem.
Array.Copy(stemp, s, Math.Min(rowsA, columnsA));
// On return the first element of the work array stores the min size of the work array could have been
// work[0] = Math.Max(3 * Math.Min(aRows, aColumns) + Math.Max(aRows, aColumns), 5 * Math.Min(aRows, aColumns));
work[0] = rowsA;
}
/// <summary>
@ -2826,14 +2546,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
var work = new Complex[rowsA];
var s = new Complex[Math.Min(rowsA, columnsA)];
var u = new Complex[rowsA*rowsA];
var vt = new Complex[columnsA*columnsA];
var clone = new Complex[a.Length];
a.Copy(clone);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt, work);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt);
SvdSolveFactored(rowsA, columnsA, s, u, vt, b, columnsB, x);
}

293
src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Complex32.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
// Copyright (c) 2009-2015 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -1055,35 +1055,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
inverse.Copy(a);
}
/// <summary>
/// Computes the inverse of matrix using LU factorization.
/// </summary>
/// <param name="a">The N by N matrix to invert. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is equivalent to the GETRF and GETRI LAPACK routines.</remarks>
public virtual void LUInverse(Complex32[] a, int order, Complex32[] work)
{
LUInverse(a, order);
}
/// <summary>
/// Computes the inverse of a previously factored matrix.
/// </summary>
/// <param name="a">The LU factored N by N matrix. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="ipiv">The pivot indices of <paramref name="a"/>.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is equivalent to the GETRI LAPACK routine.</remarks>
public virtual void LUInverseFactored(Complex32[] a, int order, int[] ipiv, Complex32[] work)
{
LUInverseFactored(a, order, ipiv);
}
/// <summary>
/// Solves A*X=B for X using LU factorization.
/// </summary>
@ -1466,72 +1437,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
}
var work = columnsR > rowsR ? new Complex32[rowsR*rowsR] : new Complex32[rowsR*columnsR];
QRFactor(r, rowsR, columnsR, q, tau, work);
}
/// <summary>
/// Computes the QR factorization of A.
/// </summary>
/// <param name="r">On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
public virtual void QRFactor(Complex32[] r, int rowsR, int columnsR, Complex32[] q, Complex32[] tau, Complex32[] work)
{
if (r == null)
{
throw new ArgumentNullException("r");
}
if (q == null)
{
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("q");
}
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r");
}
if (tau.Length < Math.Min(rowsR, columnsR))
{
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
if (q.Length != rowsR*rowsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * rowsR"), "q");
}
if (columnsR > rowsR)
{
if (work.Length < rowsR*rowsR)
{
work[0] = rowsR*rowsR;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
}
else
{
if (work.Length < rowsR*columnsR)
{
work[0] = rowsR*columnsR;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
}
CommonParallel.For(0, rowsR, (a, b) =>
{
@ -1552,8 +1457,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
{
ComputeQR(work, i, q, i, rowsR, i, rowsR, Control.MaxDegreeOfParallelism);
}
work[0] = columnsR > rowsR ? rowsR*rowsR : rowsR*columnsR;
}
/// <summary>
@ -1596,62 +1499,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
}
var work = new Complex32[rowsA*columnsA];
ThinQRFactor(a, rowsA, columnsA, r, tau, work);
}
/// <summary>
/// Computes the QR factorization of A where M &gt; N.
/// </summary>
/// <param name="a">On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the Q matrix of the QR factorization.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="r">On exit, A N by N matrix that holds the R matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
public virtual void ThinQRFactor(Complex32[] a, int rowsA, int columnsA, Complex32[] r, Complex32[] tau, Complex32[] work)
{
if (r == null)
{
throw new ArgumentNullException("r");
}
if (a == null)
{
throw new ArgumentNullException("a");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (a.Length != rowsA*columnsA)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "a");
}
if (tau.Length < Math.Min(rowsA, columnsA))
{
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
if (r.Length != columnsA*columnsA)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "columnsA * columnsA"), "r");
}
if (work.Length < rowsA*columnsA)
{
work[0] = rowsA*columnsA;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
var minmn = Math.Min(rowsA, columnsA);
for (var i = 0; i < minmn; i++)
{
@ -1681,8 +1529,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
{
ComputeQR(work, i, a, i, rowsA, i, columnsA, Control.MaxDegreeOfParallelism);
}
work[0] = rowsA*columnsA;
}
@ -1812,26 +1658,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
public virtual void QRSolve(Complex32[] a, int rows, int columns, Complex32[] b, int columnsB, Complex32[] x, QRMethod method = QRMethod.Full)
{
var work = new Complex32[rows*columns];
QRSolve(a, rows, columns, b, columnsB, x, work, method);
}
/// <summary>
/// Solves A*X=B for X using QR factorization of A.
/// </summary>
/// <param name="a">The A matrix.</param>
/// <param name="rows">The number of rows in the A matrix.</param>
/// <param name="columns">The number of columns in the A matrix.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
public virtual void QRSolve(Complex32[] a, int rows, int columns, Complex32[] b, int columnsB, Complex32[] x, Complex32[] work, QRMethod method = QRMethod.Full)
{
if (a == null)
{
@ -1848,11 +1674,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentNullException("x");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (a.Length != rows*columns)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
@ -1873,11 +1694,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentException(Resources.RowsLessThanColumns);
}
if (work.Length < rows*columns)
{
work[0] = rows*columns;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
var work = new Complex32[rows * columns];
var clone = new Complex32[a.Length];
a.Copy(clone);
@ -1894,31 +1711,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
ThinQRFactor(clone, rows, columns, r, work);
QRSolveFactored(clone, r, rows, columns, null, b, columnsB, x, method);
}
work[0] = rows*columns;
}
/// <summary>
/// Solves A*X=B for X using a previously QR factored matrix.
/// </summary>
/// <param name="q">The Q matrix obtained by QR factor. This is only used for the managed provider and can be
/// <c>null</c> for the native provider. The native provider uses the Q portion stored in the R matrix.</param>
/// <param name="r">The R matrix obtained by calling <see cref="QRFactor(Complex32[],int,int,Complex32[],Complex32[])"/>. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="tau">Contains additional information on Q. Only used for the native solver
/// and can be <c>null</c> for the managed provider.</param>
/// <param name="b">On entry the B matrix; on exit the X matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="work">The work array - only used in the native provider. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
public virtual void QRSolveFactored(Complex32[] q, Complex32[] r, int rowsR, int columnsR, Complex32[] tau, Complex32[] b, int columnsB, Complex32[] x, Complex32[] work, QRMethod method = QRMethod.Full)
{
QRSolveFactored(q, r, rowsR, columnsR, tau, b, columnsB, x, method);
}
/// <summary>
@ -2099,77 +1891,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
}
var work = new Complex32[rowsA];
SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, work);
}
/// <summary>
/// Computes the singular value decomposition of A.
/// </summary>
/// <param name="computeVectors">Compute the singular U and VT vectors or not.</param>
/// <param name="a">On entry, the M by N matrix to decompose. On exit, A may be overwritten.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="s">The singular values of A in ascending value.</param>
/// <param name="u">If <paramref name="computeVectors"/> is <c>true</c>, on exit U contains the left
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <param name="work">The work array. Length should be at least <paramref name="rowsA"/>.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
/// <exception cref="NonConvergenceException"></exception>
public virtual void SingularValueDecomposition(bool computeVectors, Complex32[] a, int rowsA, int columnsA, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] work)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (s == null)
{
throw new ArgumentNullException("s");
}
if (u == null)
{
throw new ArgumentNullException("u");
}
if (vt == null)
{
throw new ArgumentNullException("vt");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (u.Length != rowsA*rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
if (vt.Length != columnsA*columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
if (s.Length != Math.Min(rowsA, columnsA))
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
if (work.Length == 0)
{
throw new ArgumentException(Resources.ArgumentSingleDimensionArray, "work");
}
if (work.Length < rowsA)
{
work[0] = rowsA;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
const int maxiter = 1000;
var e = new Complex32[columnsA];
@ -2781,10 +2503,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
// a singular vector of length rows+1 when rows < columns. The last element is not used and needs to be removed.
// We should port lapack's svd routine to remove this problem.
Array.Copy(stemp, s, Math.Min(rowsA, columnsA));
// On return the first element of the work array stores the min size of the work array could have been
// work[0] = Math.Max(3 * Math.Min(aRows, aColumns) + Math.Max(aRows, aColumns), 5 * Math.Min(aRows, aColumns));
work[0] = rowsA;
}
/// <summary>
@ -2823,14 +2541,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
var work = new Complex32[rowsA];
var s = new Complex32[Math.Min(rowsA, columnsA)];
var u = new Complex32[rowsA*rowsA];
var vt = new Complex32[columnsA*columnsA];
var clone = new Complex32[a.Length];
a.Copy(clone);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt, work);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt);
SvdSolveFactored(rowsA, columnsA, s, u, vt, b, columnsB, x);
}

298
src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Double.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
// Copyright (c) 2009-2015 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -941,35 +941,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
inverse.Copy(a);
}
/// <summary>
/// Computes the inverse of matrix using LU factorization.
/// </summary>
/// <param name="a">The N by N matrix to invert. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is equivalent to the GETRF and GETRI LAPACK routines.</remarks>
public virtual void LUInverse(double[] a, int order, double[] work)
{
LUInverse(a, order);
}
/// <summary>
/// Computes the inverse of a previously factored matrix.
/// </summary>
/// <param name="a">The LU factored N by N matrix. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="ipiv">The pivot indices of <paramref name="a"/>.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is equivalent to the GETRI LAPACK routine.</remarks>
public virtual void LUInverseFactored(double[] a, int order, int[] ipiv, double[] work)
{
LUInverseFactored(a, order, ipiv);
}
/// <summary>
/// Solves A*X=B for X using LU factorization.
/// </summary>
@ -1351,83 +1322,15 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * rowsR"), "q");
}
var work = columnsR > rowsR ? new double[rowsR*rowsR] : new double[rowsR*columnsR];
QRFactor(r, rowsR, columnsR, q, tau, work);
}
/// <summary>
/// Computes the QR factorization of A.
/// </summary>
/// <param name="r">On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
public virtual void QRFactor(double[] r, int rowsR, int columnsR, double[] q, double[] tau, double[] work)
{
if (r == null)
{
throw new ArgumentNullException("r");
}
if (q == null)
{
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("q");
}
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r");
}
if (tau.Length < Math.Min(rowsR, columnsR))
{
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
if (q.Length != rowsR*rowsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * rowsR"), "q");
}
if (columnsR > rowsR)
{
if (work.Length < rowsR*rowsR)
{
work[0] = rowsR*rowsR;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
}
else
{
if (work.Length < rowsR*columnsR)
{
work[0] = rowsR*columnsR;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
}
CommonParallel.For(0, rowsR, (a, b) =>
{
for (int i = a; i < b; i++)
for (var i = a; i < b; i++)
{
q[(i*rowsR) + i] = 1.0;
}
});
var work = columnsR > rowsR ? new double[rowsR * rowsR] : new double[rowsR * columnsR];
var minmn = Math.Min(rowsR, columnsR);
for (var i = 0; i < minmn; i++)
{
@ -1439,8 +1342,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
{
ComputeQR(work, i, q, i, rowsR, i, rowsR, Control.MaxDegreeOfParallelism);
}
work[0] = columnsR > rowsR ? rowsR*rowsR : rowsR*columnsR;
}
/// <summary>
@ -1483,62 +1384,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
}
var work = new double[rowsA*columnsA];
ThinQRFactor(a, rowsA, columnsA, r, tau, work);
}
/// <summary>
/// Computes the thin QR factorization of A where M &gt; N.
/// </summary>
/// <param name="a">On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the Q matrix of the QR factorization.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="r">On exit, A N by N matrix that holds the R matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
public virtual void ThinQRFactor(double[] a, int rowsA, int columnsA, double[] r, double[] tau, double[] work)
{
if (r == null)
{
throw new ArgumentNullException("r");
}
if (a == null)
{
throw new ArgumentNullException("a");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (a.Length != rowsA*columnsA)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "a");
}
if (tau.Length < Math.Min(rowsA, columnsA))
{
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
if (r.Length != columnsA*columnsA)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "columnsA * columnsA"), "r");
}
if (work.Length < rowsA*columnsA)
{
work[0] = rowsA*columnsA;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
var minmn = Math.Min(rowsA, columnsA);
for (var i = 0; i < minmn; i++)
{
@ -1568,8 +1414,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
{
ComputeQR(work, i, a, i, rowsA, i, columnsA, Control.MaxDegreeOfParallelism);
}
work[0] = rowsA*columnsA;
}
#region QR Factor Helper functions
@ -1699,26 +1543,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
public virtual void QRSolve(double[] a, int rows, int columns, double[] b, int columnsB, double[] x, QRMethod method = QRMethod.Full)
{
var work = new double[rows*columns];
QRSolve(a, rows, columns, b, columnsB, x, work, method);
}
/// <summary>
/// Solves A*X=B for X using QR factorization of A.
/// </summary>
/// <param name="a">The A matrix.</param>
/// <param name="rows">The number of rows in the A matrix.</param>
/// <param name="columns">The number of columns in the A matrix.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
public virtual void QRSolve(double[] a, int rows, int columns, double[] b, int columnsB, double[] x, double[] work, QRMethod method = QRMethod.Full)
{
if (a == null)
{
@ -1735,11 +1559,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentNullException("x");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (a.Length != rows*columns)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
@ -1760,11 +1579,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentException(Resources.RowsLessThanColumns);
}
if (work.Length < rows*columns)
{
work[0] = rows*columns;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
var work = new double[rows * columns];
var clone = new double[a.Length];
a.Copy(clone);
@ -1781,31 +1596,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
ThinQRFactor(clone, rows, columns, r, work);
QRSolveFactored(clone, r, rows, columns, null, b, columnsB, x, method);
}
work[0] = rows*columns;
}
/// <summary>
/// Solves A*X=B for X using a previously QR factored matrix.
/// </summary>
/// <param name="q">The Q matrix obtained by QR factor. This is only used for the managed provider and can be
/// <c>null</c> for the native provider. The native provider uses the Q portion stored in the R matrix.</param>
/// <param name="r">The R matrix obtained by calling <see cref="QRFactor(double[],int,int,double[],double[])"/>. </param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="tau">Contains additional information on Q. Only used for the native solver
/// and can be <c>null</c> for the managed provider.</param>
/// <param name="b">On entry the B matrix; on exit the X matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="work">The work array - only used in the native provider. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
public virtual void QRSolveFactored(double[] q, double[] r, int rowsA, int columnsA, double[] tau, double[] b, int columnsB, double[] x, double[] work, QRMethod method = QRMethod.Full)
{
QRSolveFactored(q, r, rowsA, columnsA, tau, b, columnsB, x, method);
}
/// <summary>
@ -1986,76 +1776,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
}
var work = new double[rowsA];
SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, work);
}
/// <summary>
/// Computes the singular value decomposition of A.
/// </summary>
/// <param name="computeVectors">Compute the singular U and VT vectors or not.</param>
/// <param name="a">On entry, the M by N matrix to decompose. On exit, A may be overwritten.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="s">The singular values of A in ascending value.</param>
/// <param name="u">If <paramref name="computeVectors"/> is <c>true</c>, on exit U contains the left
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <param name="work">The work array. Length should be at least <paramref name="rowsA"/>.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
/// <exception cref="NonConvergenceException"></exception>
public virtual void SingularValueDecomposition(bool computeVectors, double[] a, int rowsA, int columnsA, double[] s, double[] u, double[] vt, double[] work)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (s == null)
{
throw new ArgumentNullException("s");
}
if (u == null)
{
throw new ArgumentNullException("u");
}
if (vt == null)
{
throw new ArgumentNullException("vt");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (u.Length != rowsA*rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
if (vt.Length != columnsA*columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
if (s.Length != Math.Min(rowsA, columnsA))
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
if (work.Length == 0)
{
throw new ArgumentException(Resources.ArgumentSingleDimensionArray, "work");
}
if (work.Length < rowsA)
{
work[0] = rowsA;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
const int maxiter = 1000;
@ -2672,10 +2392,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
// a singular vector of length rows+1 when rows < columns. The last element is not used and needs to be removed.
// We should port lapack's svd routine to remove this problem.
Buffer.BlockCopy(stemp, 0, s, 0, Math.Min(rowsA, columnsA)*Constants.SizeOfDouble);
// On return the first element of the work array stores the min size of the work array could have been
// work[0] = Math.Max(3 * Math.Min(aRows, aColumns) + Math.Max(aRows, aColumns), 5 * Math.Min(aRows, aColumns));
work[0] = rowsA;
}
/// <summary>
@ -2770,15 +2486,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
var work = new double[rowsA];
var s = new double[Math.Min(rowsA, columnsA)];
var u = new double[rowsA*rowsA];
var vt = new double[columnsA*columnsA];
var clone = new double[a.Length];
Buffer.BlockCopy(a, 0, clone, 0, a.Length*Constants.SizeOfDouble);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt, work);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt);
SvdSolveFactored(rowsA, columnsA, s, u, vt, b, columnsB, x);
}

291
src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Single.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
// Copyright (c) 2009-2015 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -941,35 +941,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
inverse.Copy(a);
}
/// <summary>
/// Computes the inverse of matrix using LU factorization.
/// </summary>
/// <param name="a">The N by N matrix to invert. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is equivalent to the GETRF and GETRI LAPACK routines.</remarks>
public virtual void LUInverse(float[] a, int order, float[] work)
{
LUInverse(a, order);
}
/// <summary>
/// Computes the inverse of a previously factored matrix.
/// </summary>
/// <param name="a">The LU factored N by N matrix. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="ipiv">The pivot indices of <paramref name="a"/>.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is equivalent to the GETRI LAPACK routine.</remarks>
public virtual void LUInverseFactored(float[] a, int order, int[] ipiv, float[] work)
{
LUInverseFactored(a, order, ipiv);
}
/// <summary>
/// Solves A*X=B for X using LU factorization.
/// </summary>
@ -1352,72 +1323,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
}
var work = columnsR > rowsR ? new float[rowsR*rowsR] : new float[rowsR*columnsR];
QRFactor(r, rowsR, columnsR, q, tau, work);
}
/// <summary>
/// Computes the QR factorization of A.
/// </summary>
/// <param name="r">On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
public virtual void QRFactor(float[] r, int rowsR, int columnsR, float[] q, float[] tau, float[] work)
{
if (r == null)
{
throw new ArgumentNullException("r");
}
if (q == null)
{
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("q");
}
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r");
}
if (tau.Length < Math.Min(rowsR, columnsR))
{
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
if (q.Length != rowsR*rowsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * rowsR"), "q");
}
if (columnsR > rowsR)
{
if (work.Length < rowsR*rowsR)
{
work[0] = rowsR*rowsR;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
}
else
{
if (work.Length < rowsR*columnsR)
{
work[0] = rowsR*columnsR;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
}
CommonParallel.For(0, rowsR, (a, b) =>
{
@ -1438,8 +1343,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
{
ComputeQR(work, i, q, i, rowsR, i, rowsR, Control.MaxDegreeOfParallelism);
}
work[0] = columnsR > rowsR ? rowsR*rowsR : rowsR*columnsR;
}
/// <summary>
@ -1482,61 +1385,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
}
var work = new float[rowsA*columnsA];
ThinQRFactor(a, rowsA, columnsA, r, tau, work);
}
/// <summary>
/// Computes the QR factorization of A where M &gt; N.
/// </summary>
/// <param name="a">On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the Q matrix of the QR factorization.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="r">On exit, A N by N matrix that holds the R matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
public virtual void ThinQRFactor(float[] a, int rowsA, int columnsA, float[] r, float[] tau, float[] work)
{
if (r == null)
{
throw new ArgumentNullException("r");
}
if (a == null)
{
throw new ArgumentNullException("a");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (a.Length != rowsA*columnsA)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "a");
}
if (tau.Length < Math.Min(rowsA, columnsA))
{
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
if (r.Length != columnsA*columnsA)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "columnsA * columnsA"), "r");
}
if (work.Length < rowsA*columnsA)
{
work[0] = rowsA*columnsA;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
var minmn = Math.Min(rowsA, columnsA);
for (var i = 0; i < minmn; i++)
@ -1567,8 +1415,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
{
ComputeQR(work, i, a, i, rowsA, i, columnsA, Control.MaxDegreeOfParallelism);
}
work[0] = rowsA*columnsA;
}
@ -1687,22 +1533,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
#endregion
/// <summary>
/// Solves A*X=B for X using QR factorization of A.
/// </summary>
/// <param name="a">The A matrix.</param>
/// <param name="rows">The number of rows in the A matrix.</param>
/// <param name="columns">The number of columns in the A matrix.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
public virtual void QRSolve(float[] a, int rows, int columns, float[] b, int columnsB, float[] x, QRMethod method = QRMethod.Full)
{
var work = new float[rows*columns];
QRSolve(a, rows, columns, b, columnsB, x, work, method);
}
/// <summary>
/// Solves A*X=B for X using QR factorization of A.
@ -1713,12 +1543,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
public virtual void QRSolve(float[] a, int rows, int columns, float[] b, int columnsB, float[] x, float[] work, QRMethod method = QRMethod.Full)
public virtual void QRSolve(float[] a, int rows, int columns, float[] b, int columnsB, float[] x, QRMethod method = QRMethod.Full)
{
if (a == null)
{
@ -1735,11 +1562,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentNullException("x");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (a.Length != rows*columns)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
@ -1760,11 +1582,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentException(Resources.RowsLessThanColumns);
}
if (work.Length < rows*columns)
{
work[0] = rows*columns;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
var work = new float[rows * columns];
var clone = new float[a.Length];
a.Copy(clone);
@ -1781,31 +1599,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
ThinQRFactor(clone, rows, columns, r, work);
QRSolveFactored(clone, r, rows, columns, null, b, columnsB, x, method);
}
work[0] = rows*columns;
}
/// <summary>
/// Solves A*X=B for X using a previously QR factored matrix.
/// </summary>
/// <param name="q">The Q matrix obtained by QR factor. This is only used for the managed provider and can be
/// <c>null</c> for the native provider. The native provider uses the Q portion stored in the R matrix.</param>
/// <param name="r">The R matrix obtained by calling <see cref="QRFactor(float[],int,int,float[],float[])"/>. </param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="tau">Contains additional information on Q. Only used for the native solver
/// and can be <c>null</c> for the managed provider.</param>
/// <param name="b">On entry the B matrix; on exit the X matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="work">The work array - only used in the native provider. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
public virtual void QRSolveFactored(float[] q, float[] r, int rowsA, int columnsA, float[] tau, float[] b, int columnsB, float[] x, float[] work, QRMethod method = QRMethod.Full)
{
QRSolveFactored(q, r, rowsA, columnsA, tau, b, columnsB, x, method);
}
/// <summary>
@ -1986,76 +1779,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
}
var work = new float[rowsA];
SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, work);
}
/// <summary>
/// Computes the singular value decomposition of A.
/// </summary>
/// <param name="computeVectors">Compute the singular U and VT vectors or not.</param>
/// <param name="a">On entry, the M by N matrix to decompose. On exit, A may be overwritten.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="s">The singular values of A in ascending value.</param>
/// <param name="u">If <paramref name="computeVectors"/> is <c>true</c>, on exit U contains the left
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <param name="work">The work array. Length should be at least <paramref name="rowsA"/>.</param>
/// <exception cref="NonConvergenceException"></exception>
public virtual void SingularValueDecomposition(bool computeVectors, float[] a, int rowsA, int columnsA, float[] s, float[] u, float[] vt, float[] work)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (s == null)
{
throw new ArgumentNullException("s");
}
if (u == null)
{
throw new ArgumentNullException("u");
}
if (vt == null)
{
throw new ArgumentNullException("vt");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (u.Length != rowsA*rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
if (vt.Length != columnsA*columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
if (s.Length != Math.Min(rowsA, columnsA))
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
if (work.Length == 0)
{
throw new ArgumentException(Resources.ArgumentSingleDimensionArray, "work");
}
if (work.Length < rowsA)
{
work[0] = rowsA;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
const int maxiter = 1000;
var e = new float[columnsA];
@ -2673,10 +2397,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
// a singular vector of length rows+1 when rows < columns. The last element is not used and needs to be removed.
// We should port lapack's svd routine to remove this problem.
Buffer.BlockCopy(stemp, 0, s, 0, Math.Min(rowsA, columnsA)*Constants.SizeOfFloat);
// On return the first element of the work array stores the min size of the work array could have been
// work[0] = Math.Max(3 * Math.Min(aRows, aColumns) + Math.Max(aRows, aColumns), 5 * Math.Min(aRows, aColumns));
work[0] = rowsA;
}
/// <summary>
@ -2772,14 +2492,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
var work = new float[rowsA];
var s = new float[Math.Min(rowsA, columnsA)];
var u = new float[rowsA*rowsA];
var vt = new float[columnsA*columnsA];
var clone = new float[a.Length];
Buffer.BlockCopy(a, 0, clone, 0, a.Length*Constants.SizeOfFloat);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt, work);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt);
SvdSolveFactored(rowsA, columnsA, s, u, vt, b, columnsB, x);
}

477
src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Complex.cs

@ -76,8 +76,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, rows * columns), "matrix");
}
var work = new double[rows];
return SafeNativeMethods.z_matrix_norm((byte)norm, rows, columns, matrix, work);
return SafeNativeMethods.z_matrix_norm((byte)norm, rows, columns, matrix);
}
/// <summary>
@ -274,7 +273,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
SafeNativeMethods.z_lu_factor(order, data, ipiv);
var info = SafeNativeMethods.z_lu_factor(order, data, ipiv);
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -296,77 +300,22 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
var work = new Complex[order];
SafeNativeMethods.z_lu_inverse(order, a, work, work.Length);
}
var info = SafeNativeMethods.z_lu_inverse(order, a);
/// <summary>
/// Computes the inverse of a previously factored matrix.
/// </summary>
/// <param name="a">The LU factored N by N matrix. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="ipiv">The pivot indices of <paramref name="a"/>.</param>
/// <remarks>This is equivalent to the GETRI LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void LUInverseFactored(Complex[] a, int order, int[] ipiv)
{
if (a == null)
if (info == (int)MklError.MemoryAllocation)
{
throw new ArgumentNullException("a");
throw new MemoryAllocationException();
}
if (ipiv == null)
if (info < 0)
{
throw new ArgumentNullException("ipiv");
throw new InvalidParameterException(Math.Abs(info));
}
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
if (ipiv.Length != order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
var work = new Complex[order];
SafeNativeMethods.z_lu_inverse_factored(order, a, ipiv, work, order);
}
/// <summary>
/// Computes the inverse of matrix using LU factorization.
/// </summary>
/// <param name="a">The N by N matrix to invert. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is equivalent to the GETRF and GETRI LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void LUInverse(Complex[] a, int order, Complex[] work)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (work.Length < order)
if (info > 0)
{
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new SingularUMatrixException(info);
}
SafeNativeMethods.z_lu_inverse(order, a, work, work.Length);
}
/// <summary>
@ -375,12 +324,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
/// <param name="a">The LU factored N by N matrix. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="ipiv">The pivot indices of <paramref name="a"/>.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is equivalent to the GETRI LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void LUInverseFactored(Complex[] a, int order, int[] ipiv, Complex[] work)
public override void LUInverseFactored(Complex[] a, int order, int[] ipiv)
{
if (a == null)
{
@ -402,17 +348,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
var info = SafeNativeMethods.z_lu_inverse_factored(order, a, ipiv);
if (work.Length < order)
if (info < 0)
{
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
SafeNativeMethods.z_lu_inverse_factored(order, a, ipiv, work, order);
if (info > 0)
{
throw new SingularUMatrixException(info);
}
}
/// <summary>
@ -446,7 +392,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.z_lu_solve(order, columnsOfB, a, b);
var info = SafeNativeMethods.z_lu_solve(order, columnsOfB, a, b);
if (info == (int)MklError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -491,7 +447,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.z_lu_solve_factored(order, columnsOfB, a, ipiv, b);
var info = SafeNativeMethods.z_lu_solve_factored(order, columnsOfB, a, ipiv, b);
if (info == (int)MklError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -521,6 +487,11 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
var info = SafeNativeMethods.z_cholesky_factor(order, a);
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
if (info > 0)
{
throw new ArgumentException(Resources.ArgumentMatrixPositiveDefinite);
@ -559,7 +530,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.z_cholesky_solve(orderA, columnsB, a, b);
var info = SafeNativeMethods.z_cholesky_solve(orderA, columnsB, a, b);
if (info == (int)MklError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -593,51 +574,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.z_cholesky_solve_factored(orderA, columnsB, a, b);
}
/// <summary>
/// Computes the QR factorization of A.
/// </summary>
/// <param name="r">On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void QRFactor(Complex[] r, int rowsR, int columnsR, Complex[] q, Complex[] tau)
{
if (r == null)
{
throw new ArgumentNullException("r");
}
if (q == null)
{
throw new ArgumentNullException("q");
}
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r");
}
if (tau.Length < Math.Min(rowsR, columnsR))
{
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
var info = SafeNativeMethods.z_cholesky_solve_factored(orderA, columnsB, a, b);
if (q.Length != rowsR*rowsR)
if (info < 0)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * rowsR"), "q");
throw new InvalidParameterException(Math.Abs(info));
}
var work = new Complex[columnsR*Control.BlockSize];
SafeNativeMethods.z_qr_factor(rowsR, columnsR, r, tau, q, work, work.Length);
}
/// <summary>
@ -647,16 +589,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
/// it is overwritten with the R matrix of the QR factorization. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void QRFactor(Complex[] r, int rowsR, int columnsR, Complex[] q, Complex[] tau, Complex[] work)
public override void QRFactor(Complex[] r, int rowsR, int columnsR, Complex[] q, Complex[] tau)
{
if (r == null)
{
@ -668,11 +607,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r");
@ -688,13 +622,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * rowsR"), "q");
}
if (work.Length < columnsR*Control.BlockSize)
var info = SafeNativeMethods.z_qr_factor(rowsR, columnsR, r, tau, q);
if (info < 0)
{
work[0] = columnsR*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
SafeNativeMethods.z_qr_factor(rowsR, columnsR, r, tau, q, work, work.Length);
}
/// <summary>
@ -737,66 +670,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "columnsA * columnsA"), "r");
}
var work = new Complex[columnsA * Control.BlockSize];
SafeNativeMethods.z_qr_thin_factor(rowsA, columnsA, q, tau, r, work, work.Length);
}
var info = SafeNativeMethods.z_qr_thin_factor(rowsA, columnsA, q, tau, r);
/// <summary>
/// Computes the thin QR factorization of A where M &gt; N.
/// </summary>
/// <param name="q">On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the Q matrix of the QR factorization.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="r">On exit, A N by N matrix that holds the R matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void ThinQRFactor(Complex[] q, int rowsA, int columnsA, Complex[] r, Complex[] tau, Complex[] work)
{
if (r == null)
if (info < 0)
{
throw new ArgumentNullException("r");
throw new InvalidParameterException(Math.Abs(info));
}
if (q == null)
{
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("q");
}
if (q.Length != rowsA*columnsA)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "q");
}
if (tau.Length < Math.Min(rowsA, columnsA))
{
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
if (r.Length != columnsA*columnsA)
{
throw new ArgumentException(
string.Format(Resources.ArgumentArrayWrongLength, "columnsA * columnsA"), "r");
}
if (work.Length < columnsA*Control.BlockSize)
{
work[0] = columnsA*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
SafeNativeMethods.z_qr_thin_factor(rowsA, columnsA, q, tau, r, work, work.Length);
}
/// <summary>
@ -812,27 +691,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolve(Complex[] a, int rows, int columns, Complex[] b, int columnsB, Complex[] x, QRMethod method = QRMethod.Full)
{
var work = new Complex[columns*Control.BlockSize];
QRSolve(a, rows, columns, b, columnsB, x, work, method);
}
/// <summary>
/// Solves A*X=B for X using QR factorization of A.
/// </summary>
/// <param name="a">The A matrix.</param>
/// <param name="rows">The number of rows in the A matrix.</param>
/// <param name="columns">The number of columns in the A matrix.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolve(Complex[] a, int rows, int columns, Complex[] b, int columnsB, Complex[] x, Complex[] work, QRMethod method = QRMethod.Full)
{
if (a == null)
{
@ -849,22 +707,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentNullException("x");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (a.Length != rows*columns)
if (a.Length != rows * columns)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
if (b.Length != rows*columnsB)
if (b.Length != rows * columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
if (x.Length != columns*columnsB)
if (x.Length != columns * columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "x");
}
@ -874,56 +727,40 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.RowsLessThanColumns);
}
if (work.Length < 1)
var info = SafeNativeMethods.z_qr_solve(rows, columns, columnsB, a, b, x);
if (info == (int)MklError.MemoryAllocation)
{
work[0] = rows*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new MemoryAllocationException();
}
SafeNativeMethods.z_qr_solve(rows, columns, columnsB, a, b, x, work, work.Length);
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
/// <summary>
/// Solves A*X=B for X using a previously QR factored matrix.
/// </summary>
/// <param name="q">The Q matrix obtained by calling <see cref="QRFactor(Complex[],int,int,Complex[],Complex[])"/>.</param>
/// <param name="r">The R matrix obtained by calling <see cref="QRFactor(Complex[],int,int,Complex[],Complex[])"/>. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="tau">Contains additional information on Q. Only used for the native solver
/// and can be <c>null</c> for the managed provider.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolveFactored(Complex[] q, Complex[] r, int rowsR, int columnsR, Complex[] tau, Complex[] b, int columnsB, Complex[] x, QRMethod method = QRMethod.Full)
{
var work = new Complex[columnsR*Control.BlockSize];
QRSolveFactored(q, r, rowsR, columnsR, tau, b, columnsB, x, work, method);
if (info > 0)
{
throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient, "a");
}
}
/// <summary>
/// Solves A*X=B for X using a previously QR factored matrix.
/// </summary>
/// <param name="q">The Q matrix obtained by QR factor. This is only used for the managed provider and can be
/// <c>null</c> for the native provider. The native provider uses the Q portion stored in the R matrix.</param>
/// <param name="q">The Q matrix obtained by calling <see cref="QRFactor(Complex[],int,int,Complex[],Complex[])"/>.</param>
/// <param name="r">The R matrix obtained by calling <see cref="QRFactor(Complex[],int,int,Complex[],Complex[])"/>. </param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="tau">Contains additional information on Q. Only used for the native solver
/// and can be <c>null</c> for the managed provider.</param>
/// <param name="b">On entry the B matrix; on exit the X matrix.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="work">The work array - only used in the native provider. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolveFactored(Complex[] q, Complex[] r, int rowsA, int columnsA, Complex[] tau, Complex[] b, int columnsB, Complex[] x, Complex[] work, QRMethod method = QRMethod.Full)
public override void QRSolveFactored(Complex[] q, Complex[] r, int rowsA, int columnsA, Complex[] tau, Complex[] b, int columnsB, Complex[] x, QRMethod method = QRMethod.Full)
{
if (r == null)
{
@ -945,11 +782,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
int rowsQ, columnsQ, rowsR, columnsR;
if (method == QRMethod.Full)
{
@ -962,35 +794,39 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
columnsQ = rowsR = columnsR = columnsA;
}
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR*columnsR), "r");
}
if (q.Length != rowsQ*columnsQ)
if (r.Length != rowsR * columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ*columnsQ), "q");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR * columnsR), "r");
}
if (b.Length != rowsA*columnsB)
if (q.Length != rowsQ * columnsQ)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA*columnsB), "b");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ * columnsQ), "q");
}
if (x.Length != columnsA*columnsB)
if (b.Length != rowsA * columnsB)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA*columnsB), "x");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA * columnsB), "b");
}
if (work.Length < 1)
if (x.Length != columnsA * columnsB)
{
work[0] = rowsA*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA * columnsB), "x");
}
if (method == QRMethod.Full)
{
SafeNativeMethods.z_qr_solve_factored(rowsA, columnsA, columnsB, r, b, tau, x, work, work.Length);
var info = SafeNativeMethods.z_qr_solve_factored(rowsA, columnsA, columnsB, r, b, tau, x);
if (info == (int)MklError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
else
{
@ -1000,61 +836,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
}
}
/// <summary>
/// Computes the singular value decomposition of A.
/// </summary>
/// <param name="computeVectors">Compute the singular U and VT vectors or not.</param>
/// <param name="a">On entry, the M by N matrix to decompose. On exit, A may be overwritten.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="s">The singular values of A in ascending value.</param>
/// <param name="u">If <paramref name="computeVectors"/> is <c>true</c>, on exit U contains the left
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void SingularValueDecomposition(bool computeVectors, Complex[] a, int rowsA, int columnsA, Complex[] s, Complex[] u, Complex[] vt)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (s == null)
{
throw new ArgumentNullException("s");
}
if (u == null)
{
throw new ArgumentNullException("u");
}
if (vt == null)
{
throw new ArgumentNullException("vt");
}
if (u.Length != rowsA*rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
if (vt.Length != columnsA*columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
if (s.Length != Math.Min(rowsA, columnsA))
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
var work = new Complex[(2*Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA)];
SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, work);
}
/// <summary>
/// Solves A*X=B for X using the singular value decomposition of A.
/// </summary>
@ -1091,14 +872,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
var work = new Complex[(2*Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA)];
var s = new Complex[Math.Min(rowsA, columnsA)];
var u = new Complex[rowsA*rowsA];
var vt = new Complex[columnsA*columnsA];
var clone = new Complex[a.Length];
a.Copy(clone);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt, work);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt);
SvdSolveFactored(rowsA, columnsA, s, u, vt, b, columnsB, x);
}
@ -1114,12 +894,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <param name="work">The work array. For real matrices, the work array should be at least
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void SingularValueDecomposition(bool computeVectors, Complex[] a, int rowsA, int columnsA, Complex[] s, Complex[] u, Complex[] vt, Complex[] work)
public override void SingularValueDecomposition(bool computeVectors, Complex[] a, int rowsA, int columnsA, Complex[] s, Complex[] u, Complex[] vt)
{
if (a == null)
{
@ -1141,11 +918,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentNullException("vt");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (u.Length != rowsA*rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
@ -1161,18 +933,19 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
if (work.Length == 0)
var info = SafeNativeMethods.z_svd_factor(computeVectors, rowsA, columnsA, a, s, u, vt);
if (info == (int) MklError.MemoryAllocation)
{
throw new ArgumentException(Resources.ArgumentSingleDimensionArray, "work");
throw new MemoryAllocationException();
}
if (work.Length < (2*Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA))
if (info < 0)
{
work[0] = (2*Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA);
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
if (SafeNativeMethods.z_svd_factor(computeVectors, rowsA, columnsA, a, s, u, vt, work, work.Length) > 0)
if (info > 0)
{
throw new NonConvergenceException();
}
@ -1369,7 +1142,19 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order * order), "matrixD");
}
if (SafeNativeMethods.z_eigen(isSymmetric, order, matrix, matrixEv, vectorEv, matrixD) > 0)
var info = SafeNativeMethods.z_eigen(isSymmetric, order, matrix, matrixEv, vectorEv, matrixD);
if (info == (int)MklError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
if (info > 0)
{
throw new NonConvergenceException();
}

478
src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Complex32.cs

@ -76,8 +76,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, rows * columns), "matrix");
}
var work = new float[rows];
return SafeNativeMethods.c_matrix_norm((byte)norm, rows, columns, matrix, work);
return SafeNativeMethods.c_matrix_norm((byte)norm, rows, columns, matrix);
}
/// <summary>
@ -274,7 +273,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
SafeNativeMethods.c_lu_factor(order, data, ipiv);
var info = SafeNativeMethods.c_lu_factor(order, data, ipiv);
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -296,77 +300,22 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
var work = new Complex32[order];
SafeNativeMethods.c_lu_inverse(order, a, work, work.Length);
}
/// <summary>
/// Computes the inverse of a previously factored matrix.
/// </summary>
/// <param name="a">The LU factored N by N matrix. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="ipiv">The pivot indices of <paramref name="a"/>.</param>
/// <remarks>This is equivalent to the GETRI LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void LUInverseFactored(Complex32[] a, int order, int[] ipiv)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (ipiv == null)
{
throw new ArgumentNullException("ipiv");
}
var info = SafeNativeMethods.c_lu_inverse(order, a);
if (a.Length != order*order)
if (info == (int)MklError.MemoryAllocation)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
throw new MemoryAllocationException();
}
if (ipiv.Length != order)
if (info < 0)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
throw new InvalidParameterException(Math.Abs(info));
}
var work = new Complex32[order];
SafeNativeMethods.c_lu_inverse_factored(order, a, ipiv, work, order);
}
/// <summary>
/// Computes the inverse of matrix using LU factorization.
/// </summary>
/// <param name="a">The N by N matrix to invert. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is equivalent to the GETRF and GETRI LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void LUInverse(Complex32[] a, int order, Complex32[] work)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (work.Length < order)
if (info > 0)
{
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new SingularUMatrixException(info);
}
SafeNativeMethods.c_lu_inverse(order, a, work, work.Length);
}
/// <summary>
@ -375,12 +324,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
/// <param name="a">The LU factored N by N matrix. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="ipiv">The pivot indices of <paramref name="a"/>.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is equivalent to the GETRI LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void LUInverseFactored(Complex32[] a, int order, int[] ipiv, Complex32[] work)
public override void LUInverseFactored(Complex32[] a, int order, int[] ipiv)
{
if (a == null)
{
@ -402,17 +348,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
var info = SafeNativeMethods.c_lu_inverse_factored(order, a, ipiv);
if (work.Length < order)
if (info < 0)
{
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
SafeNativeMethods.c_lu_inverse_factored(order, a, ipiv, work, order);
if (info > 0)
{
throw new SingularUMatrixException(info);
}
}
/// <summary>
@ -446,7 +392,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.c_lu_solve(order, columnsOfB, a, b);
var info = SafeNativeMethods.c_lu_solve(order, columnsOfB, a, b);
if (info == (int)MklError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -491,7 +447,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.c_lu_solve_factored(order, columnsOfB, a, ipiv, b);
var info = SafeNativeMethods.c_lu_solve_factored(order, columnsOfB, a, ipiv, b);
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -521,6 +482,11 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
var info = SafeNativeMethods.c_cholesky_factor(order, a);
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
if (info > 0)
{
throw new ArgumentException(Resources.ArgumentMatrixPositiveDefinite);
@ -559,7 +525,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.c_cholesky_solve(orderA, columnsB, a, b);
var info = SafeNativeMethods.c_cholesky_solve(orderA, columnsB, a, b);
if (info == (int)MklError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -593,51 +569,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.c_cholesky_solve_factored(orderA, columnsB, a, b);
}
/// <summary>
/// Computes the QR factorization of A.
/// </summary>
/// <param name="r">On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void QRFactor(Complex32[] r, int rowsR, int columnsR, Complex32[] q, Complex32[] tau)
{
if (r == null)
{
throw new ArgumentNullException("r");
}
if (q == null)
{
throw new ArgumentNullException("q");
}
var info = SafeNativeMethods.c_cholesky_solve_factored(orderA, columnsB, a, b);
if (r.Length != rowsR*columnsR)
if (info < 0)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r");
throw new InvalidParameterException(Math.Abs(info));
}
if (tau.Length < Math.Min(rowsR, columnsR))
{
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
if (q.Length != rowsR*rowsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * rowsR"), "q");
}
var work = new Complex32[columnsR*Control.BlockSize];
SafeNativeMethods.c_qr_factor(rowsR, columnsR, r, tau, q, work, work.Length);
}
/// <summary>
@ -647,16 +584,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
/// it is overwritten with the R matrix of the QR factorization. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void QRFactor(Complex32[] r, int rowsR, int columnsR, Complex32[] q, Complex32[] tau, Complex32[] work)
public override void QRFactor(Complex32[] r, int rowsR, int columnsR, Complex32[] q, Complex32[] tau)
{
if (r == null)
{
@ -668,11 +602,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r");
@ -688,13 +617,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * rowsR"), "q");
}
if (work.Length < columnsR*Control.BlockSize)
var info = SafeNativeMethods.c_qr_factor(rowsR, columnsR, r, tau, q);
if (info < 0)
{
work[0] = columnsR*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
SafeNativeMethods.c_qr_factor(rowsR, columnsR, r, tau, q, work, work.Length);
}
/// <summary>
@ -737,66 +665,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "columnsA * columnsA"), "r");
}
var work = new Complex32[columnsA * Control.BlockSize];
SafeNativeMethods.c_qr_thin_factor(rowsA, columnsA, q, tau, r, work, work.Length);
}
/// <summary>
/// Computes the thin QR factorization of A where M &gt; N.
/// </summary>
/// <param name="q">On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the Q matrix of the QR factorization.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="r">On exit, A N by N matrix that holds the R matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void ThinQRFactor(Complex32[] q, int rowsA, int columnsA, Complex32[] r, Complex32[] tau, Complex32[] work)
{
if (r == null)
{
throw new ArgumentNullException("r");
}
if (q == null)
{
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("q");
}
if (q.Length != rowsA*columnsA)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "q");
}
if (tau.Length < Math.Min(rowsA, columnsA))
{
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
if (r.Length != columnsA*columnsA)
{
throw new ArgumentException(
string.Format(Resources.ArgumentArrayWrongLength, "columnsA * columnsA"), "r");
}
var info = SafeNativeMethods.c_qr_thin_factor(rowsA, columnsA, q, tau, r);
if (work.Length < columnsA*Control.BlockSize)
if (info < 0)
{
work[0] = columnsA*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
SafeNativeMethods.c_qr_thin_factor(rowsA, columnsA, q, tau, r, work, work.Length);
}
/// <summary>
@ -812,27 +686,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolve(Complex32[] a, int rows, int columns, Complex32[] b, int columnsB, Complex32[] x, QRMethod method = QRMethod.Full)
{
var work = new Complex32[columns*Control.BlockSize];
QRSolve(a, rows, columns, b, columnsB, x, work, method);
}
/// <summary>
/// Solves A*X=B for X using QR factorization of A.
/// </summary>
/// <param name="a">The A matrix.</param>
/// <param name="rows">The number of rows in the A matrix.</param>
/// <param name="columns">The number of columns in the A matrix.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolve(Complex32[] a, int rows, int columns, Complex32[] b, int columnsB, Complex32[] x, Complex32[] work, QRMethod method = QRMethod.Full)
{
if (a == null)
{
@ -849,22 +702,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentNullException("x");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (a.Length != rows*columns)
if (a.Length != rows * columns)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
if (b.Length != rows*columnsB)
if (b.Length != rows * columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
if (x.Length != columns*columnsB)
if (x.Length != columns * columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "x");
}
@ -874,56 +722,40 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.RowsLessThanColumns);
}
if (work.Length < 1)
var info = SafeNativeMethods.c_qr_solve(rows, columns, columnsB, a, b, x);
if (info == (int)MklError.MemoryAllocation)
{
work[0] = rows*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new MemoryAllocationException();
}
SafeNativeMethods.c_qr_solve(rows, columns, columnsB, a, b, x, work, work.Length);
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
/// <summary>
/// Solves A*X=B for X using a previously QR factored matrix.
/// </summary>
/// <param name="q">The Q matrix obtained by calling <see cref="QRFactor(Complex32[],int,int,Complex32[],Complex32[])"/>.</param>
/// <param name="r">The R matrix obtained by calling <see cref="QRFactor(Complex32[],int,int,Complex32[],Complex32[])"/>. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="tau">Contains additional information on Q. Only used for the native solver
/// and can be <c>null</c> for the managed provider.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolveFactored(Complex32[] q, Complex32[] r, int rowsR, int columnsR, Complex32[] tau, Complex32[] b, int columnsB, Complex32[] x, QRMethod method = QRMethod.Full)
{
var work = new Complex32[columnsR*Control.BlockSize];
QRSolveFactored(q, r, rowsR, columnsR, tau, b, columnsB, x, work, method);
if (info > 0)
{
throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient, "a");
}
}
/// <summary>
/// Solves A*X=B for X using a previously QR factored matrix.
/// </summary>
/// <param name="q">The Q matrix obtained by QR factor. This is only used for the managed provider and can be
/// <c>null</c> for the native provider. The native provider uses the Q portion stored in the R matrix.</param>
/// <param name="q">The Q matrix obtained by calling <see cref="QRFactor(Complex32[],int,int,Complex32[],Complex32[])"/>.</param>
/// <param name="r">The R matrix obtained by calling <see cref="QRFactor(Complex32[],int,int,Complex32[],Complex32[])"/>. </param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="tau">Contains additional information on Q. Only used for the native solver
/// and can be <c>null</c> for the managed provider.</param>
/// <param name="b">On entry the B matrix; on exit the X matrix.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="work">The work array - only used in the native provider. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolveFactored(Complex32[] q, Complex32[] r, int rowsA, int columnsA, Complex32[] tau, Complex32[] b, int columnsB, Complex32[] x, Complex32[] work, QRMethod method = QRMethod.Full)
public override void QRSolveFactored(Complex32[] q, Complex32[] r, int rowsA, int columnsA, Complex32[] tau, Complex32[] b, int columnsB, Complex32[] x, QRMethod method = QRMethod.Full)
{
if (r == null)
{
@ -945,11 +777,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
int rowsQ, columnsQ, rowsR, columnsR;
if (method == QRMethod.Full)
{
@ -962,35 +789,39 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
columnsQ = rowsR = columnsR = columnsA;
}
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR*columnsR), "r");
}
if (q.Length != rowsQ*columnsQ)
if (r.Length != rowsR * columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ*columnsQ), "q");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR * columnsR), "r");
}
if (b.Length != rowsA*columnsB)
if (q.Length != rowsQ * columnsQ)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA*columnsB), "b");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ * columnsQ), "q");
}
if (x.Length != columnsA*columnsB)
if (b.Length != rowsA * columnsB)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA*columnsB), "x");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA * columnsB), "b");
}
if (work.Length < 1)
if (x.Length != columnsA * columnsB)
{
work[0] = rowsA*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA * columnsB), "x");
}
if (method == QRMethod.Full)
{
SafeNativeMethods.c_qr_solve_factored(rowsA, columnsA, columnsB, r, b, tau, x, work, work.Length);
var info = SafeNativeMethods.c_qr_solve_factored(rowsA, columnsA, columnsB, r, b, tau, x);
if (info == (int)MklError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
else
{
@ -1000,61 +831,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
}
}
/// <summary>
/// Computes the singular value decomposition of A.
/// </summary>
/// <param name="computeVectors">Compute the singular U and VT vectors or not.</param>
/// <param name="a">On entry, the M by N matrix to decompose. On exit, A may be overwritten.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="s">The singular values of A in ascending value.</param>
/// <param name="u">If <paramref name="computeVectors"/> is <c>true</c>, on exit U contains the left
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void SingularValueDecomposition(bool computeVectors, Complex32[] a, int rowsA, int columnsA, Complex32[] s, Complex32[] u, Complex32[] vt)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (s == null)
{
throw new ArgumentNullException("s");
}
if (u == null)
{
throw new ArgumentNullException("u");
}
if (vt == null)
{
throw new ArgumentNullException("vt");
}
if (u.Length != rowsA*rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
if (vt.Length != columnsA*columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
if (s.Length != Math.Min(rowsA, columnsA))
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
var work = new Complex32[(2*Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA)];
SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, work);
}
/// <summary>
/// Solves A*X=B for X using the singular value decomposition of A.
/// </summary>
@ -1091,14 +867,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
var work = new Complex32[(2*Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA)];
var s = new Complex32[Math.Min(rowsA, columnsA)];
var u = new Complex32[rowsA*rowsA];
var vt = new Complex32[columnsA*columnsA];
var clone = new Complex32[a.Length];
a.Copy(clone);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt, work);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt);
SvdSolveFactored(rowsA, columnsA, s, u, vt, b, columnsB, x);
}
@ -1114,12 +889,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <param name="work">The work array. For real matrices, the work array should be at least
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void SingularValueDecomposition(bool computeVectors, Complex32[] a, int rowsA, int columnsA, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] work)
public override void SingularValueDecomposition(bool computeVectors, Complex32[] a, int rowsA, int columnsA, Complex32[] s, Complex32[] u, Complex32[] vt)
{
if (a == null)
{
@ -1141,17 +913,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentNullException("vt");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (u.Length != rowsA*rowsA)
if (u.Length != rowsA * rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
if (vt.Length != columnsA*columnsA)
if (vt.Length != columnsA * columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
@ -1161,18 +928,19 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
if (work.Length == 0)
var info = SafeNativeMethods.c_svd_factor(computeVectors, rowsA, columnsA, a, s, u, vt);
if (info == (int)MklError.MemoryAllocation)
{
throw new ArgumentException(Resources.ArgumentSingleDimensionArray, "work");
throw new MemoryAllocationException();
}
if (work.Length < (2*Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA))
if (info < 0)
{
work[0] = (2*Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA);
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
if (SafeNativeMethods.c_svd_factor(computeVectors, rowsA, columnsA, a, s, u, vt, work, work.Length) > 0)
if (info > 0)
{
throw new NonConvergenceException();
}
@ -1366,10 +1134,22 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
if (matrixD.Length != order * order)
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order * order), "matrixD");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, order * order), "matrixD");
}
if (SafeNativeMethods.c_eigen(isSymmetric, order, matrix, matrixEv, vectorEv, matrixD) > 0)
var info = SafeNativeMethods.c_eigen(isSymmetric, order, matrix, matrixEv, vectorEv, matrixD);
if (info == (int)MklError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
if (info > 0)
{
throw new NonConvergenceException();
}

481
src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Double.cs

@ -76,8 +76,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, rows * columns), "matrix");
}
var work = new double[rows];
return SafeNativeMethods.d_matrix_norm((byte)norm, rows, columns, matrix, work);
return SafeNativeMethods.d_matrix_norm((byte)norm, rows, columns, matrix);
}
/// <summary>
@ -274,7 +273,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
SafeNativeMethods.d_lu_factor(order, data, ipiv);
var info = SafeNativeMethods.d_lu_factor(order, data, ipiv);
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -296,77 +300,22 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
var work = new double[order];
SafeNativeMethods.d_lu_inverse(order, a, work, work.Length);
}
var info = SafeNativeMethods.d_lu_inverse(order, a);
/// <summary>
/// Computes the inverse of a previously factored matrix.
/// </summary>
/// <param name="a">The LU factored N by N matrix. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="ipiv">The pivot indices of <paramref name="a"/>.</param>
/// <remarks>This is equivalent to the GETRI LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void LUInverseFactored(double[] a, int order, int[] ipiv)
{
if (a == null)
if (info == (int)MklError.MemoryAllocation)
{
throw new ArgumentNullException("a");
throw new MemoryAllocationException();
}
if (ipiv == null)
if (info < 0)
{
throw new ArgumentNullException("ipiv");
throw new InvalidParameterException(Math.Abs(info));
}
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
if (ipiv.Length != order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
var work = new double[order];
SafeNativeMethods.d_lu_inverse_factored(order, a, ipiv, work, order);
}
/// <summary>
/// Computes the inverse of matrix using LU factorization.
/// </summary>
/// <param name="a">The N by N matrix to invert. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is equivalent to the GETRF and GETRI LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void LUInverse(double[] a, int order, double[] work)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (work.Length < order)
if (info > 0)
{
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new SingularUMatrixException(info);
}
SafeNativeMethods.d_lu_inverse(order, a, work, work.Length);
}
/// <summary>
@ -375,12 +324,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
/// <param name="a">The LU factored N by N matrix. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="ipiv">The pivot indices of <paramref name="a"/>.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is equivalent to the GETRI LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void LUInverseFactored(double[] a, int order, int[] ipiv, double[] work)
public override void LUInverseFactored(double[] a, int order, int[] ipiv)
{
if (a == null)
{
@ -402,17 +348,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
var info = SafeNativeMethods.d_lu_inverse_factored(order, a, ipiv);
if (work.Length < order)
if (info < 0)
{
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
SafeNativeMethods.d_lu_inverse_factored(order, a, ipiv, work, order);
if (info > 0)
{
throw new SingularUMatrixException(info);
}
}
/// <summary>
@ -446,7 +392,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.d_lu_solve(order, columnsOfB, a, b);
var info = SafeNativeMethods.d_lu_solve(order, columnsOfB, a, b);
if (info == (int)MklError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -491,7 +447,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.d_lu_solve_factored(order, columnsOfB, a, ipiv, b);
var info = SafeNativeMethods.d_lu_solve_factored(order, columnsOfB, a, ipiv, b);
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -521,6 +482,16 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
var info = SafeNativeMethods.d_cholesky_factor(order, a);
if (info == (int)MklError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
if (info > 0)
{
throw new ArgumentException(Resources.ArgumentMatrixPositiveDefinite);
@ -559,7 +530,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.d_cholesky_solve(orderA, columnsB, a, b);
var info = SafeNativeMethods.d_cholesky_solve(orderA, columnsB, a, b);
if (info == (int)MklError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -593,51 +574,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.d_cholesky_solve_factored(orderA, columnsB, a, b);
}
/// <summary>
/// Computes the QR factorization of A.
/// </summary>
/// <param name="r">On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void QRFactor(double[] r, int rowsR, int columnsR, double[] q, double[] tau)
{
if (r == null)
{
throw new ArgumentNullException("r");
}
if (q == null)
{
throw new ArgumentNullException("q");
}
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r");
}
if (tau.Length < Math.Min(rowsR, columnsR))
{
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
var info = SafeNativeMethods.d_cholesky_solve_factored(orderA, columnsB, a, b);
if (q.Length != rowsR*rowsR)
if (info < 0)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * rowsR"), "q");
throw new InvalidParameterException(Math.Abs(info));
}
var work = new double[columnsR*Control.BlockSize];
SafeNativeMethods.d_qr_factor(rowsR, columnsR, r, tau, q, work, work.Length);
}
/// <summary>
@ -647,16 +589,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
/// it is overwritten with the R matrix of the QR factorization. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void QRFactor(double[] r, int rowsR, int columnsR, double[] q, double[] tau, double[] work)
public override void QRFactor(double[] r, int rowsR, int columnsR, double[] q, double[] tau)
{
if (r == null)
{
@ -668,11 +607,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r");
@ -688,13 +622,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * rowsR"), "q");
}
if (work.Length < columnsR*Control.BlockSize)
var info = SafeNativeMethods.d_qr_factor(rowsR, columnsR, r, tau, q);
if (info < 0)
{
work[0] = columnsR*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
SafeNativeMethods.d_qr_factor(rowsR, columnsR, r, tau, q, work, work.Length);
}
/// <summary>
@ -737,66 +670,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "columnsA * columnsA"), "r");
}
var work = new double[columnsA*Control.BlockSize];
SafeNativeMethods.d_qr_thin_factor(rowsA, columnsA, q, tau, r, work, work.Length);
}
var info = SafeNativeMethods.d_qr_thin_factor(rowsA, columnsA, q, tau, r);
/// <summary>
/// Computes the thin QR factorization of A where M &gt; N.
/// </summary>
/// <param name="q">On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the Q matrix of the QR factorization.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="r">On exit, A N by N matrix that holds the R matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void ThinQRFactor(double[] q, int rowsA, int columnsA, double[] r, double[] tau, double[] work)
{
if (r == null)
if (info < 0)
{
throw new ArgumentNullException("r");
throw new InvalidParameterException(Math.Abs(info));
}
if (q == null)
{
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("q");
}
if (q.Length != rowsA*columnsA)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "q");
}
if (tau.Length < Math.Min(rowsA, columnsA))
{
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
if (r.Length != columnsA*columnsA)
{
throw new ArgumentException(
string.Format(Resources.ArgumentArrayWrongLength, "columnsA * columnsA"), "r");
}
if (work.Length < columnsA*Control.BlockSize)
{
work[0] = columnsA*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
SafeNativeMethods.d_qr_thin_factor(rowsA, columnsA, q, tau, r, work, work.Length);
}
/// <summary>
@ -812,27 +691,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolve(double[] a, int rows, int columns, double[] b, int columnsB, double[] x, QRMethod method = QRMethod.Full)
{
var work = new double[columns*Control.BlockSize];
QRSolve(a, rows, columns, b, columnsB, x, work, method);
}
/// <summary>
/// Solves A*X=B for X using QR factorization of A.
/// </summary>
/// <param name="a">The A matrix.</param>
/// <param name="rows">The number of rows in the A matrix.</param>
/// <param name="columns">The number of columns in the A matrix.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolve(double[] a, int rows, int columns, double[] b, int columnsB, double[] x, double[] work, QRMethod method = QRMethod.Full)
{
if (a == null)
{
@ -849,22 +707,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentNullException("x");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (a.Length != rows*columns)
if (a.Length != rows * columns)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
if (b.Length != rows*columnsB)
if (b.Length != rows * columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
if (x.Length != columns*columnsB)
if (x.Length != columns * columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "x");
}
@ -874,56 +727,40 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.RowsLessThanColumns);
}
if (work.Length < 1)
var info = SafeNativeMethods.d_qr_solve(rows, columns, columnsB, a, b, x);
if (info == (int)MklError.MemoryAllocation)
{
work[0] = rows*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new MemoryAllocationException();
}
SafeNativeMethods.d_qr_solve(rows, columns, columnsB, a, b, x, work, work.Length);
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
/// <summary>
/// Solves A*X=B for X using a previously QR factored matrix.
/// </summary>
/// <param name="q">The Q matrix obtained by calling <see cref="QRFactor(double[],int,int,double[],double[])"/>.</param>
/// <param name="r">The R matrix obtained by calling <see cref="QRFactor(double[],int,int,double[],double[])"/>. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="tau">Contains additional information on Q. Only used for the native solver
/// and can be <c>null</c> for the managed provider.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolveFactored(double[] q, double[] r, int rowsR, int columnsR, double[] tau, double[] b, int columnsB, double[] x, QRMethod method = QRMethod.Full)
{
var work = new double[columnsR*Control.BlockSize];
QRSolveFactored(q, r, rowsR, columnsR, tau, b, columnsB, x, work, method);
if (info > 0)
{
throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient, "a");
}
}
/// <summary>
/// Solves A*X=B for X using a previously QR factored matrix.
/// </summary>
/// <param name="q">The Q matrix obtained by QR factor. This is only used for the managed provider and can be
/// <c>null</c> for the native provider. The native provider uses the Q portion stored in the R matrix.</param>
/// <param name="q">The Q matrix obtained by calling <see cref="QRFactor(double[],int,int,double[],double[])"/>.</param>
/// <param name="r">The R matrix obtained by calling <see cref="QRFactor(double[],int,int,double[],double[])"/>. </param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="tau">Contains additional information on Q. Only used for the native solver
/// and can be <c>null</c> for the managed provider.</param>
/// <param name="b">On entry the B matrix; on exit the X matrix.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="work">The work array - only used in the native provider. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolveFactored(double[] q, double[] r, int rowsA, int columnsA, double[] tau, double[] b, int columnsB, double[] x, double[] work, QRMethod method = QRMethod.Full)
public override void QRSolveFactored(double[] q, double[] r, int rowsA, int columnsA, double[] tau, double[] b, int columnsB, double[] x, QRMethod method = QRMethod.Full)
{
if (r == null)
{
@ -945,11 +782,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
int rowsQ, columnsQ, rowsR, columnsR;
if (method == QRMethod.Full)
{
@ -962,35 +794,39 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
columnsQ = rowsR = columnsR = columnsA;
}
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR*columnsR), "r");
}
if (q.Length != rowsQ*columnsQ)
if (r.Length != rowsR * columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ*columnsQ), "q");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR * columnsR), "r");
}
if (b.Length != rowsA*columnsB)
if (q.Length != rowsQ * columnsQ)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA*columnsB), "b");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ * columnsQ), "q");
}
if (x.Length != columnsA*columnsB)
if (b.Length != rowsA * columnsB)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA*columnsB), "x");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA * columnsB), "b");
}
if (work.Length < 1)
if (x.Length != columnsA * columnsB)
{
work[0] = rowsA*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA * columnsB), "x");
}
if (method == QRMethod.Full)
{
SafeNativeMethods.d_qr_solve_factored(rowsA, columnsA, columnsB, r, b, tau, x, work, work.Length);
var info = SafeNativeMethods.d_qr_solve_factored(rowsA, columnsA, columnsB, r, b, tau, x);
if (info == (int)MklError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
else
{
@ -1000,61 +836,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
}
}
/// <summary>
/// Computes the singular value decomposition of A.
/// </summary>
/// <param name="computeVectors">Compute the singular U and VT vectors or not.</param>
/// <param name="a">On entry, the M by N matrix to decompose. On exit, A may be overwritten.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="s">The singular values of A in ascending value.</param>
/// <param name="u">If <paramref name="computeVectors"/> is <c>true</c>, on exit U contains the left
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void SingularValueDecomposition(bool computeVectors, double[] a, int rowsA, int columnsA, double[] s, double[] u, double[] vt)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (s == null)
{
throw new ArgumentNullException("s");
}
if (u == null)
{
throw new ArgumentNullException("u");
}
if (vt == null)
{
throw new ArgumentNullException("vt");
}
if (u.Length != rowsA*rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
if (vt.Length != columnsA*columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
if (s.Length != Math.Min(rowsA, columnsA))
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
var work = new double[Math.Max((3*Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA), 5*Math.Min(rowsA, columnsA))];
SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, work);
}
/// <summary>
/// Solves A*X=B for X using the singular value decomposition of A.
/// </summary>
@ -1091,14 +872,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
var work = new double[Math.Max((3*Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA), 5*Math.Min(rowsA, columnsA))];
var s = new double[Math.Min(rowsA, columnsA)];
var u = new double[rowsA*rowsA];
var vt = new double[columnsA*columnsA];
var clone = new double[a.Length];
a.Copy(clone);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt, work);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt);
SvdSolveFactored(rowsA, columnsA, s, u, vt, b, columnsB, x);
}
@ -1114,12 +894,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <param name="work">The work array. For real matrices, the work array should be at least
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void SingularValueDecomposition(bool computeVectors, double[] a, int rowsA, int columnsA, double[] s, double[] u, double[] vt, double[] work)
public override void SingularValueDecomposition(bool computeVectors, double[] a, int rowsA, int columnsA, double[] s, double[] u, double[] vt)
{
if (a == null)
{
@ -1141,17 +918,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentNullException("vt");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (u.Length != rowsA*rowsA)
if (u.Length != rowsA * rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
if (vt.Length != columnsA*columnsA)
if (vt.Length != columnsA * columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
@ -1161,18 +933,19 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
if (work.Length == 0)
var info = SafeNativeMethods.d_svd_factor(computeVectors, rowsA, columnsA, a, s, u, vt);
if (info == (int)MklError.MemoryAllocation)
{
throw new ArgumentException(Resources.ArgumentSingleDimensionArray, "work");
throw new MemoryAllocationException();
}
if (work.Length < Math.Max((3*Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA), 5*Math.Min(rowsA, columnsA)))
if (info < 0)
{
work[0] = Math.Max((3*Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA), 5*Math.Min(rowsA, columnsA));
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
if (SafeNativeMethods.d_svd_factor(computeVectors, rowsA, columnsA, a, s, u, vt, work, work.Length) > 0)
if (info > 0)
{
throw new NonConvergenceException();
}
@ -1369,7 +1142,19 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order*order), "matrixD");
}
if (SafeNativeMethods.d_eigen(isSymmetric, order, matrix, matrixEv, vectorEv, matrixD) > 0)
var info = SafeNativeMethods.d_eigen(isSymmetric, order, matrix, matrixEv, vectorEv, matrixD);
if (info == (int)MklError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
if (info > 0)
{
throw new NonConvergenceException();
}

472
src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Single.cs

@ -76,8 +76,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, rows * columns), "matrix");
}
var work = new float[rows];
return SafeNativeMethods.s_matrix_norm((byte)norm, rows, columns, matrix, work);
return SafeNativeMethods.s_matrix_norm((byte)norm, rows, columns, matrix);
}
/// <summary>
@ -274,7 +273,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
SafeNativeMethods.s_lu_factor(order, data, ipiv);
var info = SafeNativeMethods.s_lu_factor(order, data, ipiv);
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -296,77 +300,22 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
var work = new float[order];
SafeNativeMethods.s_lu_inverse(order, a, work, work.Length);
}
/// <summary>
/// Computes the inverse of a previously factored matrix.
/// </summary>
/// <param name="a">The LU factored N by N matrix. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="ipiv">The pivot indices of <paramref name="a"/>.</param>
/// <remarks>This is equivalent to the GETRI LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void LUInverseFactored(float[] a, int order, int[] ipiv)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (ipiv == null)
{
throw new ArgumentNullException("ipiv");
}
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
if (ipiv.Length != order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
var work = new float[order];
SafeNativeMethods.s_lu_inverse_factored(order, a, ipiv, work, order);
}
/// <summary>
/// Computes the inverse of matrix using LU factorization.
/// </summary>
/// <param name="a">The N by N matrix to invert. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is equivalent to the GETRF and GETRI LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void LUInverse(float[] a, int order, float[] work)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
var info = SafeNativeMethods.s_lu_inverse(order, a);
if (a.Length != order*order)
if (info == (int)MklError.MemoryAllocation)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
throw new MemoryAllocationException();
}
if (work == null)
if (info < 0)
{
throw new ArgumentNullException("work");
throw new InvalidParameterException(Math.Abs(info));
}
if (work.Length < order)
if (info > 0)
{
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new SingularUMatrixException(info);
}
SafeNativeMethods.s_lu_inverse(order, a, work, work.Length);
}
/// <summary>
@ -375,12 +324,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
/// <param name="a">The LU factored N by N matrix. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="ipiv">The pivot indices of <paramref name="a"/>.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is equivalent to the GETRI LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void LUInverseFactored(float[] a, int order, int[] ipiv, float[] work)
public override void LUInverseFactored(float[] a, int order, int[] ipiv)
{
if (a == null)
{
@ -402,17 +348,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
var info = SafeNativeMethods.s_lu_inverse_factored(order, a, ipiv);
if (work.Length < order)
if (info < 0)
{
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
SafeNativeMethods.s_lu_inverse_factored(order, a, ipiv, work, order);
if (info > 0)
{
throw new SingularUMatrixException(info);
}
}
/// <summary>
@ -446,7 +392,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.s_lu_solve(order, columnsOfB, a, b);
var info = SafeNativeMethods.s_lu_solve(order, columnsOfB, a, b);
if (info == (int)MklError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -491,7 +447,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.s_lu_solve_factored(order, columnsOfB, a, ipiv, b);
var info = SafeNativeMethods.s_lu_solve_factored(order, columnsOfB, a, ipiv, b);
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -521,6 +482,11 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
var info = SafeNativeMethods.s_cholesky_factor(order, a);
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
if (info > 0)
{
throw new ArgumentException(Resources.ArgumentMatrixPositiveDefinite);
@ -559,7 +525,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.s_cholesky_solve(orderA, columnsB, a, b);
var info = SafeNativeMethods.s_cholesky_solve(orderA, columnsB, a, b);
if (info == (int)MklError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -593,51 +569,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.s_cholesky_solve_factored(orderA, columnsB, a, b);
}
/// <summary>
/// Computes the QR factorization of A.
/// </summary>
/// <param name="r">On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void QRFactor(float[] r, int rowsR, int columnsR, float[] q, float[] tau)
{
if (r == null)
{
throw new ArgumentNullException("r");
}
if (q == null)
{
throw new ArgumentNullException("q");
}
var info = SafeNativeMethods.s_cholesky_solve_factored(orderA, columnsB, a, b);
if (r.Length != rowsR*columnsR)
if (info < 0)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r");
throw new InvalidParameterException(Math.Abs(info));
}
if (tau.Length < Math.Min(rowsR, columnsR))
{
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
if (q.Length != rowsR*rowsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * rowsR"), "q");
}
var work = new float[columnsR*Control.BlockSize];
SafeNativeMethods.s_qr_factor(rowsR, columnsR, r, tau, q, work, work.Length);
}
/// <summary>
@ -647,16 +584,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
/// it is overwritten with the R matrix of the QR factorization. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void QRFactor(float[] r, int rowsR, int columnsR, float[] q, float[] tau, float[] work)
public override void QRFactor(float[] r, int rowsR, int columnsR, float[] q, float[] tau)
{
if (r == null)
{
@ -668,11 +602,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r");
@ -688,13 +617,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * rowsR"), "q");
}
if (work.Length < columnsR*Control.BlockSize)
var info = SafeNativeMethods.s_qr_factor(rowsR, columnsR, r, tau, q);
if (info < 0)
{
work[0] = columnsR*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
SafeNativeMethods.s_qr_factor(rowsR, columnsR, r, tau, q, work, work.Length);
}
/// <summary>
@ -737,66 +665,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "columnsA * columnsA"), "r");
}
var work = new float[columnsA * Control.BlockSize];
SafeNativeMethods.s_qr_thin_factor(rowsA, columnsA, q, tau, r, work, work.Length);
}
var info = SafeNativeMethods.s_qr_thin_factor(rowsA, columnsA, q, tau, r);
/// <summary>
/// Computes the thin QR factorization of A where M &gt; N.
/// </summary>
/// <param name="q">On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the Q matrix of the QR factorization.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="r">On exit, A N by N matrix that holds the R matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void ThinQRFactor(float[] q, int rowsA, int columnsA, float[] r, float[] tau, float[] work)
{
if (r == null)
if (info < 0)
{
throw new ArgumentNullException("r");
throw new InvalidParameterException(Math.Abs(info));
}
if (q == null)
{
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("q");
}
if (q.Length != rowsA*columnsA)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "q");
}
if (tau.Length < Math.Min(rowsA, columnsA))
{
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
if (r.Length != columnsA*columnsA)
{
throw new ArgumentException(
string.Format(Resources.ArgumentArrayWrongLength, "columnsA * columnsA"), "r");
}
if (work.Length < columnsA*Control.BlockSize)
{
work[0] = columnsA*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
SafeNativeMethods.s_qr_thin_factor(rowsA, columnsA, q, tau, r, work, work.Length);
}
/// <summary>
@ -812,27 +686,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolve(float[] a, int rows, int columns, float[] b, int columnsB, float[] x, QRMethod method = QRMethod.Full)
{
var work = new float[columns*Control.BlockSize];
QRSolve(a, rows, columns, b, columnsB, x, work, method);
}
/// <summary>
/// Solves A*X=B for X using QR factorization of A.
/// </summary>
/// <param name="a">The A matrix.</param>
/// <param name="rows">The number of rows in the A matrix.</param>
/// <param name="columns">The number of columns in the A matrix.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolve(float[] a, int rows, int columns, float[] b, int columnsB, float[] x, float[] work, QRMethod method = QRMethod.Full)
{
if (a == null)
{
@ -849,22 +702,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentNullException("x");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (a.Length != rows*columns)
if (a.Length != rows * columns)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
if (b.Length != rows*columnsB)
if (b.Length != rows * columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
if (x.Length != columns*columnsB)
if (x.Length != columns * columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "x");
}
@ -874,56 +722,40 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.RowsLessThanColumns);
}
if (work.Length < 1)
var info = SafeNativeMethods.s_qr_solve(rows, columns, columnsB, a, b, x);
if (info == (int)MklError.MemoryAllocation)
{
work[0] = rows*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new MemoryAllocationException();
}
SafeNativeMethods.s_qr_solve(rows, columns, columnsB, a, b, x, work, work.Length);
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
/// <summary>
/// Solves A*X=B for X using a previously QR factored matrix.
/// </summary>
/// <param name="q">The Q matrix obtained by calling <see cref="QRFactor(float[],int,int,float[],float[])"/>.</param>
/// <param name="r">The R matrix obtained by calling <see cref="QRFactor(float[],int,int,float[],float[])"/>. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="tau">Contains additional information on Q. Only used for the native solver
/// and can be <c>null</c> for the managed provider.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolveFactored(float[] q, float[] r, int rowsR, int columnsR, float[] tau, float[] b, int columnsB, float[] x, QRMethod method = QRMethod.Full)
{
var work = new float[columnsR*Control.BlockSize];
QRSolveFactored(q, r, rowsR, columnsR, tau, b, columnsB, x, work, method);
if (info > 0)
{
throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient, "a");
}
}
/// <summary>
/// Solves A*X=B for X using a previously QR factored matrix.
/// </summary>
/// <param name="q">The Q matrix obtained by QR factor. This is only used for the managed provider and can be
/// <c>null</c> for the native provider. The native provider uses the Q portion stored in the R matrix.</param>
/// <param name="q">The Q matrix obtained by calling <see cref="QRFactor(float[],int,int,float[],float[])"/>.</param>
/// <param name="r">The R matrix obtained by calling <see cref="QRFactor(float[],int,int,float[],float[])"/>. </param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="tau">Contains additional information on Q. Only used for the native solver
/// and can be <c>null</c> for the managed provider.</param>
/// <param name="b">On entry the B matrix; on exit the X matrix.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="work">The work array - only used in the native provider. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolveFactored(float[] q, float[] r, int rowsA, int columnsA, float[] tau, float[] b, int columnsB, float[] x, float[] work, QRMethod method = QRMethod.Full)
public override void QRSolveFactored(float[] q, float[] r, int rowsA, int columnsA, float[] tau, float[] b, int columnsB, float[] x, QRMethod method = QRMethod.Full)
{
if (r == null)
{
@ -945,11 +777,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
int rowsQ, columnsQ, rowsR, columnsR;
if (method == QRMethod.Full)
{
@ -962,35 +789,39 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
columnsQ = rowsR = columnsR = columnsA;
}
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR*columnsR), "r");
}
if (q.Length != rowsQ*columnsQ)
if (r.Length != rowsR * columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ*columnsQ), "q");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR * columnsR), "r");
}
if (b.Length != rowsA*columnsB)
if (q.Length != rowsQ * columnsQ)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA*columnsB), "b");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ * columnsQ), "q");
}
if (x.Length != columnsA*columnsB)
if (b.Length != rowsA * columnsB)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA*columnsB), "x");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA * columnsB), "b");
}
if (work.Length < 1)
if (x.Length != columnsA * columnsB)
{
work[0] = rowsA*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA * columnsB), "x");
}
if (method == QRMethod.Full)
{
SafeNativeMethods.s_qr_solve_factored(rowsA, columnsA, columnsB, r, b, tau, x, work, work.Length);
var info = SafeNativeMethods.s_qr_solve_factored(rowsA, columnsA, columnsB, r, b, tau, x);
if (info == (int)MklError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
else
{
@ -1000,61 +831,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
}
}
/// <summary>
/// Computes the singular value decomposition of A.
/// </summary>
/// <param name="computeVectors">Compute the singular U and VT vectors or not.</param>
/// <param name="a">On entry, the M by N matrix to decompose. On exit, A may be overwritten.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="s">The singular values of A in ascending value.</param>
/// <param name="u">If <paramref name="computeVectors"/> is <c>true</c>, on exit U contains the left
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void SingularValueDecomposition(bool computeVectors, float[] a, int rowsA, int columnsA, float[] s, float[] u, float[] vt)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (s == null)
{
throw new ArgumentNullException("s");
}
if (u == null)
{
throw new ArgumentNullException("u");
}
if (vt == null)
{
throw new ArgumentNullException("vt");
}
if (u.Length != rowsA*rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
if (vt.Length != columnsA*columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
if (s.Length != Math.Min(rowsA, columnsA))
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
var work = new float[Math.Max(((3*Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA)), 5*Math.Min(rowsA, columnsA))];
SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, work);
}
/// <summary>
/// Solves A*X=B for X using the singular value decomposition of A.
/// </summary>
@ -1091,14 +867,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
var work = new float[Math.Max(((3*Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA)), 5*Math.Min(rowsA, columnsA))];
var s = new float[Math.Min(rowsA, columnsA)];
var u = new float[rowsA*rowsA];
var vt = new float[columnsA*columnsA];
var clone = new float[a.Length];
a.Copy(clone);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt, work);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt);
SvdSolveFactored(rowsA, columnsA, s, u, vt, b, columnsB, x);
}
@ -1114,12 +889,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <param name="work">The work array. For real matrices, the work array should be at least
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void SingularValueDecomposition(bool computeVectors, float[] a, int rowsA, int columnsA, float[] s, float[] u, float[] vt, float[] work)
public override void SingularValueDecomposition(bool computeVectors, float[] a, int rowsA, int columnsA, float[] s, float[] u, float[] vt)
{
if (a == null)
{
@ -1141,11 +913,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentNullException("vt");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (u.Length != rowsA*rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
@ -1161,18 +928,19 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
if (work.Length == 0)
var info = SafeNativeMethods.s_svd_factor(computeVectors, rowsA, columnsA, a, s, u, vt);
if (info == (int)MklError.MemoryAllocation)
{
throw new ArgumentException(Resources.ArgumentSingleDimensionArray, "work");
throw new MemoryAllocationException();
}
if (work.Length < Math.Max(((3*Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA)), 5*Math.Min(rowsA, columnsA)))
if (info < 0)
{
work[0] = Math.Max(((3*Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA)), 5*Math.Min(rowsA, columnsA));
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
if (SafeNativeMethods.s_svd_factor(computeVectors, rowsA, columnsA, a, s, u, vt, work, work.Length) > 0)
if (info > 0)
{
throw new NonConvergenceException();
}
@ -1369,7 +1137,19 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order*order), "matrixD");
}
if (SafeNativeMethods.s_eigen(isSymmetric, order, matrix, matrixEv, vectorEv, matrixD) > 0)
var info = SafeNativeMethods.s_eigen(isSymmetric, order, matrix, matrixEv, vectorEv, matrixD);
if (info == (int)MklError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
if (info > 0)
{
throw new NonConvergenceException();
}

11
src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.cs

@ -34,6 +34,17 @@ using System;
namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
{
/// <summary>
/// Error codes return from the MKL provider.
/// </summary>
public enum MklError : int
{
/// <summary>
/// Unable to allocate memory.
/// </summary>
MemoryAllocation = -999999
}
/// <summary>
/// Consistency vs. performance trade-off between runs on different machines.
/// </summary>

64
src/Numerics/Providers/LinearAlgebra/Mkl/SafeNativeMethods.cs

@ -134,16 +134,16 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
#region LAPACK
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern float s_matrix_norm(byte norm, int rows, int columns, [In] float[] a, [In, Out] float[] work);
internal static extern float s_matrix_norm(byte norm, int rows, int columns, [In] float[] a);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern double d_matrix_norm(byte norm, int rows, int columns, [In] double[] a, [In, Out] double[] work);
internal static extern double d_matrix_norm(byte norm, int rows, int columns, [In] double[] a);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern float c_matrix_norm(byte norm, int rows, int columns, [In] Complex32[] a, [In, Out] float[] work);
internal static extern float c_matrix_norm(byte norm, int rows, int columns, [In] Complex32[] a);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern double z_matrix_norm(byte norm, int rows, int columns, [In] Complex[] a, [In, Out] double[] work);
internal static extern double z_matrix_norm(byte norm, int rows, int columns, [In] Complex[] a);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int s_cholesky_factor(int n, [In, Out] float[] a);
@ -170,28 +170,28 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
internal static extern int z_lu_factor(int n, [In, Out] Complex[] a, [In, Out] int[] ipiv);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int s_lu_inverse(int n, [In, Out] float[] a, [In, Out] float[] work, int lwork);
internal static extern int s_lu_inverse(int n, [In, Out] float[] a);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int d_lu_inverse(int n, [In, Out] double[] a, [In, Out] double[] work, int lwork);
internal static extern int d_lu_inverse(int n, [In, Out] double[] a);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int c_lu_inverse(int n, [In, Out] Complex32[] a, [In, Out] Complex32[] work, int lwork);
internal static extern int c_lu_inverse(int n, [In, Out] Complex32[] a);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int z_lu_inverse(int n, [In, Out] Complex[] a, [In, Out] Complex[] work, int lwork);
internal static extern int z_lu_inverse(int n, [In, Out] Complex[] a);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int s_lu_inverse_factored(int n, [In, Out] float[] a, [In, Out] int[] ipiv, [In, Out] float[] work, int lwork);
internal static extern int s_lu_inverse_factored(int n, [In, Out] float[] a, [In, Out] int[] ipiv);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int d_lu_inverse_factored(int n, [In, Out] double[] a, [In, Out] int[] ipiv, [In, Out] double[] work, int lwork);
internal static extern int d_lu_inverse_factored(int n, [In, Out] double[] a, [In, Out] int[] ipiv);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int c_lu_inverse_factored(int n, [In, Out] Complex32[] a, [In, Out] int[] ipiv, [In, Out] Complex32[] work, int lwork);
internal static extern int c_lu_inverse_factored(int n, [In, Out] Complex32[] a, [In, Out] int[] ipiv);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int z_lu_inverse_factored(int n, [In, Out] Complex[] a, [In, Out] int[] ipiv, [In, Out] Complex[] work, int lwork);
internal static extern int z_lu_inverse_factored(int n, [In, Out] Complex[] a, [In, Out] int[] ipiv);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int s_lu_solve_factored(int n, int nrhs, float[] a, [In, Out] int[] ipiv, [In, Out] float[] b);
@ -242,64 +242,64 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
internal static extern int z_cholesky_solve_factored(int n, int nrhs, Complex[] a, [In, Out] Complex[] b);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int s_qr_factor(int m, int n, [In, Out] float[] r, [In, Out] float[] tau, [In, Out] float[] q, [In, Out] float[] work, int len);
internal static extern int s_qr_factor(int m, int n, [In, Out] float[] r, [In, Out] float[] tau, [In, Out] float[] q);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int d_qr_factor(int m, int n, [In, Out] double[] r, [In, Out] double[] tau, [In, Out] double[] q, [In, Out] double[] work, int len);
internal static extern int d_qr_factor(int m, int n, [In, Out] double[] r, [In, Out] double[] tau, [In, Out] double[] q);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int c_qr_factor(int m, int n, [In, Out] Complex32[] r, [In, Out] Complex32[] tau, [In, Out] Complex32[] q, [In, Out] Complex32[] work, int len);
internal static extern int c_qr_factor(int m, int n, [In, Out] Complex32[] r, [In, Out] Complex32[] tau, [In, Out] Complex32[] q);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int z_qr_factor(int m, int n, [In, Out] Complex[] r, [In, Out] Complex[] tau, [In, Out] Complex[] q, [In, Out] Complex[] work, int len);
internal static extern int z_qr_factor(int m, int n, [In, Out] Complex[] r, [In, Out] Complex[] tau, [In, Out] Complex[] q);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int s_qr_thin_factor(int m, int n, [In, Out] float[] q, [In, Out] float[] tau, [In, Out] float[] r, [In, Out] float[] work, int len);
internal static extern int s_qr_thin_factor(int m, int n, [In, Out] float[] q, [In, Out] float[] tau, [In, Out] float[] r);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int d_qr_thin_factor(int m, int n, [In, Out] double[] q, [In, Out] double[] tau, [In, Out] double[] r, [In, Out] double[] work, int len);
internal static extern int d_qr_thin_factor(int m, int n, [In, Out] double[] q, [In, Out] double[] tau, [In, Out] double[] r);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int c_qr_thin_factor(int m, int n, [In, Out] Complex32[] q, [In, Out] Complex32[] tau, [In, Out] Complex32[] r, [In, Out] Complex32[] work, int len);
internal static extern int c_qr_thin_factor(int m, int n, [In, Out] Complex32[] q, [In, Out] Complex32[] tau, [In, Out] Complex32[] r);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int z_qr_thin_factor(int m, int n, [In, Out] Complex[] q, [In, Out] Complex[] tau, [In, Out] Complex[] r, [In, Out] Complex[] work, int len);
internal static extern int z_qr_thin_factor(int m, int n, [In, Out] Complex[] q, [In, Out] Complex[] tau, [In, Out] Complex[] r);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int s_qr_solve(int m, int n, int bn, float[] r, float[] b, [In, Out] float[] x, [In, Out] float[] work, int len);
internal static extern int s_qr_solve(int m, int n, int bn, float[] r, float[] b, [In, Out] float[] x);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int d_qr_solve(int m, int n, int bn, double[] r, double[] b, [In, Out] double[] x, [In, Out] double[] work, int len);
internal static extern int d_qr_solve(int m, int n, int bn, double[] r, double[] b, [In, Out] double[] x);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int c_qr_solve(int m, int n, int bn, Complex32[] r, Complex32[] b, [In, Out] Complex32[] x, [In, Out] Complex32[] work, int len);
internal static extern int c_qr_solve(int m, int n, int bn, Complex32[] r, Complex32[] b, [In, Out] Complex32[] x);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int z_qr_solve(int m, int n, int bn, Complex[] r, Complex[] b, [In, Out] Complex[] x, [In, Out] Complex[] work, int len);
internal static extern int z_qr_solve(int m, int n, int bn, Complex[] r, Complex[] b, [In, Out] Complex[] x);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int s_qr_solve_factored(int m, int n, int bn, float[] r, float[] b, float[] tau, [In, Out] float[] x, [In, Out] float[] work, int len);
internal static extern int s_qr_solve_factored(int m, int n, int bn, float[] r, float[] b, float[] tau, [In, Out] float[] x);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int d_qr_solve_factored(int m, int n, int bn, double[] r, double[] b, double[] tau, [In, Out] double[] x, [In, Out] double[] work, int len);
internal static extern int d_qr_solve_factored(int m, int n, int bn, double[] r, double[] b, double[] tau, [In, Out] double[] x);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int c_qr_solve_factored(int m, int n, int bn, Complex32[] r, Complex32[] b, Complex32[] tau, [In, Out] Complex32[] x, [In, Out] Complex32[] work, int len);
internal static extern int c_qr_solve_factored(int m, int n, int bn, Complex32[] r, Complex32[] b, Complex32[] tau, [In, Out] Complex32[] x);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int z_qr_solve_factored(int m, int n, int bn, Complex[] r, Complex[] b, Complex[] tau, [In, Out] Complex[] x, [In, Out] Complex[] work, int len);
internal static extern int z_qr_solve_factored(int m, int n, int bn, Complex[] r, Complex[] b, Complex[] tau, [In, Out] Complex[] x);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int s_svd_factor([MarshalAs(UnmanagedType.U1)] bool computeVectors, int m, int n, [In, Out] float[] a, [In, Out] float[] s, [In, Out] float[] u, [In, Out] float[] v, [In, Out] float[] work, int len);
internal static extern int s_svd_factor([MarshalAs(UnmanagedType.U1)] bool computeVectors, int m, int n, [In, Out] float[] a, [In, Out] float[] s, [In, Out] float[] u, [In, Out] float[] v);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int d_svd_factor([MarshalAs(UnmanagedType.U1)] bool computeVectors, int m, int n, [In, Out] double[] a, [In, Out] double[] s, [In, Out] double[] u, [In, Out] double[] v, [In, Out] double[] work, int len);
internal static extern int d_svd_factor([MarshalAs(UnmanagedType.U1)] bool computeVectors, int m, int n, [In, Out] double[] a, [In, Out] double[] s, [In, Out] double[] u, [In, Out] double[] v);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int c_svd_factor([MarshalAs(UnmanagedType.U1)] bool computeVectors, int m, int n, [In, Out] Complex32[] a, [In, Out] Complex32[] s, [In, Out] Complex32[] u, [In, Out] Complex32[] v, [In, Out] Complex32[] work, int len);
internal static extern int c_svd_factor([MarshalAs(UnmanagedType.U1)] bool computeVectors, int m, int n, [In, Out] Complex32[] a, [In, Out] Complex32[] s, [In, Out] Complex32[] u, [In, Out] Complex32[] v);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int z_svd_factor([MarshalAs(UnmanagedType.U1)] bool computeVectors, int m, int n, [In, Out] Complex[] a, [In, Out] Complex[] s, [In, Out] Complex[] u, [In, Out] Complex[] v, [In, Out] Complex[] work, int len);
internal static extern int z_svd_factor([MarshalAs(UnmanagedType.U1)] bool computeVectors, int m, int n, [In, Out] Complex[] a, [In, Out] Complex[] s, [In, Out] Complex[] u, [In, Out] Complex[] v);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int s_eigen([MarshalAs(UnmanagedType.U1)] bool isSymmetric, int n, [In] float[] a, [In, Out] float[] vectors, [In, Out] Complex[] values, [In, Out] float[] d);

493
src/Numerics/Providers/LinearAlgebra/OpenBlas/OpenBlasLinearAlgebraProvider.Complex.cs

@ -76,8 +76,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, rows * columns), "matrix");
}
var work = new double[rows];
return SafeNativeMethods.z_matrix_norm((byte)norm, rows, columns, matrix, work);
return SafeNativeMethods.z_matrix_norm((byte)norm, rows, columns, matrix);
}
/// <summary>
@ -229,7 +228,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
var k = transposeA == Transpose.DontTranspose ? columnsA : rowsA;
var l = transposeB == Transpose.DontTranspose ? rowsB : columnsB;
if (c.Length != m * n)
if (c.Length != m*n)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
@ -264,7 +263,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("ipiv");
}
if (data.Length != order * order)
if (data.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "data");
}
@ -274,7 +273,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
SafeNativeMethods.z_lu_factor(order, data, ipiv);
var info = SafeNativeMethods.z_lu_factor(order, data, ipiv);
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -291,82 +295,27 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("a");
}
if (a.Length != order * order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
var work = new Complex[order];
SafeNativeMethods.z_lu_inverse(order, a, work, work.Length);
}
/// <summary>
/// Computes the inverse of a previously factored matrix.
/// </summary>
/// <param name="a">The LU factored N by N matrix. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="ipiv">The pivot indices of <paramref name="a"/>.</param>
/// <remarks>This is equivalent to the GETRI LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void LUInverseFactored(Complex[] a, int order, int[] ipiv)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (ipiv == null)
{
throw new ArgumentNullException("ipiv");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
if (ipiv.Length != order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
var work = new Complex[order];
SafeNativeMethods.z_lu_inverse_factored(order, a, ipiv, work, order);
}
/// <summary>
/// Computes the inverse of matrix using LU factorization.
/// </summary>
/// <param name="a">The N by N matrix to invert. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is equivalent to the GETRF and GETRI LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void LUInverse(Complex[] a, int order, Complex[] work)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
var info = SafeNativeMethods.z_lu_inverse(order, a);
if (a.Length != order * order)
if (info == (int)NativeError.MemoryAllocation)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
throw new MemoryAllocationException();
}
if (work == null)
if (info < 0)
{
throw new ArgumentNullException("work");
throw new InvalidParameterException(Math.Abs(info));
}
if (work.Length < order)
if (info > 0)
{
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new SingularUMatrixException(info);
}
SafeNativeMethods.z_lu_inverse(order, a, work, work.Length);
}
/// <summary>
@ -375,12 +324,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
/// <param name="a">The LU factored N by N matrix. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="ipiv">The pivot indices of <paramref name="a"/>.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is equivalent to the GETRI LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void LUInverseFactored(Complex[] a, int order, int[] ipiv, Complex[] work)
public override void LUInverseFactored(Complex[] a, int order, int[] ipiv)
{
if (a == null)
{
@ -392,7 +338,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("ipiv");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
@ -402,17 +348,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
var info = SafeNativeMethods.z_lu_inverse_factored(order, a, ipiv);
if (work.Length < order)
if (info < 0)
{
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
SafeNativeMethods.z_lu_inverse_factored(order, a, ipiv, work, order);
if (info > 0)
{
throw new SingularUMatrixException(info);
}
}
/// <summary>
@ -431,12 +377,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("a");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
if (b.Length != columnsOfB * order)
if (b.Length != columnsOfB*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
@ -446,7 +392,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.z_lu_solve(order, columnsOfB, a, b);
var info = SafeNativeMethods.z_lu_solve(order, columnsOfB, a, b);
if (info == (int)NativeError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -471,7 +427,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("ipiv");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
@ -481,7 +437,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
if (b.Length != columnsOfB * order)
if (b.Length != columnsOfB*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
@ -491,7 +447,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.z_lu_solve_factored(order, columnsOfB, a, ipiv, b);
var info = SafeNativeMethods.z_lu_solve_factored(order, columnsOfB, a, ipiv, b);
if (info == (int)NativeError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -514,13 +480,18 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentMustBePositive, "order");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
var info = SafeNativeMethods.z_cholesky_factor(order, a);
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
if (info > 0)
{
throw new ArgumentException(Resources.ArgumentMatrixPositiveDefinite);
@ -549,7 +520,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("b");
}
if (b.Length != orderA * columnsB)
if (b.Length != orderA*columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
@ -559,7 +530,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.z_cholesky_solve(orderA, columnsB, a, b);
var info = SafeNativeMethods.z_cholesky_solve(orderA, columnsB, a, b);
if (info == (int)NativeError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -583,7 +564,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("b");
}
if (b.Length != orderA * columnsB)
if (b.Length != orderA*columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
@ -593,51 +574,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.z_cholesky_solve_factored(orderA, columnsB, a, b);
}
/// <summary>
/// Computes the QR factorization of A.
/// </summary>
/// <param name="r">On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void QRFactor(Complex[] r, int rowsR, int columnsR, Complex[] q, Complex[] tau)
{
if (r == null)
{
throw new ArgumentNullException("r");
}
if (q == null)
{
throw new ArgumentNullException("q");
}
var info = SafeNativeMethods.z_cholesky_solve_factored(orderA, columnsB, a, b);
if (r.Length != rowsR * columnsR)
if (info < 0)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r");
throw new InvalidParameterException(Math.Abs(info));
}
if (tau.Length < Math.Min(rowsR, columnsR))
{
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
if (q.Length != rowsR * rowsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * rowsR"), "q");
}
var work = new Complex[columnsR * Control.BlockSize];
SafeNativeMethods.z_qr_factor(rowsR, columnsR, r, tau, q, work, work.Length);
}
/// <summary>
@ -647,16 +589,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
/// it is overwritten with the R matrix of the QR factorization. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void QRFactor(Complex[] r, int rowsR, int columnsR, Complex[] q, Complex[] tau, Complex[] work)
public override void QRFactor(Complex[] r, int rowsR, int columnsR, Complex[] q, Complex[] tau)
{
if (r == null)
{
@ -668,12 +607,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (r.Length != rowsR * columnsR)
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r");
}
@ -683,18 +617,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
if (q.Length != rowsR * rowsR)
if (q.Length != rowsR*rowsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * rowsR"), "q");
}
if (work.Length < columnsR * Control.BlockSize)
var info = SafeNativeMethods.z_qr_factor(rowsR, columnsR, r, tau, q);
if (info < 0)
{
work[0] = columnsR * Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
SafeNativeMethods.z_qr_factor(rowsR, columnsR, r, tau, q, work, work.Length);
}
/// <summary>
@ -737,66 +670,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "columnsA * columnsA"), "r");
}
var work = new Complex[columnsA * Control.BlockSize];
SafeNativeMethods.z_qr_thin_factor(rowsA, columnsA, q, tau, r, work, work.Length);
}
/// <summary>
/// Computes the thin QR factorization of A where M &gt; N.
/// </summary>
/// <param name="q">On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the Q matrix of the QR factorization.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="r">On exit, A N by N matrix that holds the R matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void ThinQRFactor(Complex[] q, int rowsA, int columnsA, Complex[] r, Complex[] tau, Complex[] work)
{
if (r == null)
{
throw new ArgumentNullException("r");
}
if (q == null)
{
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("q");
}
if (q.Length != rowsA * columnsA)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "q");
}
if (tau.Length < Math.Min(rowsA, columnsA))
{
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
if (r.Length != columnsA * columnsA)
{
throw new ArgumentException(
string.Format(Resources.ArgumentArrayWrongLength, "columnsA * columnsA"), "r");
}
var info = SafeNativeMethods.z_qr_thin_factor(rowsA, columnsA, q, tau, r);
if (work.Length < columnsA * Control.BlockSize)
if (info < 0)
{
work[0] = columnsA * Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
SafeNativeMethods.z_qr_thin_factor(rowsA, columnsA, q, tau, r, work, work.Length);
}
/// <summary>
@ -812,27 +691,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolve(Complex[] a, int rows, int columns, Complex[] b, int columnsB, Complex[] x, QRMethod method = QRMethod.Full)
{
var work = new Complex[columns * Control.BlockSize];
QRSolve(a, rows, columns, b, columnsB, x, work, method);
}
/// <summary>
/// Solves A*X=B for X using QR factorization of A.
/// </summary>
/// <param name="a">The A matrix.</param>
/// <param name="rows">The number of rows in the A matrix.</param>
/// <param name="columns">The number of columns in the A matrix.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolve(Complex[] a, int rows, int columns, Complex[] b, int columnsB, Complex[] x, Complex[] work, QRMethod method = QRMethod.Full)
{
if (a == null)
{
@ -849,11 +707,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("x");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (a.Length != rows * columns)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
@ -874,56 +727,40 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.RowsLessThanColumns);
}
if (work.Length < 1)
var info = SafeNativeMethods.z_qr_solve(rows, columns, columnsB, a, b, x);
if (info == (int)NativeError.MemoryAllocation)
{
work[0] = rows * Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new MemoryAllocationException();
}
SafeNativeMethods.z_qr_solve(rows, columns, columnsB, a, b, x, work, work.Length);
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
/// <summary>
/// Solves A*X=B for X using a previously QR factored matrix.
/// </summary>
/// <param name="q">The Q matrix obtained by calling <see cref="QRFactor(Complex[],int,int,Complex[],Complex[])"/>.</param>
/// <param name="r">The R matrix obtained by calling <see cref="QRFactor(Complex[],int,int,Complex[],Complex[])"/>. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="tau">Contains additional information on Q. Only used for the native solver
/// and can be <c>null</c> for the managed provider.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolveFactored(Complex[] q, Complex[] r, int rowsR, int columnsR, Complex[] tau, Complex[] b, int columnsB, Complex[] x, QRMethod method = QRMethod.Full)
{
var work = new Complex[columnsR * Control.BlockSize];
QRSolveFactored(q, r, rowsR, columnsR, tau, b, columnsB, x, work, method);
if (info > 0)
{
throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient, "a");
}
}
/// <summary>
/// Solves A*X=B for X using a previously QR factored matrix.
/// </summary>
/// <param name="q">The Q matrix obtained by QR factor. This is only used for the managed provider and can be
/// <c>null</c> for the native provider. The native provider uses the Q portion stored in the R matrix.</param>
/// <param name="q">The Q matrix obtained by calling <see cref="QRFactor(Complex[],int,int,Complex[],Complex[])"/>.</param>
/// <param name="r">The R matrix obtained by calling <see cref="QRFactor(Complex[],int,int,Complex[],Complex[])"/>. </param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="tau">Contains additional information on Q. Only used for the native solver
/// and can be <c>null</c> for the managed provider.</param>
/// <param name="b">On entry the B matrix; on exit the X matrix.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="work">The work array - only used in the native provider. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolveFactored(Complex[] q, Complex[] r, int rowsA, int columnsA, Complex[] tau, Complex[] b, int columnsB, Complex[] x, Complex[] work, QRMethod method = QRMethod.Full)
public override void QRSolveFactored(Complex[] q, Complex[] r, int rowsA, int columnsA, Complex[] tau, Complex[] b, int columnsB, Complex[] x, QRMethod method = QRMethod.Full)
{
if (r == null)
{
@ -945,11 +782,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
int rowsQ, columnsQ, rowsR, columnsR;
if (method == QRMethod.Full)
{
@ -982,15 +814,19 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA * columnsB), "x");
}
if (work.Length < 1)
{
work[0] = rowsA * Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
if (method == QRMethod.Full)
{
SafeNativeMethods.z_qr_solve_factored(rowsA, columnsA, columnsB, r, b, tau, x, work, work.Length);
var info = SafeNativeMethods.z_qr_solve_factored(rowsA, columnsA, columnsB, r, b, tau, x);
if (info == (int)NativeError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
else
{
@ -1000,61 +836,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
}
}
/// <summary>
/// Computes the singular value decomposition of A.
/// </summary>
/// <param name="computeVectors">Compute the singular U and VT vectors or not.</param>
/// <param name="a">On entry, the M by N matrix to decompose. On exit, A may be overwritten.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="s">The singular values of A in ascending value.</param>
/// <param name="u">If <paramref name="computeVectors"/> is <c>true</c>, on exit U contains the left
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void SingularValueDecomposition(bool computeVectors, Complex[] a, int rowsA, int columnsA, Complex[] s, Complex[] u, Complex[] vt)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (s == null)
{
throw new ArgumentNullException("s");
}
if (u == null)
{
throw new ArgumentNullException("u");
}
if (vt == null)
{
throw new ArgumentNullException("vt");
}
if (u.Length != rowsA * rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
if (vt.Length != columnsA * columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
if (s.Length != Math.Min(rowsA, columnsA))
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
var work = new Complex[(2 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA)];
SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, work);
}
/// <summary>
/// Solves A*X=B for X using the singular value decomposition of A.
/// </summary>
@ -1081,24 +862,23 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("x");
}
if (b.Length != rowsA * columnsB)
if (b.Length != rowsA*columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
if (x.Length != columnsA * columnsB)
if (x.Length != columnsA*columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
var work = new Complex[(2 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA)];
var s = new Complex[Math.Min(rowsA, columnsA)];
var u = new Complex[rowsA * rowsA];
var vt = new Complex[columnsA * columnsA];
var u = new Complex[rowsA*rowsA];
var vt = new Complex[columnsA*columnsA];
var clone = new Complex[a.Length];
a.Copy(clone);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt, work);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt);
SvdSolveFactored(rowsA, columnsA, s, u, vt, b, columnsB, x);
}
@ -1114,12 +894,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <param name="work">The work array. For real matrices, the work array should be at least
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void SingularValueDecomposition(bool computeVectors, Complex[] a, int rowsA, int columnsA, Complex[] s, Complex[] u, Complex[] vt, Complex[] work)
public override void SingularValueDecomposition(bool computeVectors, Complex[] a, int rowsA, int columnsA, Complex[] s, Complex[] u, Complex[] vt)
{
if (a == null)
{
@ -1141,17 +918,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("vt");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (u.Length != rowsA * rowsA)
if (u.Length != rowsA*rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
if (vt.Length != columnsA * columnsA)
if (vt.Length != columnsA*columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
@ -1161,18 +933,19 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
if (work.Length == 0)
var info = SafeNativeMethods.z_svd_factor(computeVectors, rowsA, columnsA, a, s, u, vt);
if (info == (int) NativeError.MemoryAllocation)
{
throw new ArgumentException(Resources.ArgumentSingleDimensionArray, "work");
throw new MemoryAllocationException();
}
if (work.Length < (2 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA))
if (info < 0)
{
work[0] = (2 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA);
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
if (SafeNativeMethods.z_svd_factor(computeVectors, rowsA, columnsA, a, s, u, vt, work, work.Length) > 0)
if (info > 0)
{
throw new NonConvergenceException();
}
@ -1229,7 +1002,19 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order * order), "matrixD");
}
if (SafeNativeMethods.z_eigen(isSymmetric, order, matrix, matrixEv, vectorEv, matrixD) > 0)
var info = SafeNativeMethods.z_eigen(isSymmetric, order, matrix, matrixEv, vectorEv, matrixD);
if (info == (int)NativeError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
if (info > 0)
{
throw new NonConvergenceException();
}

486
src/Numerics/Providers/LinearAlgebra/OpenBlas/OpenBlasLinearAlgebraProvider.Complex32.cs

@ -76,8 +76,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, rows * columns), "matrix");
}
var work = new float[rows];
return SafeNativeMethods.c_matrix_norm((byte)norm, rows, columns, matrix, work);
return SafeNativeMethods.c_matrix_norm((byte)norm, rows, columns, matrix);
}
/// <summary>
@ -229,7 +228,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
var k = transposeA == Transpose.DontTranspose ? columnsA : rowsA;
var l = transposeB == Transpose.DontTranspose ? rowsB : columnsB;
if (c.Length != m * n)
if (c.Length != m*n)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
@ -264,7 +263,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("ipiv");
}
if (data.Length != order * order)
if (data.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "data");
}
@ -274,7 +273,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
SafeNativeMethods.c_lu_factor(order, data, ipiv);
var info = SafeNativeMethods.c_lu_factor(order, data, ipiv);
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -291,82 +295,27 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("a");
}
if (a.Length != order * order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
var work = new Complex32[order];
SafeNativeMethods.c_lu_inverse(order, a, work, work.Length);
}
/// <summary>
/// Computes the inverse of a previously factored matrix.
/// </summary>
/// <param name="a">The LU factored N by N matrix. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="ipiv">The pivot indices of <paramref name="a"/>.</param>
/// <remarks>This is equivalent to the GETRI LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void LUInverseFactored(Complex32[] a, int order, int[] ipiv)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (ipiv == null)
{
throw new ArgumentNullException("ipiv");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
if (ipiv.Length != order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
var work = new Complex32[order];
SafeNativeMethods.c_lu_inverse_factored(order, a, ipiv, work, order);
}
/// <summary>
/// Computes the inverse of matrix using LU factorization.
/// </summary>
/// <param name="a">The N by N matrix to invert. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is equivalent to the GETRF and GETRI LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void LUInverse(Complex32[] a, int order, Complex32[] work)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
var info = SafeNativeMethods.c_lu_inverse(order, a);
if (a.Length != order * order)
if (info == (int)NativeError.MemoryAllocation)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
throw new MemoryAllocationException();
}
if (work == null)
if (info < 0)
{
throw new ArgumentNullException("work");
throw new InvalidParameterException(Math.Abs(info));
}
if (work.Length < order)
if (info > 0)
{
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new SingularUMatrixException(info);
}
SafeNativeMethods.c_lu_inverse(order, a, work, work.Length);
}
/// <summary>
@ -375,12 +324,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
/// <param name="a">The LU factored N by N matrix. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="ipiv">The pivot indices of <paramref name="a"/>.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is equivalent to the GETRI LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void LUInverseFactored(Complex32[] a, int order, int[] ipiv, Complex32[] work)
public override void LUInverseFactored(Complex32[] a, int order, int[] ipiv)
{
if (a == null)
{
@ -392,7 +338,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("ipiv");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
@ -402,17 +348,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
var info = SafeNativeMethods.c_lu_inverse_factored(order, a, ipiv);
if (work.Length < order)
if (info < 0)
{
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
SafeNativeMethods.c_lu_inverse_factored(order, a, ipiv, work, order);
if (info > 0)
{
throw new SingularUMatrixException(info);
}
}
/// <summary>
@ -431,12 +377,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("a");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
if (b.Length != columnsOfB * order)
if (b.Length != columnsOfB*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
@ -446,7 +392,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.c_lu_solve(order, columnsOfB, a, b);
var info = SafeNativeMethods.c_lu_solve(order, columnsOfB, a, b);
if (info == (int)NativeError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -471,7 +427,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("ipiv");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
@ -481,7 +437,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
if (b.Length != columnsOfB * order)
if (b.Length != columnsOfB*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
@ -491,7 +447,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.c_lu_solve_factored(order, columnsOfB, a, ipiv, b);
var info = SafeNativeMethods.c_lu_solve_factored(order, columnsOfB, a, ipiv, b);
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -514,13 +475,18 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentMustBePositive, "order");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
var info = SafeNativeMethods.c_cholesky_factor(order, a);
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
if (info > 0)
{
throw new ArgumentException(Resources.ArgumentMatrixPositiveDefinite);
@ -549,7 +515,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("b");
}
if (b.Length != orderA * columnsB)
if (b.Length != orderA*columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
@ -559,7 +525,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.c_cholesky_solve(orderA, columnsB, a, b);
var info = SafeNativeMethods.c_cholesky_solve(orderA, columnsB, a, b);
if (info == (int)NativeError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -583,7 +559,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("b");
}
if (b.Length != orderA * columnsB)
if (b.Length != orderA*columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
@ -593,51 +569,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.c_cholesky_solve_factored(orderA, columnsB, a, b);
}
/// <summary>
/// Computes the QR factorization of A.
/// </summary>
/// <param name="r">On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void QRFactor(Complex32[] r, int rowsR, int columnsR, Complex32[] q, Complex32[] tau)
{
if (r == null)
{
throw new ArgumentNullException("r");
}
if (q == null)
{
throw new ArgumentNullException("q");
}
if (r.Length != rowsR * columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r");
}
var info = SafeNativeMethods.c_cholesky_solve_factored(orderA, columnsB, a, b);
if (tau.Length < Math.Min(rowsR, columnsR))
if (info < 0)
{
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
throw new InvalidParameterException(Math.Abs(info));
}
if (q.Length != rowsR * rowsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * rowsR"), "q");
}
var work = new Complex32[columnsR * Control.BlockSize];
SafeNativeMethods.c_qr_factor(rowsR, columnsR, r, tau, q, work, work.Length);
}
/// <summary>
@ -647,16 +584,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
/// it is overwritten with the R matrix of the QR factorization. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void QRFactor(Complex32[] r, int rowsR, int columnsR, Complex32[] q, Complex32[] tau, Complex32[] work)
public override void QRFactor(Complex32[] r, int rowsR, int columnsR, Complex32[] q, Complex32[] tau)
{
if (r == null)
{
@ -668,12 +602,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (r.Length != rowsR * columnsR)
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r");
}
@ -683,18 +612,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
if (q.Length != rowsR * rowsR)
if (q.Length != rowsR*rowsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * rowsR"), "q");
}
if (work.Length < columnsR * Control.BlockSize)
var info = SafeNativeMethods.c_qr_factor(rowsR, columnsR, r, tau, q);
if (info < 0)
{
work[0] = columnsR * Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
SafeNativeMethods.c_qr_factor(rowsR, columnsR, r, tau, q, work, work.Length);
}
/// <summary>
@ -737,66 +665,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "columnsA * columnsA"), "r");
}
var work = new Complex32[columnsA * Control.BlockSize];
SafeNativeMethods.c_qr_thin_factor(rowsA, columnsA, q, tau, r, work, work.Length);
}
var info = SafeNativeMethods.c_qr_thin_factor(rowsA, columnsA, q, tau, r);
/// <summary>
/// Computes the thin QR factorization of A where M &gt; N.
/// </summary>
/// <param name="q">On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the Q matrix of the QR factorization.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="r">On exit, A N by N matrix that holds the R matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void ThinQRFactor(Complex32[] q, int rowsA, int columnsA, Complex32[] r, Complex32[] tau, Complex32[] work)
{
if (r == null)
{
throw new ArgumentNullException("r");
}
if (q == null)
if (info < 0)
{
throw new ArgumentNullException("q");
throw new InvalidParameterException(Math.Abs(info));
}
if (work == null)
{
throw new ArgumentNullException("q");
}
if (q.Length != rowsA * columnsA)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "q");
}
if (tau.Length < Math.Min(rowsA, columnsA))
{
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
if (r.Length != columnsA * columnsA)
{
throw new ArgumentException(
string.Format(Resources.ArgumentArrayWrongLength, "columnsA * columnsA"), "r");
}
if (work.Length < columnsA * Control.BlockSize)
{
work[0] = columnsA * Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
SafeNativeMethods.c_qr_thin_factor(rowsA, columnsA, q, tau, r, work, work.Length);
}
/// <summary>
@ -812,27 +686,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolve(Complex32[] a, int rows, int columns, Complex32[] b, int columnsB, Complex32[] x, QRMethod method = QRMethod.Full)
{
var work = new Complex32[columns * Control.BlockSize];
QRSolve(a, rows, columns, b, columnsB, x, work, method);
}
/// <summary>
/// Solves A*X=B for X using QR factorization of A.
/// </summary>
/// <param name="a">The A matrix.</param>
/// <param name="rows">The number of rows in the A matrix.</param>
/// <param name="columns">The number of columns in the A matrix.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolve(Complex32[] a, int rows, int columns, Complex32[] b, int columnsB, Complex32[] x, Complex32[] work, QRMethod method = QRMethod.Full)
{
if (a == null)
{
@ -849,11 +702,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("x");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (a.Length != rows * columns)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
@ -874,56 +722,40 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.RowsLessThanColumns);
}
if (work.Length < 1)
var info = SafeNativeMethods.c_qr_solve(rows, columns, columnsB, a, b, x);
if (info == (int)NativeError.MemoryAllocation)
{
work[0] = rows * Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new MemoryAllocationException();
}
SafeNativeMethods.c_qr_solve(rows, columns, columnsB, a, b, x, work, work.Length);
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
/// <summary>
/// Solves A*X=B for X using a previously QR factored matrix.
/// </summary>
/// <param name="q">The Q matrix obtained by calling <see cref="QRFactor(Complex32[],int,int,Complex32[],Complex32[])"/>.</param>
/// <param name="r">The R matrix obtained by calling <see cref="QRFactor(Complex32[],int,int,Complex32[],Complex32[])"/>. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="tau">Contains additional information on Q. Only used for the native solver
/// and can be <c>null</c> for the managed provider.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolveFactored(Complex32[] q, Complex32[] r, int rowsR, int columnsR, Complex32[] tau, Complex32[] b, int columnsB, Complex32[] x, QRMethod method = QRMethod.Full)
{
var work = new Complex32[columnsR * Control.BlockSize];
QRSolveFactored(q, r, rowsR, columnsR, tau, b, columnsB, x, work, method);
if (info > 0)
{
throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient, "a");
}
}
/// <summary>
/// Solves A*X=B for X using a previously QR factored matrix.
/// </summary>
/// <param name="q">The Q matrix obtained by QR factor. This is only used for the managed provider and can be
/// <c>null</c> for the native provider. The native provider uses the Q portion stored in the R matrix.</param>
/// <param name="q">The Q matrix obtained by calling <see cref="QRFactor(Complex32[],int,int,Complex32[],Complex32[])"/>.</param>
/// <param name="r">The R matrix obtained by calling <see cref="QRFactor(Complex32[],int,int,Complex32[],Complex32[])"/>. </param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="tau">Contains additional information on Q. Only used for the native solver
/// and can be <c>null</c> for the managed provider.</param>
/// <param name="b">On entry the B matrix; on exit the X matrix.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="work">The work array - only used in the native provider. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolveFactored(Complex32[] q, Complex32[] r, int rowsA, int columnsA, Complex32[] tau, Complex32[] b, int columnsB, Complex32[] x, Complex32[] work, QRMethod method = QRMethod.Full)
public override void QRSolveFactored(Complex32[] q, Complex32[] r, int rowsA, int columnsA, Complex32[] tau, Complex32[] b, int columnsB, Complex32[] x, QRMethod method = QRMethod.Full)
{
if (r == null)
{
@ -945,11 +777,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
int rowsQ, columnsQ, rowsR, columnsR;
if (method == QRMethod.Full)
{
@ -982,15 +809,19 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA * columnsB), "x");
}
if (work.Length < 1)
{
work[0] = rowsA * Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
if (method == QRMethod.Full)
{
SafeNativeMethods.c_qr_solve_factored(rowsA, columnsA, columnsB, r, b, tau, x, work, work.Length);
var info = SafeNativeMethods.c_qr_solve_factored(rowsA, columnsA, columnsB, r, b, tau, x);
if (info == (int)NativeError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
else
{
@ -1000,61 +831,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
}
}
/// <summary>
/// Computes the singular value decomposition of A.
/// </summary>
/// <param name="computeVectors">Compute the singular U and VT vectors or not.</param>
/// <param name="a">On entry, the M by N matrix to decompose. On exit, A may be overwritten.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="s">The singular values of A in ascending value.</param>
/// <param name="u">If <paramref name="computeVectors"/> is <c>true</c>, on exit U contains the left
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void SingularValueDecomposition(bool computeVectors, Complex32[] a, int rowsA, int columnsA, Complex32[] s, Complex32[] u, Complex32[] vt)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (s == null)
{
throw new ArgumentNullException("s");
}
if (u == null)
{
throw new ArgumentNullException("u");
}
if (vt == null)
{
throw new ArgumentNullException("vt");
}
if (u.Length != rowsA * rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
if (vt.Length != columnsA * columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
if (s.Length != Math.Min(rowsA, columnsA))
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
var work = new Complex32[(2 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA)];
SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, work);
}
/// <summary>
/// Solves A*X=B for X using the singular value decomposition of A.
/// </summary>
@ -1081,24 +857,23 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("x");
}
if (b.Length != rowsA * columnsB)
if (b.Length != rowsA*columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
if (x.Length != columnsA * columnsB)
if (x.Length != columnsA*columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
var work = new Complex32[(2 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA)];
var s = new Complex32[Math.Min(rowsA, columnsA)];
var u = new Complex32[rowsA * rowsA];
var vt = new Complex32[columnsA * columnsA];
var u = new Complex32[rowsA*rowsA];
var vt = new Complex32[columnsA*columnsA];
var clone = new Complex32[a.Length];
a.Copy(clone);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt, work);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt);
SvdSolveFactored(rowsA, columnsA, s, u, vt, b, columnsB, x);
}
@ -1114,12 +889,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <param name="work">The work array. For real matrices, the work array should be at least
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void SingularValueDecomposition(bool computeVectors, Complex32[] a, int rowsA, int columnsA, Complex32[] s, Complex32[] u, Complex32[] vt, Complex32[] work)
public override void SingularValueDecomposition(bool computeVectors, Complex32[] a, int rowsA, int columnsA, Complex32[] s, Complex32[] u, Complex32[] vt)
{
if (a == null)
{
@ -1141,11 +913,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("vt");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (u.Length != rowsA * rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
@ -1161,18 +928,19 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
if (work.Length == 0)
var info = SafeNativeMethods.c_svd_factor(computeVectors, rowsA, columnsA, a, s, u, vt);
if (info == (int)NativeError.MemoryAllocation)
{
throw new ArgumentException(Resources.ArgumentSingleDimensionArray, "work");
throw new MemoryAllocationException();
}
if (work.Length < (2 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA))
if (info < 0)
{
work[0] = (2 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA);
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
if (SafeNativeMethods.c_svd_factor(computeVectors, rowsA, columnsA, a, s, u, vt, work, work.Length) > 0)
if (info > 0)
{
throw new NonConvergenceException();
}
@ -1226,10 +994,22 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
if (matrixD.Length != order * order)
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order * order), "matrixD");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, order * order), "matrixD");
}
if (SafeNativeMethods.c_eigen(isSymmetric, order, matrix, matrixEv, vectorEv, matrixD) > 0)
var info = SafeNativeMethods.c_eigen(isSymmetric, order, matrix, matrixEv, vectorEv, matrixD);
if (info == (int)NativeError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
if (info > 0)
{
throw new NonConvergenceException();
}

505
src/Numerics/Providers/LinearAlgebra/OpenBlas/OpenBlasLinearAlgebraProvider.Double.cs

@ -76,8 +76,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, rows * columns), "matrix");
}
var work = new double[rows];
return SafeNativeMethods.d_matrix_norm((byte)norm, rows, columns, matrix, work);
return SafeNativeMethods.d_matrix_norm((byte)norm, rows, columns, matrix);
}
/// <summary>
@ -229,7 +228,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
var k = transposeA == Transpose.DontTranspose ? columnsA : rowsA;
var l = transposeB == Transpose.DontTranspose ? rowsB : columnsB;
if (c.Length != m * n)
if (c.Length != m*n)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
@ -264,7 +263,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("ipiv");
}
if (data.Length != order * order)
if (data.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "data");
}
@ -274,7 +273,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
SafeNativeMethods.d_lu_factor(order, data, ipiv);
var info = SafeNativeMethods.d_lu_factor(order, data, ipiv);
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -291,82 +295,27 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("a");
}
if (a.Length != order * order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
var work = new double[order];
SafeNativeMethods.d_lu_inverse(order, a, work, work.Length);
}
/// <summary>
/// Computes the inverse of a previously factored matrix.
/// </summary>
/// <param name="a">The LU factored N by N matrix. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="ipiv">The pivot indices of <paramref name="a"/>.</param>
/// <remarks>This is equivalent to the GETRI LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void LUInverseFactored(double[] a, int order, int[] ipiv)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (ipiv == null)
{
throw new ArgumentNullException("ipiv");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
if (ipiv.Length != order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
var work = new double[order];
SafeNativeMethods.d_lu_inverse_factored(order, a, ipiv, work, order);
}
/// <summary>
/// Computes the inverse of matrix using LU factorization.
/// </summary>
/// <param name="a">The N by N matrix to invert. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is equivalent to the GETRF and GETRI LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void LUInverse(double[] a, int order, double[] work)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
var info = SafeNativeMethods.d_lu_inverse(order, a);
if (a.Length != order * order)
if (info == (int)NativeError.MemoryAllocation)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
throw new MemoryAllocationException();
}
if (work == null)
if (info < 0)
{
throw new ArgumentNullException("work");
throw new InvalidParameterException(Math.Abs(info));
}
if (work.Length < order)
if (info > 0)
{
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new SingularUMatrixException(info);
}
SafeNativeMethods.d_lu_inverse(order, a, work, work.Length);
}
/// <summary>
@ -375,12 +324,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
/// <param name="a">The LU factored N by N matrix. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="ipiv">The pivot indices of <paramref name="a"/>.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is equivalent to the GETRI LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void LUInverseFactored(double[] a, int order, int[] ipiv, double[] work)
public override void LUInverseFactored(double[] a, int order, int[] ipiv)
{
if (a == null)
{
@ -392,7 +338,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("ipiv");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
@ -402,17 +348,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
var info = SafeNativeMethods.d_lu_inverse_factored(order, a, ipiv);
if (work.Length < order)
if (info < 0)
{
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
SafeNativeMethods.d_lu_inverse_factored(order, a, ipiv, work, order);
if (info > 0)
{
throw new SingularUMatrixException(info);
}
}
/// <summary>
@ -431,12 +377,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("a");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
if (b.Length != columnsOfB * order)
if (b.Length != columnsOfB*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
@ -446,7 +392,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.d_lu_solve(order, columnsOfB, a, b);
var info = SafeNativeMethods.d_lu_solve(order, columnsOfB, a, b);
if (info == (int)NativeError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -471,7 +427,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("ipiv");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
@ -481,7 +437,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
if (b.Length != columnsOfB * order)
if (b.Length != columnsOfB*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
@ -491,7 +447,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.d_lu_solve_factored(order, columnsOfB, a, ipiv, b);
var info = SafeNativeMethods.d_lu_solve_factored(order, columnsOfB, a, ipiv, b);
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -514,13 +475,23 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentMustBePositive, "order");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
var info = SafeNativeMethods.d_cholesky_factor(order, a);
if (info == (int)NativeError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
if (info > 0)
{
throw new ArgumentException(Resources.ArgumentMatrixPositiveDefinite);
@ -549,7 +520,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("b");
}
if (b.Length != orderA * columnsB)
if (b.Length != orderA*columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
@ -559,7 +530,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.d_cholesky_solve(orderA, columnsB, a, b);
var info = SafeNativeMethods.d_cholesky_solve(orderA, columnsB, a, b);
if (info == (int)NativeError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -583,7 +564,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("b");
}
if (b.Length != orderA * columnsB)
if (b.Length != orderA*columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
@ -593,51 +574,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.d_cholesky_solve_factored(orderA, columnsB, a, b);
}
/// <summary>
/// Computes the QR factorization of A.
/// </summary>
/// <param name="r">On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void QRFactor(double[] r, int rowsR, int columnsR, double[] q, double[] tau)
{
if (r == null)
{
throw new ArgumentNullException("r");
}
if (q == null)
{
throw new ArgumentNullException("q");
}
var info = SafeNativeMethods.d_cholesky_solve_factored(orderA, columnsB, a, b);
if (r.Length != rowsR * columnsR)
if (info < 0)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r");
throw new InvalidParameterException(Math.Abs(info));
}
if (tau.Length < Math.Min(rowsR, columnsR))
{
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
if (q.Length != rowsR * rowsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * rowsR"), "q");
}
var work = new double[columnsR * Control.BlockSize];
SafeNativeMethods.d_qr_factor(rowsR, columnsR, r, tau, q, work, work.Length);
}
/// <summary>
@ -647,16 +589,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
/// it is overwritten with the R matrix of the QR factorization. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void QRFactor(double[] r, int rowsR, int columnsR, double[] q, double[] tau, double[] work)
public override void QRFactor(double[] r, int rowsR, int columnsR, double[] q, double[] tau)
{
if (r == null)
{
@ -668,12 +607,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (r.Length != rowsR * columnsR)
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r");
}
@ -683,18 +617,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
if (q.Length != rowsR * rowsR)
if (q.Length != rowsR*rowsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * rowsR"), "q");
}
if (work.Length < columnsR * Control.BlockSize)
var info = SafeNativeMethods.d_qr_factor(rowsR, columnsR, r, tau, q);
if (info < 0)
{
work[0] = columnsR * Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
SafeNativeMethods.d_qr_factor(rowsR, columnsR, r, tau, q, work, work.Length);
}
/// <summary>
@ -722,7 +655,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("q");
}
if (q.Length != rowsA * columnsA)
if (q.Length != rowsA*columnsA)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "q");
}
@ -732,71 +665,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
if (r.Length != columnsA * columnsA)
if (r.Length != columnsA*columnsA)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "columnsA * columnsA"), "r");
}
var work = new double[columnsA * Control.BlockSize];
SafeNativeMethods.d_qr_thin_factor(rowsA, columnsA, q, tau, r, work, work.Length);
}
/// <summary>
/// Computes the thin QR factorization of A where M &gt; N.
/// </summary>
/// <param name="q">On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the Q matrix of the QR factorization.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="r">On exit, A N by N matrix that holds the R matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void ThinQRFactor(double[] q, int rowsA, int columnsA, double[] r, double[] tau, double[] work)
{
if (r == null)
{
throw new ArgumentNullException("r");
}
if (q == null)
{
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("q");
}
if (q.Length != rowsA * columnsA)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "q");
}
if (tau.Length < Math.Min(rowsA, columnsA))
{
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
if (r.Length != columnsA * columnsA)
{
throw new ArgumentException(
string.Format(Resources.ArgumentArrayWrongLength, "columnsA * columnsA"), "r");
}
var info = SafeNativeMethods.d_qr_thin_factor(rowsA, columnsA, q, tau, r);
if (work.Length < columnsA * Control.BlockSize)
if (info < 0)
{
work[0] = columnsA * Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
SafeNativeMethods.d_qr_thin_factor(rowsA, columnsA, q, tau, r, work, work.Length);
}
/// <summary>
@ -812,27 +691,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolve(double[] a, int rows, int columns, double[] b, int columnsB, double[] x, QRMethod method = QRMethod.Full)
{
var work = new double[columns * Control.BlockSize];
QRSolve(a, rows, columns, b, columnsB, x, work, method);
}
/// <summary>
/// Solves A*X=B for X using QR factorization of A.
/// </summary>
/// <param name="a">The A matrix.</param>
/// <param name="rows">The number of rows in the A matrix.</param>
/// <param name="columns">The number of columns in the A matrix.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolve(double[] a, int rows, int columns, double[] b, int columnsB, double[] x, double[] work, QRMethod method = QRMethod.Full)
{
if (a == null)
{
@ -849,11 +707,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("x");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (a.Length != rows * columns)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
@ -874,56 +727,40 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.RowsLessThanColumns);
}
if (work.Length < 1)
var info = SafeNativeMethods.d_qr_solve(rows, columns, columnsB, a, b, x);
if (info == (int)NativeError.MemoryAllocation)
{
work[0] = rows * Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new MemoryAllocationException();
}
SafeNativeMethods.d_qr_solve(rows, columns, columnsB, a, b, x, work, work.Length);
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
/// <summary>
/// Solves A*X=B for X using a previously QR factored matrix.
/// </summary>
/// <param name="q">The Q matrix obtained by calling <see cref="QRFactor(double[],int,int,double[],double[])"/>.</param>
/// <param name="r">The R matrix obtained by calling <see cref="QRFactor(double[],int,int,double[],double[])"/>. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="tau">Contains additional information on Q. Only used for the native solver
/// and can be <c>null</c> for the managed provider.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolveFactored(double[] q, double[] r, int rowsR, int columnsR, double[] tau, double[] b, int columnsB, double[] x, QRMethod method = QRMethod.Full)
{
var work = new double[columnsR * Control.BlockSize];
QRSolveFactored(q, r, rowsR, columnsR, tau, b, columnsB, x, work, method);
if (info > 0)
{
throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient, "a");
}
}
/// <summary>
/// Solves A*X=B for X using a previously QR factored matrix.
/// </summary>
/// <param name="q">The Q matrix obtained by QR factor. This is only used for the managed provider and can be
/// <c>null</c> for the native provider. The native provider uses the Q portion stored in the R matrix.</param>
/// <param name="q">The Q matrix obtained by calling <see cref="QRFactor(double[],int,int,double[],double[])"/>.</param>
/// <param name="r">The R matrix obtained by calling <see cref="QRFactor(double[],int,int,double[],double[])"/>. </param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="tau">Contains additional information on Q. Only used for the native solver
/// and can be <c>null</c> for the managed provider.</param>
/// <param name="b">On entry the B matrix; on exit the X matrix.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="work">The work array - only used in the native provider. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolveFactored(double[] q, double[] r, int rowsA, int columnsA, double[] tau, double[] b, int columnsB, double[] x, double[] work, QRMethod method = QRMethod.Full)
public override void QRSolveFactored(double[] q, double[] r, int rowsA, int columnsA, double[] tau, double[] b, int columnsB, double[] x, QRMethod method = QRMethod.Full)
{
if (r == null)
{
@ -945,11 +782,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
int rowsQ, columnsQ, rowsR, columnsR;
if (method == QRMethod.Full)
{
@ -982,15 +814,19 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA * columnsB), "x");
}
if (work.Length < 1)
{
work[0] = rowsA * Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
if (method == QRMethod.Full)
{
SafeNativeMethods.d_qr_solve_factored(rowsA, columnsA, columnsB, r, b, tau, x, work, work.Length);
var info = SafeNativeMethods.d_qr_solve_factored(rowsA, columnsA, columnsB, r, b, tau, x);
if (info == (int)NativeError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
else
{
@ -1000,61 +836,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
}
}
/// <summary>
/// Computes the singular value decomposition of A.
/// </summary>
/// <param name="computeVectors">Compute the singular U and VT vectors or not.</param>
/// <param name="a">On entry, the M by N matrix to decompose. On exit, A may be overwritten.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="s">The singular values of A in ascending value.</param>
/// <param name="u">If <paramref name="computeVectors"/> is <c>true</c>, on exit U contains the left
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void SingularValueDecomposition(bool computeVectors, double[] a, int rowsA, int columnsA, double[] s, double[] u, double[] vt)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (s == null)
{
throw new ArgumentNullException("s");
}
if (u == null)
{
throw new ArgumentNullException("u");
}
if (vt == null)
{
throw new ArgumentNullException("vt");
}
if (u.Length != rowsA * rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
if (vt.Length != columnsA * columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
if (s.Length != Math.Min(rowsA, columnsA))
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
var work = new double[Math.Max((3 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA), 5 * Math.Min(rowsA, columnsA))];
SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, work);
}
/// <summary>
/// Solves A*X=B for X using the singular value decomposition of A.
/// </summary>
@ -1081,24 +862,23 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("x");
}
if (b.Length != rowsA * columnsB)
if (b.Length != rowsA*columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
if (x.Length != columnsA * columnsB)
if (x.Length != columnsA*columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
var work = new double[Math.Max((3 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA), 5 * Math.Min(rowsA, columnsA))];
var s = new double[Math.Min(rowsA, columnsA)];
var u = new double[rowsA * rowsA];
var vt = new double[columnsA * columnsA];
var u = new double[rowsA*rowsA];
var vt = new double[columnsA*columnsA];
var clone = new double[a.Length];
a.Copy(clone);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt, work);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt);
SvdSolveFactored(rowsA, columnsA, s, u, vt, b, columnsB, x);
}
@ -1114,12 +894,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <param name="work">The work array. For real matrices, the work array should be at least
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void SingularValueDecomposition(bool computeVectors, double[] a, int rowsA, int columnsA, double[] s, double[] u, double[] vt, double[] work)
public override void SingularValueDecomposition(bool computeVectors, double[] a, int rowsA, int columnsA, double[] s, double[] u, double[] vt)
{
if (a == null)
{
@ -1141,11 +918,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("vt");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (u.Length != rowsA * rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
@ -1161,18 +933,19 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
if (work.Length == 0)
var info = SafeNativeMethods.d_svd_factor(computeVectors, rowsA, columnsA, a, s, u, vt);
if (info == (int)NativeError.MemoryAllocation)
{
throw new ArgumentException(Resources.ArgumentSingleDimensionArray, "work");
throw new MemoryAllocationException();
}
if (work.Length < Math.Max((3 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA), 5 * Math.Min(rowsA, columnsA)))
if (info < 0)
{
work[0] = Math.Max((3 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA), 5 * Math.Min(rowsA, columnsA));
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
if (SafeNativeMethods.d_svd_factor(computeVectors, rowsA, columnsA, a, s, u, vt, work, work.Length) > 0)
if (info > 0)
{
throw new NonConvergenceException();
}
@ -1194,9 +967,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("matrix");
}
if (matrix.Length != order * order)
if (matrix.Length != order*order)
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order * order), "matrix");
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order*order), "matrix");
}
if (matrixEv == null)
@ -1204,9 +977,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("matrixEv");
}
if (matrixEv.Length != order * order)
if (matrixEv.Length != order*order)
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order * order), "matrixEv");
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order*order), "matrixEv");
}
if (vectorEv == null)
@ -1224,12 +997,24 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("matrixD");
}
if (matrixD.Length != order * order)
if (matrixD.Length != order*order)
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order * order), "matrixD");
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order*order), "matrixD");
}
if (SafeNativeMethods.d_eigen(isSymmetric, order, matrix, matrixEv, vectorEv, matrixD) > 0)
var info = SafeNativeMethods.d_eigen(isSymmetric, order, matrix, matrixEv, vectorEv, matrixD);
if (info == (int)NativeError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
if (info > 0)
{
throw new NonConvergenceException();
}

500
src/Numerics/Providers/LinearAlgebra/OpenBlas/OpenBlasLinearAlgebraProvider.Single.cs

@ -76,8 +76,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, rows * columns), "matrix");
}
var work = new float[rows];
return SafeNativeMethods.s_matrix_norm((byte)norm, rows, columns, matrix, work);
return SafeNativeMethods.s_matrix_norm((byte)norm, rows, columns, matrix);
}
/// <summary>
@ -229,7 +228,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
var k = transposeA == Transpose.DontTranspose ? columnsA : rowsA;
var l = transposeB == Transpose.DontTranspose ? rowsB : columnsB;
if (c.Length != m * n)
if (c.Length != m*n)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
@ -264,7 +263,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("ipiv");
}
if (data.Length != order * order)
if (data.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "data");
}
@ -274,7 +273,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
SafeNativeMethods.s_lu_factor(order, data, ipiv);
var info = SafeNativeMethods.s_lu_factor(order, data, ipiv);
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -291,82 +295,27 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("a");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
var work = new float[order];
SafeNativeMethods.s_lu_inverse(order, a, work, work.Length);
}
/// <summary>
/// Computes the inverse of a previously factored matrix.
/// </summary>
/// <param name="a">The LU factored N by N matrix. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="ipiv">The pivot indices of <paramref name="a"/>.</param>
/// <remarks>This is equivalent to the GETRI LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void LUInverseFactored(float[] a, int order, int[] ipiv)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (ipiv == null)
{
throw new ArgumentNullException("ipiv");
}
var info = SafeNativeMethods.s_lu_inverse(order, a);
if (a.Length != order * order)
if (info == (int)NativeError.MemoryAllocation)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
throw new MemoryAllocationException();
}
if (ipiv.Length != order)
if (info < 0)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
throw new InvalidParameterException(Math.Abs(info));
}
var work = new float[order];
SafeNativeMethods.s_lu_inverse_factored(order, a, ipiv, work, order);
}
/// <summary>
/// Computes the inverse of matrix using LU factorization.
/// </summary>
/// <param name="a">The N by N matrix to invert. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is equivalent to the GETRF and GETRI LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void LUInverse(float[] a, int order, float[] work)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (a.Length != order * order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (work.Length < order)
if (info > 0)
{
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new SingularUMatrixException(info);
}
SafeNativeMethods.s_lu_inverse(order, a, work, work.Length);
}
/// <summary>
@ -375,12 +324,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
/// <param name="a">The LU factored N by N matrix. Contains the inverse On exit.</param>
/// <param name="order">The order of the square matrix <paramref name="a"/>.</param>
/// <param name="ipiv">The pivot indices of <paramref name="a"/>.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is equivalent to the GETRI LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void LUInverseFactored(float[] a, int order, int[] ipiv, float[] work)
public override void LUInverseFactored(float[] a, int order, int[] ipiv)
{
if (a == null)
{
@ -392,7 +338,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("ipiv");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
@ -402,17 +348,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
var info = SafeNativeMethods.s_lu_inverse_factored(order, a, ipiv);
if (work.Length < order)
if (info < 0)
{
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
SafeNativeMethods.s_lu_inverse_factored(order, a, ipiv, work, order);
if (info > 0)
{
throw new SingularUMatrixException(info);
}
}
/// <summary>
@ -431,12 +377,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("a");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
if (b.Length != columnsOfB * order)
if (b.Length != columnsOfB*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
@ -446,7 +392,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.s_lu_solve(order, columnsOfB, a, b);
var info = SafeNativeMethods.s_lu_solve(order, columnsOfB, a, b);
if (info == (int)NativeError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -471,7 +427,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("ipiv");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
@ -481,7 +437,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
if (b.Length != columnsOfB * order)
if (b.Length != columnsOfB*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
@ -491,7 +447,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.s_lu_solve_factored(order, columnsOfB, a, ipiv, b);
var info = SafeNativeMethods.s_lu_solve_factored(order, columnsOfB, a, ipiv, b);
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -514,13 +475,18 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentMustBePositive, "order");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
var info = SafeNativeMethods.s_cholesky_factor(order, a);
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
if (info > 0)
{
throw new ArgumentException(Resources.ArgumentMatrixPositiveDefinite);
@ -549,7 +515,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("b");
}
if (b.Length != orderA * columnsB)
if (b.Length != orderA*columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
@ -559,7 +525,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.s_cholesky_solve(orderA, columnsB, a, b);
var info = SafeNativeMethods.s_cholesky_solve(orderA, columnsB, a, b);
if (info == (int)NativeError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
/// <summary>
@ -583,7 +559,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("b");
}
if (b.Length != orderA * columnsB)
if (b.Length != orderA*columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
@ -593,51 +569,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.s_cholesky_solve_factored(orderA, columnsB, a, b);
}
/// <summary>
/// Computes the QR factorization of A.
/// </summary>
/// <param name="r">On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the R matrix of the QR factorization. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void QRFactor(float[] r, int rowsR, int columnsR, float[] q, float[] tau)
{
if (r == null)
{
throw new ArgumentNullException("r");
}
if (q == null)
{
throw new ArgumentNullException("q");
}
if (r.Length != rowsR * columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r");
}
if (tau.Length < Math.Min(rowsR, columnsR))
{
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
var info = SafeNativeMethods.s_cholesky_solve_factored(orderA, columnsB, a, b);
if (q.Length != rowsR * rowsR)
if (info < 0)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * rowsR"), "q");
throw new InvalidParameterException(Math.Abs(info));
}
var work = new float[columnsR * Control.BlockSize];
SafeNativeMethods.s_qr_factor(rowsR, columnsR, r, tau, q, work, work.Length);
}
/// <summary>
@ -647,16 +584,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
/// it is overwritten with the R matrix of the QR factorization. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// <param name="q">On exit, A M by M matrix that holds the Q matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void QRFactor(float[] r, int rowsR, int columnsR, float[] q, float[] tau, float[] work)
public override void QRFactor(float[] r, int rowsR, int columnsR, float[] q, float[] tau)
{
if (r == null)
{
@ -668,12 +602,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (r.Length != rowsR * columnsR)
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r");
}
@ -683,18 +612,17 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
if (q.Length != rowsR * rowsR)
if (q.Length != rowsR*rowsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * rowsR"), "q");
}
if (work.Length < columnsR * Control.BlockSize)
var info = SafeNativeMethods.s_qr_factor(rowsR, columnsR, r, tau, q);
if (info < 0)
{
work[0] = columnsR * Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
SafeNativeMethods.s_qr_factor(rowsR, columnsR, r, tau, q, work, work.Length);
}
/// <summary>
@ -737,66 +665,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "columnsA * columnsA"), "r");
}
var work = new float[columnsA * Control.BlockSize];
SafeNativeMethods.s_qr_thin_factor(rowsA, columnsA, q, tau, r, work, work.Length);
}
/// <summary>
/// Computes the thin QR factorization of A where M &gt; N.
/// </summary>
/// <param name="q">On entry, it is the M by N A matrix to factor. On exit,
/// it is overwritten with the Q matrix of the QR factorization.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="r">On exit, A N by N matrix that holds the R matrix of the
/// QR factorization.</param>
/// <param name="tau">A min(m,n) vector. On exit, contains additional information
/// to be used by the QR solve routine.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <remarks>This is similar to the GEQRF and ORGQR LAPACK routines.</remarks>
[SecuritySafeCritical]
public override void ThinQRFactor(float[] q, int rowsA, int columnsA, float[] r, float[] tau, float[] work)
{
if (r == null)
{
throw new ArgumentNullException("r");
}
if (q == null)
{
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("q");
}
if (q.Length != rowsA * columnsA)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "q");
}
if (tau.Length < Math.Min(rowsA, columnsA))
{
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau");
}
var info = SafeNativeMethods.s_qr_thin_factor(rowsA, columnsA, q, tau, r);
if (r.Length != columnsA * columnsA)
if (info < 0)
{
throw new ArgumentException(
string.Format(Resources.ArgumentArrayWrongLength, "columnsA * columnsA"), "r");
throw new InvalidParameterException(Math.Abs(info));
}
if (work.Length < columnsA * Control.BlockSize)
{
work[0] = columnsA * Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
SafeNativeMethods.s_qr_thin_factor(rowsA, columnsA, q, tau, r, work, work.Length);
}
/// <summary>
@ -812,27 +686,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolve(float[] a, int rows, int columns, float[] b, int columnsB, float[] x, QRMethod method = QRMethod.Full)
{
var work = new float[columns * Control.BlockSize];
QRSolve(a, rows, columns, b, columnsB, x, work, method);
}
/// <summary>
/// Solves A*X=B for X using QR factorization of A.
/// </summary>
/// <param name="a">The A matrix.</param>
/// <param name="rows">The number of rows in the A matrix.</param>
/// <param name="columns">The number of columns in the A matrix.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="work">The work array. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolve(float[] a, int rows, int columns, float[] b, int columnsB, float[] x, float[] work, QRMethod method = QRMethod.Full)
{
if (a == null)
{
@ -849,11 +702,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("x");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (a.Length != rows * columns)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
@ -874,56 +722,40 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.RowsLessThanColumns);
}
if (work.Length < 1)
var info = SafeNativeMethods.s_qr_solve(rows, columns, columnsB, a, b, x);
if (info == (int)NativeError.MemoryAllocation)
{
work[0] = rows * Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new MemoryAllocationException();
}
SafeNativeMethods.s_qr_solve(rows, columns, columnsB, a, b, x, work, work.Length);
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
/// <summary>
/// Solves A*X=B for X using a previously QR factored matrix.
/// </summary>
/// <param name="q">The Q matrix obtained by calling <see cref="QRFactor(float[],int,int,float[],float[])"/>.</param>
/// <param name="r">The R matrix obtained by calling <see cref="QRFactor(float[],int,int,float[],float[])"/>. </param>
/// <param name="rowsR">The number of rows in the A matrix.</param>
/// <param name="columnsR">The number of columns in the A matrix.</param>
/// <param name="tau">Contains additional information on Q. Only used for the native solver
/// and can be <c>null</c> for the managed provider.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolveFactored(float[] q, float[] r, int rowsR, int columnsR, float[] tau, float[] b, int columnsB, float[] x, QRMethod method = QRMethod.Full)
{
var work = new float[columnsR * Control.BlockSize];
QRSolveFactored(q, r, rowsR, columnsR, tau, b, columnsB, x, work, method);
if (info > 0)
{
throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient, "a");
}
}
/// <summary>
/// Solves A*X=B for X using a previously QR factored matrix.
/// </summary>
/// <param name="q">The Q matrix obtained by QR factor. This is only used for the managed provider and can be
/// <c>null</c> for the native provider. The native provider uses the Q portion stored in the R matrix.</param>
/// <param name="q">The Q matrix obtained by calling <see cref="QRFactor(float[],int,int,float[],float[])"/>.</param>
/// <param name="r">The R matrix obtained by calling <see cref="QRFactor(float[],int,int,float[],float[])"/>. </param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="tau">Contains additional information on Q. Only used for the native solver
/// and can be <c>null</c> for the managed provider.</param>
/// <param name="b">On entry the B matrix; on exit the X matrix.</param>
/// <param name="b">The B matrix.</param>
/// <param name="columnsB">The number of columns of B.</param>
/// <param name="x">On exit, the solution matrix.</param>
/// <param name="work">The work array - only used in the native provider. The array must have a length of at least N,
/// but should be N*blocksize. The blocksize is machine dependent. On exit, work[0] contains the optimal
/// work size value.</param>
/// <param name="method">The type of QR factorization to perform. <seealso cref="QRMethod"/></param>
/// <remarks>Rows must be greater or equal to columns.</remarks>
[SecuritySafeCritical]
public override void QRSolveFactored(float[] q, float[] r, int rowsA, int columnsA, float[] tau, float[] b, int columnsB, float[] x, float[] work, QRMethod method = QRMethod.Full)
public override void QRSolveFactored(float[] q, float[] r, int rowsA, int columnsA, float[] tau, float[] b, int columnsB, float[] x, QRMethod method = QRMethod.Full)
{
if (r == null)
{
@ -945,11 +777,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("q");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
int rowsQ, columnsQ, rowsR, columnsR;
if (method == QRMethod.Full)
{
@ -982,15 +809,19 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA * columnsB), "x");
}
if (work.Length < 1)
{
work[0] = rowsA * Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
if (method == QRMethod.Full)
{
SafeNativeMethods.s_qr_solve_factored(rowsA, columnsA, columnsB, r, b, tau, x, work, work.Length);
var info = SafeNativeMethods.s_qr_solve_factored(rowsA, columnsA, columnsB, r, b, tau, x);
if (info == (int)NativeError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
}
else
{
@ -1000,61 +831,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
}
}
/// <summary>
/// Computes the singular value decomposition of A.
/// </summary>
/// <param name="computeVectors">Compute the singular U and VT vectors or not.</param>
/// <param name="a">On entry, the M by N matrix to decompose. On exit, A may be overwritten.</param>
/// <param name="rowsA">The number of rows in the A matrix.</param>
/// <param name="columnsA">The number of columns in the A matrix.</param>
/// <param name="s">The singular values of A in ascending value.</param>
/// <param name="u">If <paramref name="computeVectors"/> is <c>true</c>, on exit U contains the left
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void SingularValueDecomposition(bool computeVectors, float[] a, int rowsA, int columnsA, float[] s, float[] u, float[] vt)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (s == null)
{
throw new ArgumentNullException("s");
}
if (u == null)
{
throw new ArgumentNullException("u");
}
if (vt == null)
{
throw new ArgumentNullException("vt");
}
if (u.Length != rowsA * rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
if (vt.Length != columnsA * columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
if (s.Length != Math.Min(rowsA, columnsA))
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
var work = new float[Math.Max(((3 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA)), 5 * Math.Min(rowsA, columnsA))];
SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, work);
}
/// <summary>
/// Solves A*X=B for X using the singular value decomposition of A.
/// </summary>
@ -1081,24 +857,23 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("x");
}
if (b.Length != rowsA * columnsB)
if (b.Length != rowsA*columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
if (x.Length != columnsA * columnsB)
if (x.Length != columnsA*columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
var work = new float[Math.Max(((3 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA)), 5 * Math.Min(rowsA, columnsA))];
var s = new float[Math.Min(rowsA, columnsA)];
var u = new float[rowsA * rowsA];
var vt = new float[columnsA * columnsA];
var u = new float[rowsA*rowsA];
var vt = new float[columnsA*columnsA];
var clone = new float[a.Length];
a.Copy(clone);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt, work);
SingularValueDecomposition(true, clone, rowsA, columnsA, s, u, vt);
SvdSolveFactored(rowsA, columnsA, s, u, vt, b, columnsB, x);
}
@ -1114,12 +889,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
/// singular vectors.</param>
/// <param name="vt">If <paramref name="computeVectors"/> is <c>true</c>, on exit VT contains the transposed
/// right singular vectors.</param>
/// <param name="work">The work array. For real matrices, the work array should be at least
/// Max(3*Min(M, N) + Max(M, N), 5*Min(M,N)). For complex matrices, 2*Min(M, N) + Max(M, N).
/// On exit, work[0] contains the optimal work size value.</param>
/// <remarks>This is equivalent to the GESVD LAPACK routine.</remarks>
[SecuritySafeCritical]
public override void SingularValueDecomposition(bool computeVectors, float[] a, int rowsA, int columnsA, float[] s, float[] u, float[] vt, float[] work)
public override void SingularValueDecomposition(bool computeVectors, float[] a, int rowsA, int columnsA, float[] s, float[] u, float[] vt)
{
if (a == null)
{
@ -1141,17 +913,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("vt");
}
if (work == null)
{
throw new ArgumentNullException("work");
}
if (u.Length != rowsA * rowsA)
if (u.Length != rowsA*rowsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
}
if (vt.Length != columnsA * columnsA)
if (vt.Length != columnsA*columnsA)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
}
@ -1161,18 +928,19 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
if (work.Length == 0)
var info = SafeNativeMethods.s_svd_factor(computeVectors, rowsA, columnsA, a, s, u, vt);
if (info == (int)NativeError.MemoryAllocation)
{
throw new ArgumentException(Resources.ArgumentSingleDimensionArray, "work");
throw new MemoryAllocationException();
}
if (work.Length < Math.Max(((3 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA)), 5 * Math.Min(rowsA, columnsA)))
if (info < 0)
{
work[0] = Math.Max(((3 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA)), 5 * Math.Min(rowsA, columnsA));
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
throw new InvalidParameterException(Math.Abs(info));
}
if (SafeNativeMethods.s_svd_factor(computeVectors, rowsA, columnsA, a, s, u, vt, work, work.Length) > 0)
if (info > 0)
{
throw new NonConvergenceException();
}
@ -1194,9 +962,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("matrix");
}
if (matrix.Length != order * order)
if (matrix.Length != order*order)
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order * order), "matrix");
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order*order), "matrix");
}
if (matrixEv == null)
@ -1204,9 +972,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("matrixEv");
}
if (matrixEv.Length != order * order)
if (matrixEv.Length != order*order)
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order * order), "matrixEv");
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order*order), "matrixEv");
}
if (vectorEv == null)
@ -1224,12 +992,24 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
throw new ArgumentNullException("matrixD");
}
if (matrixD.Length != order * order)
if (matrixD.Length != order*order)
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order * order), "matrixD");
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order*order), "matrixD");
}
if (SafeNativeMethods.s_eigen(isSymmetric, order, matrix, matrixEv, vectorEv, matrixD) > 0)
var info = SafeNativeMethods.s_eigen(isSymmetric, order, matrix, matrixEv, vectorEv, matrixD);
if (info == (int)NativeError.MemoryAllocation)
{
throw new MemoryAllocationException();
}
if (info < 0)
{
throw new InvalidParameterException(Math.Abs(info));
}
if (info > 0)
{
throw new NonConvergenceException();
}

11
src/Numerics/Providers/LinearAlgebra/OpenBlas/OpenBlasLinearAlgebraProvider.cs

@ -34,6 +34,17 @@ using System;
namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
{
/// <summary>
/// Error codes return from the native OpenBLAS provider.
/// </summary>
public enum NativeError : int
{
/// <summary>
/// Unable to allocate memory.
/// </summary>
MemoryAllocation = -999999
}
internal enum ParallelType : int
{
Sequential = 0,

100
src/Numerics/Providers/LinearAlgebra/OpenBlas/SafeNativeMethods.cs

@ -2,7 +2,7 @@
// Math.NET Numerics, part of the Math.NET Project
// http://mathnet.opensourcedotnet.info
//
// Copyright (c) 2009-2010 Math.NET
// Copyright (c) 2009-2015 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -117,16 +117,28 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
#region LAPACK
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern float s_matrix_norm(byte norm, int rows, int columns, [In] float[] a, [In, Out] float[] work);
internal static extern float s_matrix_norm(byte norm, int rows, int columns, [In] float[] a);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern float d_matrix_norm(byte norm, int rows, int columns, [In] double[] a, [In, Out] double[] work);
internal static extern double d_matrix_norm(byte norm, int rows, int columns, [In] double[] a);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern float c_matrix_norm(byte norm, int rows, int columns, [In] Complex32[] a, [In, Out] float[] work);
internal static extern float c_matrix_norm(byte norm, int rows, int columns, [In] Complex32[] a);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern double z_matrix_norm(byte norm, int rows, int columns, [In] Complex[] a, [In, Out] double[] work);
internal static extern double z_matrix_norm(byte norm, int rows, int columns, [In] Complex[] a);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int s_cholesky_factor(int n, [In, Out] float[] a);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int d_cholesky_factor(int n, [In, Out] double[] a);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int c_cholesky_factor(int n, [In, Out] Complex32[] a);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int z_cholesky_factor(int n, [In, Out] Complex[] a);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int s_lu_factor(int n, [In, Out] float[] a, [In, Out] int[] ipiv);
@ -141,28 +153,28 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
internal static extern int z_lu_factor(int n, [In, Out] Complex[] a, [In, Out] int[] ipiv);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int s_lu_inverse(int n, [In, Out] float[] a, [In, Out] float[] work, int lwork);
internal static extern int s_lu_inverse(int n, [In, Out] float[] a);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int d_lu_inverse(int n, [In, Out] double[] a, [In, Out] double[] work, int lwork);
internal static extern int d_lu_inverse(int n, [In, Out] double[] a);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int c_lu_inverse(int n, [In, Out] Complex32[] a, [In, Out] Complex32[] work, int lwork);
internal static extern int c_lu_inverse(int n, [In, Out] Complex32[] a);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int z_lu_inverse(int n, [In, Out] Complex[] a, [In, Out] Complex[] work, int lwork);
internal static extern int z_lu_inverse(int n, [In, Out] Complex[] a);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int s_lu_inverse_factored(int n, [In, Out] float[] a, [In, Out] int[] ipiv, [In, Out] float[] work, int lwork);
internal static extern int s_lu_inverse_factored(int n, [In, Out] float[] a, [In, Out] int[] ipiv);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int d_lu_inverse_factored(int n, [In, Out] double[] a, [In, Out] int[] ipiv, [In, Out] double[] work, int lwork);
internal static extern int d_lu_inverse_factored(int n, [In, Out] double[] a, [In, Out] int[] ipiv);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int c_lu_inverse_factored(int n, [In, Out] Complex32[] a, [In, Out] int[] ipiv, [In, Out] Complex32[] work, int lwork);
internal static extern int c_lu_inverse_factored(int n, [In, Out] Complex32[] a, [In, Out] int[] ipiv);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int z_lu_inverse_factored(int n, [In, Out] Complex[] a, [In, Out] int[] ipiv, [In, Out] Complex[] work, int lwork);
internal static extern int z_lu_inverse_factored(int n, [In, Out] Complex[] a, [In, Out] int[] ipiv);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int s_lu_solve_factored(int n, int nrhs, float[] a, [In, Out] int[] ipiv, [In, Out] float[] b);
@ -188,18 +200,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int z_lu_solve(int n, int nrhs, Complex[] a, [In, Out] Complex[] b);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int s_cholesky_factor(int n, [In, Out] float[] a);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int d_cholesky_factor(int n, [In, Out] double[] a);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int c_cholesky_factor(int n, [In, Out] Complex32[] a);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int z_cholesky_factor(int n, [In, Out] Complex[] a);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int s_cholesky_solve(int n, int nrhs, float[] a, [In, Out] float[] b);
@ -225,77 +225,77 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.OpenBlas
internal static extern int z_cholesky_solve_factored(int n, int nrhs, Complex[] a, [In, Out] Complex[] b);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int s_qr_factor(int m, int n, [In, Out] float[] r, [In, Out] float[] tau, [In, Out] float[] q, [In, Out] float[] work, int len);
internal static extern int s_qr_factor(int m, int n, [In, Out] float[] r, [In, Out] float[] tau, [In, Out] float[] q);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int s_qr_thin_factor(int m, int n, [In, Out] float[] q, [In, Out] float[] tau, [In, Out] float[] r, [In, Out] float[] work, int len);
internal static extern int d_qr_factor(int m, int n, [In, Out] double[] r, [In, Out] double[] tau, [In, Out] double[] q);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int d_qr_factor(int m, int n, [In, Out] double[] r, [In, Out] double[] tau, [In, Out] double[] q, [In, Out] double[] work, int len);
internal static extern int c_qr_factor(int m, int n, [In, Out] Complex32[] r, [In, Out] Complex32[] tau, [In, Out] Complex32[] q);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int d_qr_thin_factor(int m, int n, [In, Out] double[] q, [In, Out] double[] tau, [In, Out] double[] r, [In, Out] double[] work, int len);
internal static extern int z_qr_factor(int m, int n, [In, Out] Complex[] r, [In, Out] Complex[] tau, [In, Out] Complex[] q);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int c_qr_factor(int m, int n, [In, Out] Complex32[] r, [In, Out] Complex32[] tau, [In, Out] Complex32[] q, [In, Out] Complex32[] work, int len);
internal static extern int s_qr_thin_factor(int m, int n, [In, Out] float[] q, [In, Out] float[] tau, [In, Out] float[] r);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int c_qr_thin_factor(int m, int n, [In, Out] Complex32[] q, [In, Out] Complex32[] tau, [In, Out] Complex32[] r, [In, Out] Complex32[] work, int len);
internal static extern int d_qr_thin_factor(int m, int n, [In, Out] double[] q, [In, Out] double[] tau, [In, Out] double[] r);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int z_qr_factor(int m, int n, [In, Out] Complex[] r, [In, Out] Complex[] tau, [In, Out] Complex[] q, [In, Out] Complex[] work, int len);
internal static extern int c_qr_thin_factor(int m, int n, [In, Out] Complex32[] q, [In, Out] Complex32[] tau, [In, Out] Complex32[] r);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int z_qr_thin_factor(int m, int n, [In, Out] Complex[] q, [In, Out] Complex[] tau, [In, Out] Complex[] r, [In, Out] Complex[] work, int len);
internal static extern int z_qr_thin_factor(int m, int n, [In, Out] Complex[] q, [In, Out] Complex[] tau, [In, Out] Complex[] r);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int s_qr_solve(int m, int n, int bn, float[] r, float[] b, [In, Out] float[] x, [In, Out] float[] work, int len);
internal static extern int s_qr_solve(int m, int n, int bn, float[] r, float[] b, [In, Out] float[] x);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int d_qr_solve(int m, int n, int bn, double[] r, double[] b, [In, Out] double[] x, [In, Out] double[] work, int len);
internal static extern int d_qr_solve(int m, int n, int bn, double[] r, double[] b, [In, Out] double[] x);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int c_qr_solve(int m, int n, int bn, Complex32[] r, Complex32[] b, [In, Out] Complex32[] x, [In, Out] Complex32[] work, int len);
internal static extern int c_qr_solve(int m, int n, int bn, Complex32[] r, Complex32[] b, [In, Out] Complex32[] x);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int z_qr_solve(int m, int n, int bn, Complex[] r, Complex[] b, [In, Out] Complex[] x, [In, Out] Complex[] work, int len);
internal static extern int z_qr_solve(int m, int n, int bn, Complex[] r, Complex[] b, [In, Out] Complex[] x);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int s_qr_solve_factored(int m, int n, int bn, float[] r, float[] b, float[] tau, [In, Out] float[] x, [In, Out] float[] work, int len);
internal static extern int s_qr_solve_factored(int m, int n, int bn, float[] r, float[] b, float[] tau, [In, Out] float[] x);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int d_qr_solve_factored(int m, int n, int bn, double[] r, double[] b, double[] tau, [In, Out] double[] x, [In, Out] double[] work, int len);
internal static extern int d_qr_solve_factored(int m, int n, int bn, double[] r, double[] b, double[] tau, [In, Out] double[] x);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int c_qr_solve_factored(int m, int n, int bn, Complex32[] r, Complex32[] b, Complex32[] tau, [In, Out] Complex32[] x, [In, Out] Complex32[] work, int len);
internal static extern int c_qr_solve_factored(int m, int n, int bn, Complex32[] r, Complex32[] b, Complex32[] tau, [In, Out] Complex32[] x);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int z_qr_solve_factored(int m, int n, int bn, Complex[] r, Complex[] b, Complex[] tau, [In, Out] Complex[] x, [In, Out] Complex[] work, int len);
internal static extern int z_qr_solve_factored(int m, int n, int bn, Complex[] r, Complex[] b, Complex[] tau, [In, Out] Complex[] x);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int s_svd_factor(bool computeVectors, int m, int n, [In, Out] float[] a, [In, Out] float[] s, [In, Out] float[] u, [In, Out] float[] v, [In, Out] float[] work, int len);
internal static extern int s_svd_factor([MarshalAs(UnmanagedType.U1)] bool computeVectors, int m, int n, [In, Out] float[] a, [In, Out] float[] s, [In, Out] float[] u, [In, Out] float[] v);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int d_svd_factor(bool computeVectors, int m, int n, [In, Out] double[] a, [In, Out] double[] s, [In, Out] double[] u, [In, Out] double[] v, [In, Out] double[] work, int len);
internal static extern int d_svd_factor([MarshalAs(UnmanagedType.U1)] bool computeVectors, int m, int n, [In, Out] double[] a, [In, Out] double[] s, [In, Out] double[] u, [In, Out] double[] v);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int c_svd_factor(bool computeVectors, int m, int n, [In, Out] Complex32[] a, [In, Out] Complex32[] s, [In, Out] Complex32[] u, [In, Out] Complex32[] v, [In, Out] Complex32[] work, int len);
internal static extern int c_svd_factor([MarshalAs(UnmanagedType.U1)] bool computeVectors, int m, int n, [In, Out] Complex32[] a, [In, Out] Complex32[] s, [In, Out] Complex32[] u, [In, Out] Complex32[] v);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int z_svd_factor(bool computeVectors, int m, int n, [In, Out] Complex[] a, [In, Out] Complex[] s, [In, Out] Complex[] u, [In, Out] Complex[] v, [In, Out] Complex[] work, int len);
internal static extern int z_svd_factor([MarshalAs(UnmanagedType.U1)] bool computeVectors, int m, int n, [In, Out] Complex[] a, [In, Out] Complex[] s, [In, Out] Complex[] u, [In, Out] Complex[] v);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int s_eigen(bool isSymmetric, int n, [In, Out] float[] a, [In, Out] float[] vectors, [In, Out] Complex[] values, [In, Out] float[] d);
internal static extern int s_eigen([MarshalAs(UnmanagedType.U1)] bool isSymmetric, int n, [In] float[] a, [In, Out] float[] vectors, [In, Out] Complex[] values, [In, Out] float[] d);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int d_eigen(bool isSymmetric, int n, [In, Out] double[] a, [In, Out] double[] vectors, [In, Out] Complex[] values, [In, Out] double[] d);
internal static extern int d_eigen([MarshalAs(UnmanagedType.U1)] bool isSymmetric, int n, [In] double[] a, [In, Out] double[] vectors, [In, Out] Complex[] values, [In, Out] double[] d);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int c_eigen(bool isSymmetric, int n, [In, Out] Complex32[] a, [In, Out] Complex32[] vectors, [In, Out] Complex[] values, [In, Out] Complex32[] d);
internal static extern int c_eigen([MarshalAs(UnmanagedType.U1)] bool isSymmetric, int n, [In] Complex32[] a, [In, Out] Complex32[] vectors, [In, Out] Complex[] values, [In, Out] Complex32[] d);
[DllImport(_DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int z_eigen(bool isSymmetric, int n, [In, Out] Complex[] a, [In, Out] Complex[] vectors, [In, Out] Complex[] values, [In, Out] Complex[] d);
internal static extern int z_eigen([MarshalAs(UnmanagedType.U1)] bool isSymmetric, int n, [In] Complex[] a, [In, Out] Complex[] vectors, [In, Out] Complex[] values, [In, Out] Complex[] d);
#endregion LAPACK
}
}

588
src/UnitTests/LinearAlgebraProviderTests/Complex/LinearAlgebraProviderTests.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
// Copyright (c) 2009-2015 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -433,68 +433,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Complex
AssertHelpers.AlmostEqualRelative(a[8], -0.113636363636364, 13);
}
/// <summary>
/// Can compute the inverse of a matrix using LU factorization
/// with a work array.
/// </summary>
[Test]
public void CanComputeLuInverseWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new Complex[matrix.RowCount*matrix.RowCount];
Array.Copy(matrix.Values, a, a.Length);
#if CUDA
Complex[] work = null;
#else
var work = new Complex[matrix.RowCount];
#endif
Control.LinearAlgebraProvider.LUInverse(a, matrix.RowCount, work);
AssertHelpers.AlmostEqualRelative(a[0], -0.454545454545454, 13);
AssertHelpers.AlmostEqualRelative(a[1], -0.909090909090908, 13);
AssertHelpers.AlmostEqualRelative(a[2], 0.454545454545454, 13);
AssertHelpers.AlmostEqualRelative(a[3], -0.340909090909090, 13);
AssertHelpers.AlmostEqualRelative(a[4], -2.045454545454543, 13);
AssertHelpers.AlmostEqualRelative(a[5], 1.477272727272726, 13);
AssertHelpers.AlmostEqualRelative(a[6], -0.113636363636364, 13);
AssertHelpers.AlmostEqualRelative(a[7], 0.227272727272727, 13);
AssertHelpers.AlmostEqualRelative(a[8], -0.113636363636364, 13);
}
/// <summary>
/// Can compute the inverse of a matrix using LU factorization
/// using a previously factored matrix with a work array.
/// </summary>
[Test]
public void CanComputeLuInverseOnFactoredMatrixWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new Complex[matrix.RowCount*matrix.RowCount];
Array.Copy(matrix.Values, a, a.Length);
var ipiv = new int[matrix.RowCount];
Control.LinearAlgebraProvider.LUFactor(a, matrix.RowCount, ipiv);
#if CUDA
Complex[] work = null;
#else
var work = new Complex[matrix.RowCount];
#endif
Control.LinearAlgebraProvider.LUInverseFactored(a, matrix.RowCount, ipiv, work);
AssertHelpers.AlmostEqualRelative(a[0], -0.454545454545454, 13);
AssertHelpers.AlmostEqualRelative(a[1], -0.909090909090908, 13);
AssertHelpers.AlmostEqualRelative(a[2], 0.454545454545454, 13);
AssertHelpers.AlmostEqualRelative(a[3], -0.340909090909090, 13);
AssertHelpers.AlmostEqualRelative(a[4], -2.045454545454543, 13);
AssertHelpers.AlmostEqualRelative(a[5], 1.477272727272726, 13);
AssertHelpers.AlmostEqualRelative(a[6], -0.113636363636364, 13);
AssertHelpers.AlmostEqualRelative(a[7], 0.227272727272727, 13);
AssertHelpers.AlmostEqualRelative(a[8], -0.113636363636364, 13);
}
/// <summary>
/// Can solve Ax=b using LU factorization.
/// </summary>
@ -692,90 +630,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Complex
}
}
/// <summary>
/// Can compute QR factorization of a square matrix using a work array.
/// </summary>
[Test]
public void CanComputeQRFactorSquareMatrixWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var r = new Complex[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, r, r.Length);
var tau = new Complex[3];
var q = new Complex[matrix.RowCount*matrix.RowCount];
var work = new Complex[matrix.ColumnCount*Control.BlockSize];
Control.LinearAlgebraProvider.QRFactor(r, matrix.RowCount, matrix.ColumnCount, q, tau, work);
var mq = new DenseMatrix(matrix.RowCount, matrix.RowCount, q);
var mr = new DenseMatrix(matrix.RowCount, matrix.ColumnCount, r).UpperTriangle();
var a = mq*mr;
for (var row = 0; row < matrix.RowCount; row++)
{
for (var col = 0; col < matrix.ColumnCount; col++)
{
AssertHelpers.AlmostEqualRelative(matrix[row, col], a[row, col], 14);
}
}
}
/// <summary>
/// Can compute QR factorization of a tall matrix using a work matrix.
/// </summary>
[Test]
public void CanComputeQRFactorTallMatrixWithWorkArray()
{
var matrix = _matrices["Tall3x2"];
var r = new Complex[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, r, r.Length);
var tau = new Complex[3];
var q = new Complex[matrix.RowCount*matrix.RowCount];
var work = new Complex[matrix.ColumnCount*Control.BlockSize];
Control.LinearAlgebraProvider.QRFactor(r, matrix.RowCount, matrix.ColumnCount, q, tau, work);
var mr = new DenseMatrix(matrix.RowCount, matrix.ColumnCount, r).UpperTriangle();
var mq = new DenseMatrix(matrix.RowCount, matrix.RowCount, q);
var a = mq*mr;
for (var row = 0; row < matrix.RowCount; row++)
{
for (var col = 0; col < matrix.ColumnCount; col++)
{
AssertHelpers.AlmostEqualRelative(matrix[row, col], a[row, col], 14);
}
}
}
/// <summary>
/// Can compute QR factorization of a wide matrix using a work matrix.
/// </summary>
[Test]
public void CanComputeQRFactorWideMatrixWithWorkArray()
{
var matrix = _matrices["Wide2x3"];
var r = new Complex[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, r, r.Length);
var tau = new Complex[3];
var q = new Complex[matrix.RowCount*matrix.RowCount];
var work = new Complex[matrix.ColumnCount*Control.BlockSize];
Control.LinearAlgebraProvider.QRFactor(r, matrix.RowCount, matrix.ColumnCount, q, tau, work);
var mr = new DenseMatrix(matrix.RowCount, matrix.ColumnCount, r).UpperTriangle();
var mq = new DenseMatrix(matrix.RowCount, matrix.RowCount, q);
var a = mq*mr;
for (var row = 0; row < matrix.RowCount; row++)
{
for (var col = 0; col < matrix.ColumnCount; col++)
{
AssertHelpers.AlmostEqualRelative(matrix[row, col], a[row, col], 14);
}
}
}
/// <summary>
/// Can compute thin QR factorization of a square matrix.
/// </summary>
@ -830,61 +684,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Complex
}
}
/// <summary>
/// Can compute thin QR factorization of a square matrix using a work array.
/// </summary>
[Test]
public void CanComputeThinQRFactorSquareMatrixWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var r = new Complex[matrix.ColumnCount*matrix.ColumnCount];
var tau = new Complex[3];
var q = new Complex[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, q, q.Length);
var work = new Complex[matrix.ColumnCount*Control.BlockSize];
Control.LinearAlgebraProvider.ThinQRFactor(q, matrix.RowCount, matrix.ColumnCount, r, tau, work);
var mq = new DenseMatrix(matrix.RowCount, matrix.ColumnCount, q);
var mr = new DenseMatrix(matrix.ColumnCount, matrix.ColumnCount, r);
var a = mq*mr;
for (var row = 0; row < matrix.RowCount; row++)
{
for (var col = 0; col < matrix.ColumnCount; col++)
{
AssertHelpers.AlmostEqualRelative(matrix[row, col], a[row, col], 14);
}
}
}
/// <summary>
/// Can compute thin QR factorization of a tall matrix using a work matrix.
/// </summary>
[Test]
public void CanComputeThinQRFactorTallMatrixWithWorkArray()
{
var matrix = _matrices["Tall3x2"];
var r = new Complex[matrix.ColumnCount*matrix.ColumnCount];
var tau = new Complex[3];
var q = new Complex[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, q, q.Length);
var work = new Complex[matrix.ColumnCount*Control.BlockSize];
Control.LinearAlgebraProvider.ThinQRFactor(q, matrix.RowCount, matrix.ColumnCount, r, tau, work);
var mq = new DenseMatrix(matrix.RowCount, matrix.ColumnCount, q);
var mr = new DenseMatrix(matrix.ColumnCount, matrix.ColumnCount, r);
var a = mq*mr;
for (var row = 0; row < matrix.RowCount; row++)
{
for (var col = 0; col < matrix.ColumnCount; col++)
{
AssertHelpers.AlmostEqualRelative(matrix[row, col], a[row, col], 14);
}
}
}
/// <summary>
/// Can solve Ax=b using QR factorization with a square A matrix.
/// </summary>
@ -936,92 +735,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Complex
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 13);
}
/// <summary>
/// Can solve Ax=b using QR factorization with a square A matrix
/// using a work array.
/// </summary>
[Test]
public void CanSolveUsingQRSquareMatrixUsingWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new Complex[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var b = new[] {new Complex(1.0, 0), 2.0, 3.0, 4.0, 5.0, 6.0};
var x = new Complex[matrix.ColumnCount*2];
var work = new Complex[matrix.RowCount*matrix.RowCount];
Control.LinearAlgebraProvider.QRSolve(a, matrix.RowCount, matrix.ColumnCount, b, 2, x, work);
NotModified(3, 3, a, matrix);
var mx = new DenseMatrix(matrix.ColumnCount, 2, x);
var mb = matrix*mx;
AssertHelpers.AlmostEqualRelative(mb[0, 0], b[0], 13);
AssertHelpers.AlmostEqualRelative(mb[1, 0], b[1], 13);
AssertHelpers.AlmostEqualRelative(mb[2, 0], b[2], 13);
AssertHelpers.AlmostEqualRelative(mb[0, 1], b[3], 13);
AssertHelpers.AlmostEqualRelative(mb[1, 1], b[4], 13);
AssertHelpers.AlmostEqualRelative(mb[2, 1], b[5], 13);
}
/// <summary>
/// Can solve Ax=b using QR factorization with a tall A matrix
/// using a work array.
/// </summary>
[Test]
public void CanSolveUsingQRTallMatrixUsingWorkArray()
{
var matrix = _matrices["Tall3x2"];
var a = new Complex[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var b = new[] {new Complex(1.0, 0), 2.0, 3.0, 4.0, 5.0, 6.0};
var x = new Complex[matrix.ColumnCount*2];
var work = new Complex[matrix.RowCount*matrix.RowCount];
Control.LinearAlgebraProvider.QRSolve(a, matrix.RowCount, matrix.ColumnCount, b, 2, x, work);
NotModified(3, 2, a, matrix);
var mb = new DenseMatrix(matrix.RowCount, 2, b);
var test = (matrix.Transpose()*matrix).Inverse()*matrix.Transpose()*mb;
AssertHelpers.AlmostEqualRelative(test[0, 0], x[0], 13);
AssertHelpers.AlmostEqualRelative(test[1, 0], x[1], 13);
AssertHelpers.AlmostEqualRelative(test[0, 1], x[2], 13);
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 13);
}
/// <summary>
/// Can solve Ax=b using QR factorization with a square A matrix
/// using a factored A matrix.
/// </summary>
[Test]
public void CanSolveUsingQRSquareMatrixOnFactoredMatrix()
{
var matrix = _matrices["Square3x3"];
var a = new Complex[matrix.RowCount*matrix.RowCount];
Array.Copy(matrix.Values, a, a.Length);
var tau = new Complex[matrix.ColumnCount];
var q = new Complex[matrix.ColumnCount*matrix.ColumnCount];
Control.LinearAlgebraProvider.QRFactor(a, matrix.RowCount, matrix.ColumnCount, q, tau);
var b = new[] {new Complex(1.0, 0), 2.0, 3.0, 4.0, 5.0, 6.0};
var x = new Complex[matrix.ColumnCount*2];
Control.LinearAlgebraProvider.QRSolveFactored(q, a, matrix.RowCount, matrix.ColumnCount, tau, b, 2, x);
var mx = new DenseMatrix(matrix.ColumnCount, 2, x);
var mb = matrix*mx;
AssertHelpers.AlmostEqualRelative(mb[0, 0], b[0], 13);
AssertHelpers.AlmostEqualRelative(mb[1, 0], b[1], 13);
AssertHelpers.AlmostEqualRelative(mb[2, 0], b[2], 13);
AssertHelpers.AlmostEqualRelative(mb[0, 1], b[3], 13);
AssertHelpers.AlmostEqualRelative(mb[1, 1], b[4], 13);
AssertHelpers.AlmostEqualRelative(mb[2, 1], b[5], 13);
}
/// <summary>
/// Can solve Ax=b using QR factorization with a tall A matrix
/// using a factored A matrix.
@ -1050,66 +763,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Complex
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 13);
}
/// <summary>
/// Can solve Ax=b using QR factorization with a square A matrix
/// using a factored A matrix with a work array.
/// </summary>
[Test]
public void CanSolveUsingQRSquareMatrixOnFactoredMatrixWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new Complex[matrix.RowCount*matrix.RowCount];
Array.Copy(matrix.Values, a, a.Length);
var tau = new Complex[matrix.ColumnCount];
var q = new Complex[matrix.ColumnCount*matrix.ColumnCount];
var work = new Complex[2048];
Control.LinearAlgebraProvider.QRFactor(a, matrix.RowCount, matrix.ColumnCount, q, tau, work);
var b = new[] {new Complex(1.0, 0), 2.0, 3.0, 4.0, 5.0, 6.0};
var x = new Complex[matrix.ColumnCount*2];
Control.LinearAlgebraProvider.QRSolveFactored(q, a, matrix.RowCount, matrix.ColumnCount, tau, b, 2, x, work);
var mx = new DenseMatrix(matrix.ColumnCount, 2, x);
var mb = matrix*mx;
AssertHelpers.AlmostEqualRelative(mb[0, 0], b[0], 13);
AssertHelpers.AlmostEqualRelative(mb[1, 0], b[1], 13);
AssertHelpers.AlmostEqualRelative(mb[2, 0], b[2], 13);
AssertHelpers.AlmostEqualRelative(mb[0, 1], b[3], 13);
AssertHelpers.AlmostEqualRelative(mb[1, 1], b[4], 13);
AssertHelpers.AlmostEqualRelative(mb[2, 1], b[5], 13);
}
/// <summary>
/// Can solve Ax=b using QR factorization with a tall A matrix
/// using a factored A matrix with a work array.
/// </summary>
[Test]
public void CanSolveUsingQRTallMatrixOnFactoredMatrixWithWorkArray()
{
var matrix = _matrices["Tall3x2"];
var a = new Complex[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var tau = new Complex[matrix.ColumnCount];
var q = new Complex[matrix.RowCount*matrix.RowCount];
var work = new Complex[2048];
Control.LinearAlgebraProvider.QRFactor(a, matrix.RowCount, matrix.ColumnCount, q, tau, work);
var b = new[] {new Complex(1.0, 0), 2.0, 3.0, 4.0, 5.0, 6.0};
var x = new Complex[matrix.ColumnCount*2];
Control.LinearAlgebraProvider.QRSolveFactored(q, a, matrix.RowCount, matrix.ColumnCount, tau, b, 2, x, work);
var mb = new DenseMatrix(matrix.RowCount, 2, b);
var test = (matrix.Transpose()*matrix).Inverse()*matrix.Transpose()*mb;
AssertHelpers.AlmostEqualRelative(test[0, 0], x[0], 13);
AssertHelpers.AlmostEqualRelative(test[1, 0], x[1], 13);
AssertHelpers.AlmostEqualRelative(test[0, 1], x[2], 13);
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 13);
}
/// <summary>
/// Can solve Ax=b using thin QR factorization with a square A matrix.
/// </summary>
@ -1162,62 +815,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Complex
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 13);
}
/// <summary>
/// Can solve Ax=b using thin QR factorization with a square A matrix
/// using a work array.
/// </summary>
[Test]
public void CanSolveUsingThinQRSquareMatrixUsingWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new Complex[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var b = new[] {new Complex(1.0, 0), 2.0, 3.0, 4.0, 5.0, 6.0};
var x = new Complex[matrix.ColumnCount*2];
var work = new Complex[matrix.RowCount*matrix.ColumnCount];
Control.LinearAlgebraProvider.QRSolve(a, matrix.RowCount, matrix.ColumnCount, b, 2, x, work, QRMethod.Thin);
NotModified(3, 3, a, matrix);
var mx = new DenseMatrix(matrix.ColumnCount, 2, x);
var mb = matrix*mx;
AssertHelpers.AlmostEqualRelative(mb[0, 0], b[0], 13);
AssertHelpers.AlmostEqualRelative(mb[1, 0], b[1], 13);
AssertHelpers.AlmostEqualRelative(mb[2, 0], b[2], 13);
AssertHelpers.AlmostEqualRelative(mb[0, 1], b[3], 13);
AssertHelpers.AlmostEqualRelative(mb[1, 1], b[4], 13);
AssertHelpers.AlmostEqualRelative(mb[2, 1], b[5], 13);
}
/// <summary>
/// Can solve Ax=b using thin QR factorization with a tall A matrix
/// using a work array.
/// </summary>
[Test]
public void CanSolveUsingThinQRTallMatrixUsingWorkArray()
{
var matrix = _matrices["Tall3x2"];
var a = new Complex[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var b = new[] {new Complex(1.0, 0), 2.0, 3.0, 4.0, 5.0, 6.0};
var x = new Complex[matrix.ColumnCount*2];
var work = new Complex[matrix.RowCount*matrix.ColumnCount];
Control.LinearAlgebraProvider.QRSolve(a, matrix.RowCount, matrix.ColumnCount, b, 2, x, work, QRMethod.Thin);
NotModified(3, 2, a, matrix);
var mb = new DenseMatrix(matrix.RowCount, 2, b);
var test = (matrix.Transpose()*matrix).Inverse()*matrix.Transpose()*mb;
AssertHelpers.AlmostEqualRelative(test[0, 0], x[0], 13);
AssertHelpers.AlmostEqualRelative(test[1, 0], x[1], 13);
AssertHelpers.AlmostEqualRelative(test[0, 1], x[2], 13);
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 13);
}
/// <summary>
/// Can solve Ax=b using thin QR factorization with a square A matrix
/// using a factored A matrix.
@ -1276,66 +873,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Complex
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 13);
}
/// <summary>
/// Can solve Ax=b using thin QR factorization with a square A matrix
/// using a factored A matrix with a work array.
/// </summary>
[Test]
public void CanSolveUsingThinQRSquareMatrixOnFactoredMatrixWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new Complex[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var tau = new Complex[matrix.ColumnCount];
var r = new Complex[matrix.ColumnCount*matrix.ColumnCount];
var work = new Complex[2048];
Control.LinearAlgebraProvider.ThinQRFactor(a, matrix.RowCount, matrix.ColumnCount, r, tau, work);
var b = new[] {new Complex(1.0, 0), 2.0, 3.0, 4.0, 5.0, 6.0};
var x = new Complex[matrix.ColumnCount*2];
Control.LinearAlgebraProvider.QRSolveFactored(a, r, matrix.RowCount, matrix.ColumnCount, tau, b, 2, x, work, QRMethod.Thin);
var mx = new DenseMatrix(matrix.ColumnCount, 2, x);
var mb = matrix*mx;
AssertHelpers.AlmostEqualRelative(mb[0, 0], b[0], 13);
AssertHelpers.AlmostEqualRelative(mb[1, 0], b[1], 13);
AssertHelpers.AlmostEqualRelative(mb[2, 0], b[2], 13);
AssertHelpers.AlmostEqualRelative(mb[0, 1], b[3], 13);
AssertHelpers.AlmostEqualRelative(mb[1, 1], b[4], 13);
AssertHelpers.AlmostEqualRelative(mb[2, 1], b[5], 13);
}
/// <summary>
/// Can solve Ax=b using thin QR factorization with a tall A matrix
/// using a factored A matrix with a work array.
/// </summary>
[Test]
public void CanSolveUsingThinQRTallMatrixOnFactoredMatrixWithWorkArray()
{
var matrix = _matrices["Tall3x2"];
var a = new Complex[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var tau = new Complex[matrix.ColumnCount];
var r = new Complex[matrix.ColumnCount*matrix.ColumnCount];
var work = new Complex[2048];
Control.LinearAlgebraProvider.ThinQRFactor(a, matrix.RowCount, matrix.ColumnCount, r, tau, work);
var b = new[] {new Complex(1.0, 0), 2.0, 3.0, 4.0, 5.0, 6.0};
var x = new Complex[matrix.ColumnCount*2];
Control.LinearAlgebraProvider.QRSolveFactored(a, r, matrix.RowCount, matrix.ColumnCount, tau, b, 2, x, work, QRMethod.Thin);
var mb = new DenseMatrix(matrix.RowCount, 2, b);
var test = (matrix.Transpose()*matrix).Inverse()*matrix.Transpose()*mb;
AssertHelpers.AlmostEqualRelative(test[0, 0], x[0], 13);
AssertHelpers.AlmostEqualRelative(test[1, 0], x[1], 13);
AssertHelpers.AlmostEqualRelative(test[0, 1], x[2], 13);
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 13);
}
/// <summary>
/// Can compute the SVD factorization of a square matrix.
/// </summary>
@ -1441,129 +978,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Complex
AssertHelpers.AlmostEqualRelative(matrix[1, 2], result[1, 2], 14);
}
/// <summary>
/// Can compute the SVD factorization of a square matrix using
/// a work array.
/// </summary>
[Test]
public void CanComputeSVDFactorizationOfSquareMatrixWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new Complex[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var s = new Complex[matrix.RowCount];
var u = new Complex[matrix.RowCount*matrix.RowCount];
var vt = new Complex[matrix.ColumnCount*matrix.ColumnCount];
#if CUDA
Complex[] work = null;
#else
var work = new Complex[100];
#endif
Control.LinearAlgebraProvider.SingularValueDecomposition(true, a, matrix.RowCount, matrix.ColumnCount, s, u, vt, work);
var w = new DenseMatrix(matrix.RowCount, matrix.ColumnCount);
for (var index = 0; index < s.Length; index++)
{
w[index, index] = s[index];
}
var mU = new DenseMatrix(matrix.RowCount, matrix.RowCount, u);
var mV = new DenseMatrix(matrix.ColumnCount, matrix.ColumnCount, vt);
var result = mU*w*mV;
AssertHelpers.AlmostEqualRelative(matrix[0, 0], result[0, 0], 13);
AssertHelpers.AlmostEqualRelative(matrix[1, 0], result[1, 0], 13);
AssertHelpers.AlmostEqualRelative(matrix[2, 0], result[2, 0], 13);
AssertHelpers.AlmostEqualRelative(matrix[0, 1], result[0, 1], 13);
AssertHelpers.AlmostEqualRelative(matrix[1, 1], result[1, 1], 13);
AssertHelpers.AlmostEqualRelative(matrix[2, 1], result[2, 1], 13);
AssertHelpers.AlmostEqualRelative(matrix[0, 2], result[0, 2], 13);
AssertHelpers.AlmostEqualRelative(matrix[1, 2], result[1, 2], 13);
AssertHelpers.AlmostEqualRelative(matrix[2, 2], result[2, 2], 13);
}
/// <summary>
/// Can compute the SVD factorization of a tall matrix using
/// a work array.
/// </summary>
[Test]
public void CanComputeSVDFactorizationOfTallMatrixWithWorkArray()
{
var matrix = _matrices["Tall3x2"];
var a = new Complex[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var s = new Complex[matrix.ColumnCount];
var u = new Complex[matrix.RowCount*matrix.RowCount];
var vt = new Complex[matrix.ColumnCount*matrix.ColumnCount];
#if CUDA
Complex[] work = null;
#else
var work = new Complex[100];
#endif
Control.LinearAlgebraProvider.SingularValueDecomposition(true, a, matrix.RowCount, matrix.ColumnCount, s, u, vt, work);
var w = new DenseMatrix(matrix.RowCount, matrix.ColumnCount);
for (var index = 0; index < s.Length; index++)
{
w[index, index] = s[index];
}
var mU = new DenseMatrix(matrix.RowCount, matrix.RowCount, u);
var mV = new DenseMatrix(matrix.ColumnCount, matrix.ColumnCount, vt);
var result = mU*w*mV;
AssertHelpers.AlmostEqualRelative(matrix[0, 0], result[0, 0], 14);
AssertHelpers.AlmostEqualRelative(matrix[1, 0], result[1, 0], 14);
AssertHelpers.AlmostEqualRelative(matrix[2, 0], result[2, 0], 14);
AssertHelpers.AlmostEqualRelative(matrix[0, 1], result[0, 1], 14);
AssertHelpers.AlmostEqualRelative(matrix[1, 1], result[1, 1], 14);
AssertHelpers.AlmostEqualRelative(matrix[2, 1], result[2, 1], 14);
}
/// <summary>
/// Can compute the SVD factorization of a wide matrix using
/// a work array.
/// </summary>
[Test]
public void CanComputeSVDFactorizationOfWideMatrixWithWorkArray()
{
var matrix = _matrices["Wide2x3"];
var a = new Complex[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var s = new Complex[matrix.RowCount];
var u = new Complex[matrix.RowCount*matrix.RowCount];
var vt = new Complex[matrix.ColumnCount*matrix.ColumnCount];
#if CUDA
Complex[] work = null;
#else
var work = new Complex[100];
#endif
Control.LinearAlgebraProvider.SingularValueDecomposition(true, a, matrix.RowCount, matrix.ColumnCount, s, u, vt, work);
var w = new DenseMatrix(matrix.RowCount, matrix.ColumnCount);
for (var index = 0; index < s.Length; index++)
{
w[index, index] = s[index];
}
var mU = new DenseMatrix(matrix.RowCount, matrix.RowCount, u);
var mV = new DenseMatrix(matrix.ColumnCount, matrix.ColumnCount, vt);
var result = mU*w*mV;
AssertHelpers.AlmostEqualRelative(matrix[0, 0], result[0, 0], 14);
AssertHelpers.AlmostEqualRelative(matrix[1, 0], result[1, 0], 14);
AssertHelpers.AlmostEqualRelative(matrix[0, 1], result[0, 1], 14);
AssertHelpers.AlmostEqualRelative(matrix[1, 1], result[1, 1], 14);
AssertHelpers.AlmostEqualRelative(matrix[0, 2], result[0, 2], 14);
AssertHelpers.AlmostEqualRelative(matrix[1, 2], result[1, 2], 14);
}
/// <summary>
/// Can solve Ax=b using SVD factorization with a square A matrix.
/// </summary>

558
src/UnitTests/LinearAlgebraProviderTests/Complex32/LinearAlgebraProviderTests.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
// Copyright (c) 2009-2015 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -437,68 +437,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Complex32
AssertHelpers.AlmostEqualRelative(a[8], -0.113636363636364f, 5);
}
/// <summary>
/// Can compute the inverse of a matrix using LU factorization
/// with a work array.
/// </summary>
[Test]
public void CanComputeLuInverseWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new Complex32[matrix.RowCount*matrix.RowCount];
Array.Copy(matrix.Values, a, a.Length);
#if CUDA
Complex32[] work = null;
#else
var work = new Complex32[matrix.RowCount];
#endif
Control.LinearAlgebraProvider.LUInverse(a, matrix.RowCount, work);
AssertHelpers.AlmostEqualRelative(a[0], -0.454545454545454f, 5);
AssertHelpers.AlmostEqualRelative(a[1], -0.909090909090908f, 5);
AssertHelpers.AlmostEqualRelative(a[2], 0.454545454545454f, 5);
AssertHelpers.AlmostEqualRelative(a[3], -0.340909090909090f, 5);
AssertHelpers.AlmostEqualRelative(a[4], -2.045454545454543f, 5);
AssertHelpers.AlmostEqualRelative(a[5], 1.477272727272726f, 5);
AssertHelpers.AlmostEqualRelative(a[6], -0.113636363636364f, 5);
AssertHelpers.AlmostEqualRelative(a[7], 0.227272727272727f, 5);
AssertHelpers.AlmostEqualRelative(a[8], -0.113636363636364f, 5);
}
/// <summary>
/// Can compute the inverse of a matrix using LU factorization
/// using a previously factored matrix with a work array.
/// </summary>
[Test]
public void CanComputeLuInverseOnFactoredMatrixWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new Complex32[matrix.RowCount*matrix.RowCount];
Array.Copy(matrix.Values, a, a.Length);
var ipiv = new int[matrix.RowCount];
Control.LinearAlgebraProvider.LUFactor(a, matrix.RowCount, ipiv);
#if CUDA
Complex32[] work = null;
#else
var work = new Complex32[matrix.RowCount];
#endif
Control.LinearAlgebraProvider.LUInverseFactored(a, matrix.RowCount, ipiv, work);
AssertHelpers.AlmostEqualRelative(a[0], -0.454545454545454f, 5);
AssertHelpers.AlmostEqualRelative(a[1], -0.909090909090908f, 5);
AssertHelpers.AlmostEqualRelative(a[2], 0.454545454545454f, 5);
AssertHelpers.AlmostEqualRelative(a[3], -0.340909090909090f, 5);
AssertHelpers.AlmostEqualRelative(a[4], -2.045454545454543f, 5);
AssertHelpers.AlmostEqualRelative(a[5], 1.477272727272726f, 5);
AssertHelpers.AlmostEqualRelative(a[6], -0.113636363636364f, 5);
AssertHelpers.AlmostEqualRelative(a[7], 0.227272727272727f, 5);
AssertHelpers.AlmostEqualRelative(a[8], -0.113636363636364f, 5);
}
/// <summary>
/// Can solve Ax=b using LU factorization.
/// </summary>
@ -696,90 +634,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Complex32
}
}
/// <summary>
/// Can compute QR factorization of a square matrix using a work array.
/// </summary>
[Test]
public void CanComputeQRFactorSquareMatrixWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var r = new Complex32[matrix.RowCount*matrix.ColumnCount];
var tau = new Complex32[3];
var q = new Complex32[matrix.RowCount*matrix.RowCount];
Array.Copy(matrix.Values, r, r.Length);
var work = new Complex32[matrix.ColumnCount*Control.BlockSize];
Control.LinearAlgebraProvider.QRFactor(r, matrix.RowCount, matrix.ColumnCount, q, tau, work);
var mq = new DenseMatrix(matrix.RowCount, matrix.RowCount, q);
var mr = new DenseMatrix(matrix.RowCount, matrix.ColumnCount, r).UpperTriangle();
var a = mq*mr;
for (var row = 0; row < matrix.RowCount; row++)
{
for (var col = 0; col < matrix.ColumnCount; col++)
{
AssertHelpers.AlmostEqualRelative(matrix[row, col], a[row, col], 5);
}
}
}
/// <summary>
/// Can compute QR factorization of a tall matrix using a work matrix.
/// </summary>
[Test]
public void CanComputeQRFactorTallMatrixWithWorkArray()
{
var matrix = _matrices["Tall3x2"];
var r = new Complex32[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, r, r.Length);
var tau = new Complex32[3];
var q = new Complex32[matrix.RowCount*matrix.RowCount];
var work = new Complex32[matrix.ColumnCount*Control.BlockSize];
Control.LinearAlgebraProvider.QRFactor(r, matrix.RowCount, matrix.ColumnCount, q, tau, work);
var mr = new DenseMatrix(matrix.RowCount, matrix.ColumnCount, r).UpperTriangle();
var mq = new DenseMatrix(matrix.RowCount, matrix.RowCount, q);
var a = mq*mr;
for (var row = 0; row < matrix.RowCount; row++)
{
for (var col = 0; col < matrix.ColumnCount; col++)
{
AssertHelpers.AlmostEqualRelative(matrix[row, col], a[row, col], 5);
}
}
}
/// <summary>
/// Can compute QR factorization of a wide matrix using a work matrix.
/// </summary>
[Test]
public void CanComputeQRFactorWideMatrixWithWorkArray()
{
var matrix = _matrices["Wide2x3"];
var r = new Complex32[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, r, r.Length);
var tau = new Complex32[3];
var q = new Complex32[matrix.RowCount*matrix.RowCount];
var work = new Complex32[matrix.ColumnCount*Control.BlockSize];
Control.LinearAlgebraProvider.QRFactor(r, matrix.RowCount, matrix.ColumnCount, q, tau, work);
var mr = new DenseMatrix(matrix.RowCount, matrix.ColumnCount, r).UpperTriangle();
var mq = new DenseMatrix(matrix.RowCount, matrix.RowCount, q);
var a = mq*mr;
for (var row = 0; row < matrix.RowCount; row++)
{
for (var col = 0; col < matrix.ColumnCount; col++)
{
AssertHelpers.AlmostEqualRelative(matrix[row, col], a[row, col], 5);
}
}
}
/// <summary>
/// Can compute thin QR factorization of a square matrix.
/// </summary>
@ -834,61 +688,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Complex32
}
}
/// <summary>
/// Can compute thin QR factorization of a square matrix using a work array.
/// </summary>
[Test]
public void CanComputeThinQRFactorSquareMatrixWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var r = new Complex32[matrix.ColumnCount*matrix.ColumnCount];
var tau = new Complex32[3];
var q = new Complex32[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, q, q.Length);
var work = new Complex32[matrix.ColumnCount*Control.BlockSize];
Control.LinearAlgebraProvider.ThinQRFactor(q, matrix.RowCount, matrix.ColumnCount, r, tau, work);
var mq = new DenseMatrix(matrix.RowCount, matrix.ColumnCount, q);
var mr = new DenseMatrix(matrix.ColumnCount, matrix.ColumnCount, r);
var a = mq*mr;
for (var row = 0; row < matrix.RowCount; row++)
{
for (var col = 0; col < matrix.ColumnCount; col++)
{
AssertHelpers.AlmostEqualRelative(matrix[row, col], a[row, col], 5);
}
}
}
/// <summary>
/// Can compute thin QR factorization of a tall matrix using a work matrix.
/// </summary>
[Test]
public void CanComputeThinQRFactorTallMatrixWithWorkArray()
{
var matrix = _matrices["Tall3x2"];
var r = new Complex32[matrix.ColumnCount*matrix.ColumnCount];
var tau = new Complex32[3];
var q = new Complex32[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, q, q.Length);
var work = new Complex32[matrix.ColumnCount*Control.BlockSize];
Control.LinearAlgebraProvider.ThinQRFactor(q, matrix.RowCount, matrix.ColumnCount, r, tau, work);
var mq = new DenseMatrix(matrix.RowCount, matrix.ColumnCount, q);
var mr = new DenseMatrix(matrix.ColumnCount, matrix.ColumnCount, r);
var a = mq*mr;
for (var row = 0; row < matrix.RowCount; row++)
{
for (var col = 0; col < matrix.ColumnCount; col++)
{
AssertHelpers.AlmostEqualRelative(matrix[row, col], a[row, col], 5);
}
}
}
/// <summary>
/// Can solve Ax=b using QR factorization with a square A matrix.
/// </summary>
@ -941,62 +740,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Complex32
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 5);
}
/// <summary>
/// Can solve Ax=b using QR factorization with a square A matrix
/// using a work array.
/// </summary>
[Test]
public void CanSolveUsingQRSquareMatrixUsingWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new Complex32[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var b = new[] {new Complex32(1.0f, 0.0f), 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
var x = new Complex32[matrix.ColumnCount*2];
var work = new Complex32[matrix.RowCount*matrix.RowCount];
Control.LinearAlgebraProvider.QRSolve(a, matrix.RowCount, matrix.ColumnCount, b, 2, x, work);
NotModified(3, 3, a, matrix);
var mx = new DenseMatrix(matrix.ColumnCount, 2, x);
var mb = matrix*mx;
AssertHelpers.AlmostEqualRelative(mb[0, 0], b[0], 5);
AssertHelpers.AlmostEqualRelative(mb[1, 0], b[1], 5);
AssertHelpers.AlmostEqualRelative(mb[2, 0], b[2], 5);
AssertHelpers.AlmostEqualRelative(mb[0, 1], b[3], 5);
AssertHelpers.AlmostEqualRelative(mb[1, 1], b[4], 4);
AssertHelpers.AlmostEqualRelative(mb[2, 1], b[5], 4);
}
/// <summary>
/// Can solve Ax=b using QR factorization with a tall A matrix
/// using a work array.
/// </summary>
[Test]
public void CanSolveUsingQRTallMatrixUsingWorkArray()
{
var matrix = _matrices["Tall3x2"];
var a = new Complex32[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var b = new[] {new Complex32(1.0f, 0.0f), 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
var x = new Complex32[matrix.ColumnCount*2];
var work = new Complex32[matrix.RowCount*matrix.RowCount];
Control.LinearAlgebraProvider.QRSolve(a, matrix.RowCount, matrix.ColumnCount, b, 2, x, work);
NotModified(3, 2, a, matrix);
var mb = new DenseMatrix(matrix.RowCount, 2, b);
var test = (matrix.Transpose()*matrix).Inverse()*matrix.Transpose()*mb;
AssertHelpers.AlmostEqualRelative(test[0, 0], x[0], 5);
AssertHelpers.AlmostEqualRelative(test[1, 0], x[1], 5);
AssertHelpers.AlmostEqualRelative(test[0, 1], x[2], 5);
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 5);
}
/// <summary>
/// Can solve Ax=b using QR factorization with a square A matrix
/// using a factored A matrix.
@ -1055,66 +798,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Complex32
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 5);
}
/// <summary>
/// Can solve Ax=b using QR factorization with a square A matrix
/// using a factored A matrix with a work array.
/// </summary>
[Test]
public void CanSolveUsingQRSquareMatrixOnFactoredMatrixWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new Complex32[matrix.RowCount*matrix.RowCount];
Array.Copy(matrix.Values, a, a.Length);
var tau = new Complex32[matrix.ColumnCount];
var q = new Complex32[matrix.ColumnCount*matrix.ColumnCount];
var work = new Complex32[2048];
Control.LinearAlgebraProvider.QRFactor(a, matrix.RowCount, matrix.ColumnCount, q, tau, work);
var b = new[] {new Complex32(1.0f, 0.0f), 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
var x = new Complex32[matrix.ColumnCount*2];
Control.LinearAlgebraProvider.QRSolveFactored(q, a, matrix.RowCount, matrix.ColumnCount, tau, b, 2, x, work);
var mx = new DenseMatrix(matrix.ColumnCount, 2, x);
var mb = matrix*mx;
AssertHelpers.AlmostEqualRelative(mb[0, 0], b[0], 5);
AssertHelpers.AlmostEqualRelative(mb[1, 0], b[1], 5);
AssertHelpers.AlmostEqualRelative(mb[2, 0], b[2], 5);
AssertHelpers.AlmostEqualRelative(mb[0, 1], b[3], 5);
AssertHelpers.AlmostEqualRelative(mb[1, 1], b[4], 4);
AssertHelpers.AlmostEqualRelative(mb[2, 1], b[5], 4);
}
/// <summary>
/// Can solve Ax=b using QR factorization with a tall A matrix
/// using a factored A matrix with a work array.
/// </summary>
[Test]
public void CanSolveUsingQRTallMatrixOnFactoredMatrixWithWorkArray()
{
var matrix = _matrices["Tall3x2"];
var a = new Complex32[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var tau = new Complex32[matrix.ColumnCount];
var q = new Complex32[matrix.RowCount*matrix.RowCount];
var work = new Complex32[2048];
Control.LinearAlgebraProvider.QRFactor(a, matrix.RowCount, matrix.ColumnCount, q, tau, work);
var b = new[] {new Complex32(1.0f, 0.0f), 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
var x = new Complex32[matrix.ColumnCount*2];
Control.LinearAlgebraProvider.QRSolveFactored(q, a, matrix.RowCount, matrix.ColumnCount, tau, b, 2, x, work);
var mb = new DenseMatrix(matrix.RowCount, 2, b);
var test = (matrix.Transpose()*matrix).Inverse()*matrix.Transpose()*mb;
AssertHelpers.AlmostEqualRelative(test[0, 0], x[0], 5);
AssertHelpers.AlmostEqualRelative(test[1, 0], x[1], 5);
AssertHelpers.AlmostEqualRelative(test[0, 1], x[2], 5);
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 5);
}
/// <summary>
/// Can solve Ax=b using thin QR factorization with a square A matrix.
/// </summary>
@ -1167,62 +850,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Complex32
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 5);
}
/// <summary>
/// Can solve Ax=b using thin QR factorization with a square A matrix
/// using a work array.
/// </summary>
[Test]
public void CanSolveUsingThinQRSquareMatrixUsingWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new Complex32[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var b = new[] {new Complex32(1.0f, 0.0f), 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
var x = new Complex32[matrix.ColumnCount*2];
var work = new Complex32[matrix.RowCount*matrix.ColumnCount];
Control.LinearAlgebraProvider.QRSolve(a, matrix.RowCount, matrix.ColumnCount, b, 2, x, work, QRMethod.Thin);
NotModified(3, 3, a, matrix);
var mx = new DenseMatrix(matrix.ColumnCount, 2, x);
var mb = matrix*mx;
AssertHelpers.AlmostEqualRelative(mb[0, 0], b[0], 5);
AssertHelpers.AlmostEqualRelative(mb[1, 0], b[1], 5);
AssertHelpers.AlmostEqualRelative(mb[2, 0], b[2], 5);
AssertHelpers.AlmostEqualRelative(mb[0, 1], b[3], 5);
AssertHelpers.AlmostEqualRelative(mb[1, 1], b[4], 4);
AssertHelpers.AlmostEqualRelative(mb[2, 1], b[5], 4);
}
/// <summary>
/// Can solve Ax=b using thin QR factorization with a tall A matrix
/// using a work array.
/// </summary>
[Test]
public void CanSolveUsingThinQRTallMatrixUsingWorkArray()
{
var matrix = _matrices["Tall3x2"];
var a = new Complex32[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var b = new[] {new Complex32(1.0f, 0.0f), 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
var x = new Complex32[matrix.ColumnCount*2];
var work = new Complex32[matrix.RowCount*matrix.ColumnCount];
Control.LinearAlgebraProvider.QRSolve(a, matrix.RowCount, matrix.ColumnCount, b, 2, x, work, QRMethod.Thin);
NotModified(3, 2, a, matrix);
var mb = new DenseMatrix(matrix.RowCount, 2, b);
var test = (matrix.Transpose()*matrix).Inverse()*matrix.Transpose()*mb;
AssertHelpers.AlmostEqualRelative(test[0, 0], x[0], 5);
AssertHelpers.AlmostEqualRelative(test[1, 0], x[1], 5);
AssertHelpers.AlmostEqualRelative(test[0, 1], x[2], 5);
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 5);
}
/// <summary>
/// Can solve Ax=b using thin QR factorization with a square A matrix
/// using a factored A matrix.
@ -1281,66 +908,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Complex32
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 5);
}
/// <summary>
/// Can solve Ax=b using thin QR factorization with a square A matrix
/// using a factored A matrix with a work array.
/// </summary>
[Test]
public void CanSolveUsingThinQRSquareMatrixOnFactoredMatrixWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new Complex32[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var tau = new Complex32[matrix.ColumnCount];
var r = new Complex32[matrix.ColumnCount*matrix.ColumnCount];
var work = new Complex32[2048];
Control.LinearAlgebraProvider.ThinQRFactor(a, matrix.RowCount, matrix.ColumnCount, r, tau, work);
var b = new[] {new Complex32(1.0f, 0.0f), 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
var x = new Complex32[matrix.ColumnCount*2];
Control.LinearAlgebraProvider.QRSolveFactored(a, r, matrix.RowCount, matrix.ColumnCount, tau, b, 2, x, work, QRMethod.Thin);
var mx = new DenseMatrix(matrix.ColumnCount, 2, x);
var mb = matrix*mx;
AssertHelpers.AlmostEqualRelative(mb[0, 0], b[0], 5);
AssertHelpers.AlmostEqualRelative(mb[1, 0], b[1], 5);
AssertHelpers.AlmostEqualRelative(mb[2, 0], b[2], 5);
AssertHelpers.AlmostEqualRelative(mb[0, 1], b[3], 5);
AssertHelpers.AlmostEqualRelative(mb[1, 1], b[4], 4);
AssertHelpers.AlmostEqualRelative(mb[2, 1], b[5], 4);
}
/// <summary>
/// Can solve Ax=b using thin QR factorization with a tall A matrix
/// using a factored A matrix with a work array.
/// </summary>
[Test]
public void CanSolveUsingThinQRTallMatrixOnFactoredMatrixWithWorkArray()
{
var matrix = _matrices["Tall3x2"];
var a = new Complex32[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var tau = new Complex32[matrix.ColumnCount];
var r = new Complex32[matrix.ColumnCount*matrix.ColumnCount];
var work = new Complex32[2048];
Control.LinearAlgebraProvider.ThinQRFactor(a, matrix.RowCount, matrix.ColumnCount, r, tau, work);
var b = new[] {new Complex32(1.0f, 0.0f), 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
var x = new Complex32[matrix.ColumnCount*2];
Control.LinearAlgebraProvider.QRSolveFactored(a, r, matrix.RowCount, matrix.ColumnCount, tau, b, 2, x, work, QRMethod.Thin);
var mb = new DenseMatrix(matrix.RowCount, 2, b);
var test = (matrix.Transpose()*matrix).Inverse()*matrix.Transpose()*mb;
AssertHelpers.AlmostEqualRelative(test[0, 0], x[0], 5);
AssertHelpers.AlmostEqualRelative(test[1, 0], x[1], 5);
AssertHelpers.AlmostEqualRelative(test[0, 1], x[2], 5);
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 5);
}
/// <summary>
/// Can compute the SVD factorization of a square matrix.
/// </summary>
@ -1446,129 +1013,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Complex32
AssertHelpers.AlmostEqualRelative(matrix[1, 2], result[1, 2], 4);
}
/// <summary>
/// Can compute the SVD factorization of a square matrix using
/// a work array.
/// </summary>
[Test]
public void CanComputeSVDFactorizationOfSquareMatrixWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new Complex32[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var s = new Complex32[matrix.RowCount];
var u = new Complex32[matrix.RowCount*matrix.RowCount];
var vt = new Complex32[matrix.ColumnCount*matrix.ColumnCount];
#if CUDA
Complex32[] work = null;
#else
var work = new Complex32[100];
#endif
Control.LinearAlgebraProvider.SingularValueDecomposition(true, a, matrix.RowCount, matrix.ColumnCount, s, u, vt, work);
var w = new DenseMatrix(matrix.RowCount, matrix.ColumnCount);
for (var index = 0; index < s.Length; index++)
{
w[index, index] = s[index];
}
var mU = new DenseMatrix(matrix.RowCount, matrix.RowCount, u);
var mV = new DenseMatrix(matrix.ColumnCount, matrix.ColumnCount, vt);
var result = mU*w*mV;
AssertHelpers.AlmostEqualRelative(matrix[0, 0], result[0, 0], 5);
AssertHelpers.AlmostEqualRelative(matrix[1, 0], result[1, 0], 5);
AssertHelpers.AlmostEqualRelative(matrix[2, 0], result[2, 0], 5);
AssertHelpers.AlmostEqualRelative(matrix[0, 1], result[0, 1], 5);
AssertHelpers.AlmostEqualRelative(matrix[1, 1], result[1, 1], 5);
AssertHelpers.AlmostEqualRelative(matrix[2, 1], result[2, 1], 5);
AssertHelpers.AlmostEqualRelative(matrix[0, 2], result[0, 2], 5);
AssertHelpers.AlmostEqualRelative(matrix[1, 2], result[1, 2], 5);
AssertHelpers.AlmostEqualRelative(matrix[2, 2], result[2, 2], 5);
}
/// <summary>
/// Can compute the SVD factorization of a tall matrix using
/// a work array.
/// </summary>
[Test]
public void CanComputeSVDFactorizationOfTallMatrixWithWorkArray()
{
var matrix = _matrices["Tall3x2"];
var a = new Complex32[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var s = new Complex32[matrix.ColumnCount];
var u = new Complex32[matrix.RowCount*matrix.RowCount];
var vt = new Complex32[matrix.ColumnCount*matrix.ColumnCount];
#if CUDA
Complex32[] work = null;
#else
var work = new Complex32[100];
#endif
Control.LinearAlgebraProvider.SingularValueDecomposition(true, a, matrix.RowCount, matrix.ColumnCount, s, u, vt, work);
var w = new DenseMatrix(matrix.RowCount, matrix.ColumnCount);
for (var index = 0; index < s.Length; index++)
{
w[index, index] = s[index];
}
var mU = new DenseMatrix(matrix.RowCount, matrix.RowCount, u);
var mV = new DenseMatrix(matrix.ColumnCount, matrix.ColumnCount, vt);
var result = mU*w*mV;
AssertHelpers.AlmostEqualRelative(matrix[0, 0], result[0, 0], 5);
AssertHelpers.AlmostEqualRelative(matrix[1, 0], result[1, 0], 5);
AssertHelpers.AlmostEqualRelative(matrix[2, 0], result[2, 0], 5);
AssertHelpers.AlmostEqualRelative(matrix[0, 1], result[0, 1], 5);
AssertHelpers.AlmostEqualRelative(matrix[1, 1], result[1, 1], 5);
AssertHelpers.AlmostEqualRelative(matrix[2, 1], result[2, 1], 4);
}
/// <summary>
/// Can compute the SVD factorization of a wide matrix using
/// a work array.
/// </summary>
[Test]
public void CanComputeSVDFactorizationOfWideMatrixWithWorkArray()
{
var matrix = _matrices["Wide2x3"];
var a = new Complex32[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var s = new Complex32[matrix.RowCount];
var u = new Complex32[matrix.RowCount*matrix.RowCount];
var vt = new Complex32[matrix.ColumnCount*matrix.ColumnCount];
#if CUDA
Complex32[] work = null;
#else
var work = new Complex32[100];
#endif
Control.LinearAlgebraProvider.SingularValueDecomposition(true, a, matrix.RowCount, matrix.ColumnCount, s, u, vt, work);
var w = new DenseMatrix(matrix.RowCount, matrix.ColumnCount);
for (var index = 0; index < s.Length; index++)
{
w[index, index] = s[index];
}
var mU = new DenseMatrix(matrix.RowCount, matrix.RowCount, u);
var mV = new DenseMatrix(matrix.ColumnCount, matrix.ColumnCount, vt);
var result = mU*w*mV;
AssertHelpers.AlmostEqualRelative(matrix[0, 0], result[0, 0], 5);
AssertHelpers.AlmostEqualRelative(matrix[1, 0], result[1, 0], 5);
AssertHelpers.AlmostEqualRelative(matrix[0, 1], result[0, 1], 5);
AssertHelpers.AlmostEqualRelative(matrix[1, 1], result[1, 1], 5);
AssertHelpers.AlmostEqualRelative(matrix[0, 2], result[0, 2], 5);
AssertHelpers.AlmostEqualRelative(matrix[1, 2], result[1, 2], 4);
}
/// <summary>
/// Can solve Ax=b using SVD factorization with a square A matrix.
/// </summary>

558
src/UnitTests/LinearAlgebraProviderTests/Double/LinearAlgebraProviderTests.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
// Copyright (c) 2009-2015 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -427,68 +427,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Double
AssertHelpers.AlmostEqualRelative(a[8], -0.113636363636364, 13);
}
/// <summary>
/// Can compute the inverse of a matrix using LU factorization
/// with a work array.
/// </summary>
[Test]
public void CanComputeLuInverseWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new double[matrix.RowCount*matrix.RowCount];
Array.Copy(matrix.Values, a, a.Length);
#if CUDA
double[] work = null;
#else
var work = new double[matrix.RowCount];
#endif
Control.LinearAlgebraProvider.LUInverse(a, matrix.RowCount, work);
AssertHelpers.AlmostEqualRelative(a[0], -0.454545454545454, 13);
AssertHelpers.AlmostEqualRelative(a[1], -0.909090909090908, 13);
AssertHelpers.AlmostEqualRelative(a[2], 0.454545454545454, 13);
AssertHelpers.AlmostEqualRelative(a[3], -0.340909090909090, 13);
AssertHelpers.AlmostEqualRelative(a[4], -2.045454545454543, 13);
AssertHelpers.AlmostEqualRelative(a[5], 1.477272727272726, 13);
AssertHelpers.AlmostEqualRelative(a[6], -0.113636363636364, 13);
AssertHelpers.AlmostEqualRelative(a[7], 0.227272727272727, 13);
AssertHelpers.AlmostEqualRelative(a[8], -0.113636363636364, 13);
}
/// <summary>
/// Can compute the inverse of a matrix using LU factorization
/// using a previously factored matrix with a work array.
/// </summary>
[Test]
public void CanComputeLuInverseOnFactoredMatrixWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new double[matrix.RowCount*matrix.RowCount];
Array.Copy(matrix.Values, a, a.Length);
var ipiv = new int[matrix.RowCount];
Control.LinearAlgebraProvider.LUFactor(a, matrix.RowCount, ipiv);
#if CUDA
double[] work = null;
#else
var work = new double[matrix.RowCount];
#endif
Control.LinearAlgebraProvider.LUInverseFactored(a, matrix.RowCount, ipiv, work);
AssertHelpers.AlmostEqualRelative(a[0], -0.454545454545454, 13);
AssertHelpers.AlmostEqualRelative(a[1], -0.909090909090908, 13);
AssertHelpers.AlmostEqualRelative(a[2], 0.454545454545454, 13);
AssertHelpers.AlmostEqualRelative(a[3], -0.340909090909090, 13);
AssertHelpers.AlmostEqualRelative(a[4], -2.045454545454543, 13);
AssertHelpers.AlmostEqualRelative(a[5], 1.477272727272726, 13);
AssertHelpers.AlmostEqualRelative(a[6], -0.113636363636364, 13);
AssertHelpers.AlmostEqualRelative(a[7], 0.227272727272727, 13);
AssertHelpers.AlmostEqualRelative(a[8], -0.113636363636364, 13);
}
/// <summary>
/// Can solve Ax=b using LU factorization.
/// </summary>
@ -686,90 +624,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Double
}
}
/// <summary>
/// Can compute QR factorization of a square matrix using a work array.
/// </summary>
[Test]
public void CanComputeQRFactorSquareMatrixWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var r = new double[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, r, r.Length);
var tau = new double[3];
var q = new double[matrix.RowCount*matrix.RowCount];
var work = new double[matrix.ColumnCount*Control.BlockSize];
Control.LinearAlgebraProvider.QRFactor(r, matrix.RowCount, matrix.ColumnCount, q, tau, work);
var mq = Matrix<double>.Build.Dense(matrix.RowCount, matrix.RowCount, q);
var mr = Matrix<double>.Build.Dense(matrix.RowCount, matrix.ColumnCount, r).UpperTriangle();
var a = mq*mr;
for (var row = 0; row < matrix.RowCount; row++)
{
for (var col = 0; col < matrix.ColumnCount; col++)
{
AssertHelpers.AlmostEqualRelative(matrix[row, col], a[row, col], 14);
}
}
}
/// <summary>
/// Can compute QR factorization of a tall matrix using a work matrix.
/// </summary>
[Test]
public void CanComputeQRFactorTallMatrixWithWorkArray()
{
var matrix = _matrices["Tall3x2"];
var r = new double[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, r, r.Length);
var tau = new double[3];
var q = new double[matrix.RowCount*matrix.RowCount];
var work = new double[matrix.ColumnCount*Control.BlockSize];
Control.LinearAlgebraProvider.QRFactor(r, matrix.RowCount, matrix.ColumnCount, q, tau, work);
var mr = Matrix<double>.Build.Dense(matrix.RowCount, matrix.ColumnCount, r).UpperTriangle();
var mq = Matrix<double>.Build.Dense(matrix.RowCount, matrix.RowCount, q);
var a = mq*mr;
for (var row = 0; row < matrix.RowCount; row++)
{
for (var col = 0; col < matrix.ColumnCount; col++)
{
AssertHelpers.AlmostEqualRelative(matrix[row, col], a[row, col], 14);
}
}
}
/// <summary>
/// Can compute QR factorization of a wide matrix using a work matrix.
/// </summary>
[Test]
public void CanComputeQRFactorWideMatrixWithWorkArray()
{
var matrix = _matrices["Wide2x3"];
var r = new double[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, r, r.Length);
var tau = new double[3];
var q = new double[matrix.RowCount*matrix.RowCount];
var work = new double[matrix.ColumnCount*Control.BlockSize];
Control.LinearAlgebraProvider.QRFactor(r, matrix.RowCount, matrix.ColumnCount, q, tau, work);
var mr = Matrix<double>.Build.Dense(matrix.RowCount, matrix.ColumnCount, r).UpperTriangle();
var mq = Matrix<double>.Build.Dense(matrix.RowCount, matrix.RowCount, q);
var a = mq*mr;
for (var row = 0; row < matrix.RowCount; row++)
{
for (var col = 0; col < matrix.ColumnCount; col++)
{
AssertHelpers.AlmostEqualRelative(matrix[row, col], a[row, col], 14);
}
}
}
/// <summary>
/// Can compute thin QR factorization of a square matrix.
/// </summary>
@ -824,61 +678,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Double
}
}
/// <summary>
/// Can compute thin QR factorization of a square matrix using a work array.
/// </summary>
[Test]
public void CanComputeThinQRFactorSquareMatrixWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var r = new double[matrix.ColumnCount*matrix.ColumnCount];
var tau = new double[3];
var q = new double[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, q, q.Length);
var work = new double[matrix.ColumnCount*Control.BlockSize];
Control.LinearAlgebraProvider.ThinQRFactor(q, matrix.RowCount, matrix.ColumnCount, r, tau, work);
var mq = Matrix<double>.Build.Dense(matrix.RowCount, matrix.ColumnCount, q);
var mr = Matrix<double>.Build.Dense(matrix.ColumnCount, matrix.ColumnCount, r);
var a = mq*mr;
for (var row = 0; row < matrix.RowCount; row++)
{
for (var col = 0; col < matrix.ColumnCount; col++)
{
AssertHelpers.AlmostEqualRelative(matrix[row, col], a[row, col], 14);
}
}
}
/// <summary>
/// Can compute thin QR factorization of a tall matrix using a work matrix.
/// </summary>
[Test]
public void CanComputeThinQRFactorTallMatrixWithWorkArray()
{
var matrix = _matrices["Tall3x2"];
var r = new double[matrix.ColumnCount*matrix.ColumnCount];
var tau = new double[3];
var q = new double[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, q, q.Length);
var work = new double[matrix.ColumnCount*Control.BlockSize];
Control.LinearAlgebraProvider.ThinQRFactor(q, matrix.RowCount, matrix.ColumnCount, r, tau, work);
var mq = Matrix<double>.Build.Dense(matrix.RowCount, matrix.ColumnCount, q);
var mr = Matrix<double>.Build.Dense(matrix.ColumnCount, matrix.ColumnCount, r);
var a = mq*mr;
for (var row = 0; row < matrix.RowCount; row++)
{
for (var col = 0; col < matrix.ColumnCount; col++)
{
AssertHelpers.AlmostEqualRelative(matrix[row, col], a[row, col], 14);
}
}
}
/// <summary>
/// Can solve Ax=b using QR factorization with a square A matrix.
/// </summary>
@ -931,62 +730,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Double
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 13);
}
/// <summary>
/// Can solve Ax=b using QR factorization with a square A matrix
/// using a work array.
/// </summary>
[Test]
public void CanSolveUsingQRSquareMatrixUsingWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new double[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var b = new[] {1.0, 2.0, 3.0, 4.0, 5.0, 6.0};
var x = new double[matrix.ColumnCount*2];
var work = new double[matrix.RowCount*Control.BlockSize];
Control.LinearAlgebraProvider.QRSolve(a, matrix.RowCount, matrix.ColumnCount, b, 2, x, work);
NotModified(3, 3, a, matrix);
var mx = Matrix<double>.Build.Dense(matrix.ColumnCount, 2, x);
var mb = matrix*mx;
AssertHelpers.AlmostEqualRelative(mb[0, 0], b[0], 13);
AssertHelpers.AlmostEqualRelative(mb[1, 0], b[1], 13);
AssertHelpers.AlmostEqualRelative(mb[2, 0], b[2], 13);
AssertHelpers.AlmostEqualRelative(mb[0, 1], b[3], 13);
AssertHelpers.AlmostEqualRelative(mb[1, 1], b[4], 13);
AssertHelpers.AlmostEqualRelative(mb[2, 1], b[5], 13);
}
/// <summary>
/// Can solve Ax=b using QR factorization with a tall A matrix
/// using a work array.
/// </summary>
[Test]
public void CanSolveUsingQRTallMatrixUsingWorkArray()
{
var matrix = _matrices["Tall3x2"];
var a = new double[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var b = new[] {1.0, 2.0, 3.0, 4.0, 5.0, 6.0};
var x = new double[matrix.ColumnCount*2];
var work = new double[matrix.RowCount*matrix.RowCount];
Control.LinearAlgebraProvider.QRSolve(a, matrix.RowCount, matrix.ColumnCount, b, 2, x, work);
NotModified(3, 2, a, matrix);
var mb = Matrix<double>.Build.Dense(matrix.RowCount, 2, b);
var test = (matrix.Transpose()*matrix).Inverse()*matrix.Transpose()*mb;
AssertHelpers.AlmostEqualRelative(test[0, 0], x[0], 13);
AssertHelpers.AlmostEqualRelative(test[1, 0], x[1], 13);
AssertHelpers.AlmostEqualRelative(test[0, 1], x[2], 13);
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 13);
}
/// <summary>
/// Can solve Ax=b using QR factorization with a square A matrix
/// using a factored A matrix.
@ -1045,66 +788,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Double
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 13);
}
/// <summary>
/// Can solve Ax=b using QR factorization with a square A matrix
/// using a factored A matrix with a work array.
/// </summary>
[Test]
public void CanSolveUsingQRSquareMatrixOnFactoredMatrixWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new double[matrix.RowCount*matrix.RowCount];
Array.Copy(matrix.Values, a, a.Length);
var tau = new double[matrix.ColumnCount];
var q = new double[matrix.ColumnCount*matrix.ColumnCount];
var work = new double[2048];
Control.LinearAlgebraProvider.QRFactor(a, matrix.RowCount, matrix.ColumnCount, q, tau, work);
var b = new[] {1.0, 2.0, 3.0, 4.0, 5.0, 6.0};
var x = new double[matrix.ColumnCount*2];
Control.LinearAlgebraProvider.QRSolveFactored(q, a, matrix.RowCount, matrix.ColumnCount, tau, b, 2, x, work);
var mx = Matrix<double>.Build.Dense(matrix.ColumnCount, 2, x);
var mb = matrix*mx;
AssertHelpers.AlmostEqualRelative(mb[0, 0], b[0], 13);
AssertHelpers.AlmostEqualRelative(mb[1, 0], b[1], 13);
AssertHelpers.AlmostEqualRelative(mb[2, 0], b[2], 13);
AssertHelpers.AlmostEqualRelative(mb[0, 1], b[3], 13);
AssertHelpers.AlmostEqualRelative(mb[1, 1], b[4], 13);
AssertHelpers.AlmostEqualRelative(mb[2, 1], b[5], 13);
}
/// <summary>
/// Can solve Ax=b using QR factorization with a tall A matrix
/// using a factored A matrix with a work array.
/// </summary>
[Test]
public void CanSolveUsingQRTallMatrixOnFactoredMatrixWithWorkArray()
{
var matrix = _matrices["Tall3x2"];
var a = new double[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var tau = new double[matrix.ColumnCount];
var q = new double[matrix.RowCount*matrix.RowCount];
var work = new double[2048];
Control.LinearAlgebraProvider.QRFactor(a, matrix.RowCount, matrix.ColumnCount, q, tau, work);
var b = new[] {1.0, 2.0, 3.0, 4.0, 5.0, 6.0};
var x = new double[matrix.ColumnCount*2];
Control.LinearAlgebraProvider.QRSolveFactored(q, a, matrix.RowCount, matrix.ColumnCount, tau, b, 2, x, work);
var mb = Matrix<double>.Build.Dense(matrix.RowCount, 2, b);
var test = (matrix.Transpose()*matrix).Inverse()*matrix.Transpose()*mb;
AssertHelpers.AlmostEqualRelative(test[0, 0], x[0], 13);
AssertHelpers.AlmostEqualRelative(test[1, 0], x[1], 13);
AssertHelpers.AlmostEqualRelative(test[0, 1], x[2], 13);
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 13);
}
/// <summary>
/// Can solve Ax=b using thin QR factorization with a square A matrix.
/// </summary>
@ -1157,62 +840,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Double
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 13);
}
/// <summary>
/// Can solve Ax=b using thin QR factorization with a square A matrix
/// using a work array.
/// </summary>
[Test]
public void CanSolveUsingThinQRSquareMatrixUsingWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new double[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var b = new[] {1.0, 2.0, 3.0, 4.0, 5.0, 6.0};
var x = new double[matrix.ColumnCount*2];
var work = new double[matrix.RowCount*matrix.ColumnCount];
Control.LinearAlgebraProvider.QRSolve(a, matrix.RowCount, matrix.ColumnCount, b, 2, x, work, QRMethod.Thin);
NotModified(3, 3, a, matrix);
var mx = Matrix<double>.Build.Dense(matrix.ColumnCount, 2, x);
var mb = matrix*mx;
AssertHelpers.AlmostEqualRelative(mb[0, 0], b[0], 13);
AssertHelpers.AlmostEqualRelative(mb[1, 0], b[1], 13);
AssertHelpers.AlmostEqualRelative(mb[2, 0], b[2], 13);
AssertHelpers.AlmostEqualRelative(mb[0, 1], b[3], 13);
AssertHelpers.AlmostEqualRelative(mb[1, 1], b[4], 13);
AssertHelpers.AlmostEqualRelative(mb[2, 1], b[5], 13);
}
/// <summary>
/// Can solve Ax=b using thin QR factorization with a tall A matrix
/// using a work array.
/// </summary>
[Test]
public void CanSolveUsingThinQRTallMatrixUsingWorkArray()
{
var matrix = _matrices["Tall3x2"];
var a = new double[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var b = new[] {1.0, 2.0, 3.0, 4.0, 5.0, 6.0};
var x = new double[matrix.ColumnCount*2];
var work = new double[matrix.RowCount*matrix.ColumnCount];
Control.LinearAlgebraProvider.QRSolve(a, matrix.RowCount, matrix.ColumnCount, b, 2, x, work, QRMethod.Thin);
NotModified(3, 2, a, matrix);
var mb = Matrix<double>.Build.Dense(matrix.RowCount, 2, b);
var test = (matrix.Transpose()*matrix).Inverse()*matrix.Transpose()*mb;
AssertHelpers.AlmostEqualRelative(test[0, 0], x[0], 13);
AssertHelpers.AlmostEqualRelative(test[1, 0], x[1], 13);
AssertHelpers.AlmostEqualRelative(test[0, 1], x[2], 13);
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 13);
}
/// <summary>
/// Can solve Ax=b using thin QR factorization with a square A matrix
/// using a factored A matrix.
@ -1271,66 +898,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Double
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 13);
}
/// <summary>
/// Can solve Ax=b using thin QR factorization with a square A matrix
/// using a factored A matrix with a work array.
/// </summary>
[Test]
public void CanSolveUsingThinQRSquareMatrixOnFactoredMatrixWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new double[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var tau = new double[matrix.ColumnCount];
var r = new double[matrix.ColumnCount*matrix.ColumnCount];
var work = new double[2048];
Control.LinearAlgebraProvider.ThinQRFactor(a, matrix.RowCount, matrix.ColumnCount, r, tau, work);
var b = new[] {1.0, 2.0, 3.0, 4.0, 5.0, 6.0};
var x = new double[matrix.ColumnCount*2];
Control.LinearAlgebraProvider.QRSolveFactored(a, r, matrix.RowCount, matrix.ColumnCount, tau, b, 2, x, work, QRMethod.Thin);
var mx = Matrix<double>.Build.Dense(matrix.ColumnCount, 2, x);
var mb = matrix*mx;
AssertHelpers.AlmostEqualRelative(mb[0, 0], b[0], 13);
AssertHelpers.AlmostEqualRelative(mb[1, 0], b[1], 13);
AssertHelpers.AlmostEqualRelative(mb[2, 0], b[2], 13);
AssertHelpers.AlmostEqualRelative(mb[0, 1], b[3], 13);
AssertHelpers.AlmostEqualRelative(mb[1, 1], b[4], 13);
AssertHelpers.AlmostEqualRelative(mb[2, 1], b[5], 13);
}
/// <summary>
/// Can solve Ax=b using thin QR factorization with a tall A matrix
/// using a factored A matrix with a work array.
/// </summary>
[Test]
public void CanSolveUsingThinQRTallMatrixOnFactoredMatrixWithWorkArray()
{
var matrix = _matrices["Tall3x2"];
var a = new double[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var tau = new double[matrix.ColumnCount];
var r = new double[matrix.ColumnCount*matrix.ColumnCount];
var work = new double[2048];
Control.LinearAlgebraProvider.ThinQRFactor(a, matrix.RowCount, matrix.ColumnCount, r, tau, work);
var b = new[] {1.0, 2.0, 3.0, 4.0, 5.0, 6.0};
var x = new double[matrix.ColumnCount*2];
Control.LinearAlgebraProvider.QRSolveFactored(a, r, matrix.RowCount, matrix.ColumnCount, tau, b, 2, x, work, QRMethod.Thin);
var mb = Matrix<double>.Build.Dense(matrix.RowCount, 2, b);
var test = (matrix.Transpose()*matrix).Inverse()*matrix.Transpose()*mb;
AssertHelpers.AlmostEqualRelative(test[0, 0], x[0], 13);
AssertHelpers.AlmostEqualRelative(test[1, 0], x[1], 13);
AssertHelpers.AlmostEqualRelative(test[0, 1], x[2], 13);
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 13);
}
/// <summary>
/// Can compute the SVD factorization of a square matrix.
/// </summary>
@ -1436,129 +1003,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Double
AssertHelpers.AlmostEqualRelative(matrix[1, 2], result[1, 2], 14);
}
/// <summary>
/// Can compute the SVD factorization of a square matrix using
/// a work array.
/// </summary>
[Test]
public void CanComputeSVDFactorizationOfSquareMatrixWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new double[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var s = new double[matrix.RowCount];
var u = new double[matrix.RowCount*matrix.RowCount];
var vt = new double[matrix.ColumnCount*matrix.ColumnCount];
#if CUDA
double[] work = null;
#else
var work = new double[100];
#endif
Control.LinearAlgebraProvider.SingularValueDecomposition(true, a, matrix.RowCount, matrix.ColumnCount, s, u, vt, work);
var w = new DenseMatrix(matrix.RowCount, matrix.ColumnCount);
for (var index = 0; index < s.Length; index++)
{
w[index, index] = s[index];
}
var mU = Matrix<double>.Build.Dense(matrix.RowCount, matrix.RowCount, u);
var mV = Matrix<double>.Build.Dense(matrix.ColumnCount, matrix.ColumnCount, vt);
var result = mU*w*mV;
AssertHelpers.AlmostEqualRelative(matrix[0, 0], result[0, 0], 14);
AssertHelpers.AlmostEqualRelative(matrix[1, 0], result[1, 0], 14);
AssertHelpers.AlmostEqualRelative(matrix[2, 0], result[2, 0], 14);
AssertHelpers.AlmostEqualRelative(matrix[0, 1], result[0, 1], 14);
AssertHelpers.AlmostEqualRelative(matrix[1, 1], result[1, 1], 14);
AssertHelpers.AlmostEqualRelative(matrix[2, 1], result[2, 1], 14);
AssertHelpers.AlmostEqualRelative(matrix[0, 2], result[0, 2], 14);
AssertHelpers.AlmostEqualRelative(matrix[1, 2], result[1, 2], 14);
AssertHelpers.AlmostEqualRelative(matrix[2, 2], result[2, 2], 14);
}
/// <summary>
/// Can compute the SVD factorization of a tall matrix using
/// a work array.
/// </summary>
[Test]
public void CanComputeSVDFactorizationOfTallMatrixWithWorkArray()
{
var matrix = _matrices["Tall3x2"];
var a = new double[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var s = new double[matrix.ColumnCount];
var u = new double[matrix.RowCount*matrix.RowCount];
var vt = new double[matrix.ColumnCount*matrix.ColumnCount];
#if CUDA
double[] work = null;
#else
var work = new double[100];
#endif
Control.LinearAlgebraProvider.SingularValueDecomposition(true, a, matrix.RowCount, matrix.ColumnCount, s, u, vt, work);
var w = new DenseMatrix(matrix.RowCount, matrix.ColumnCount);
for (var index = 0; index < s.Length; index++)
{
w[index, index] = s[index];
}
var mU = Matrix<double>.Build.Dense(matrix.RowCount, matrix.RowCount, u);
var mV = Matrix<double>.Build.Dense(matrix.ColumnCount, matrix.ColumnCount, vt);
var result = mU*w*mV;
AssertHelpers.AlmostEqualRelative(matrix[0, 0], result[0, 0], 14);
AssertHelpers.AlmostEqualRelative(matrix[1, 0], result[1, 0], 14);
AssertHelpers.AlmostEqualRelative(matrix[2, 0], result[2, 0], 14);
AssertHelpers.AlmostEqualRelative(matrix[0, 1], result[0, 1], 14);
AssertHelpers.AlmostEqualRelative(matrix[1, 1], result[1, 1], 14);
AssertHelpers.AlmostEqualRelative(matrix[2, 1], result[2, 1], 14);
}
/// <summary>
/// Can compute the SVD factorization of a wide matrix using
/// a work array.
/// </summary>
[Test]
public void CanComputeSVDFactorizationOfWideMatrixWithWorkArray()
{
var matrix = _matrices["Wide2x3"];
var a = new double[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var s = new double[matrix.RowCount];
var u = new double[matrix.RowCount*matrix.RowCount];
var vt = new double[matrix.ColumnCount*matrix.ColumnCount];
#if CUDA
double[] work = null;
#else
var work = new double[100];
#endif
Control.LinearAlgebraProvider.SingularValueDecomposition(true, a, matrix.RowCount, matrix.ColumnCount, s, u, vt, work);
var w = new DenseMatrix(matrix.RowCount, matrix.ColumnCount);
for (var index = 0; index < s.Length; index++)
{
w[index, index] = s[index];
}
var mU = Matrix<double>.Build.Dense(matrix.RowCount, matrix.RowCount, u);
var mV = Matrix<double>.Build.Dense(matrix.ColumnCount, matrix.ColumnCount, vt);
var result = mU*w*mV;
AssertHelpers.AlmostEqualRelative(matrix[0, 0], result[0, 0], 14);
AssertHelpers.AlmostEqualRelative(matrix[1, 0], result[1, 0], 14);
AssertHelpers.AlmostEqualRelative(matrix[0, 1], result[0, 1], 14);
AssertHelpers.AlmostEqualRelative(matrix[1, 1], result[1, 1], 14);
AssertHelpers.AlmostEqualRelative(matrix[0, 2], result[0, 2], 14);
AssertHelpers.AlmostEqualRelative(matrix[1, 2], result[1, 2], 14);
}
/// <summary>
/// Can solve Ax=b using SVD factorization with a square A matrix.
/// </summary>

558
src/UnitTests/LinearAlgebraProviderTests/Single/LinearAlgebraProviderTests.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
// Copyright (c) 2009-2015 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -435,68 +435,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Single
AssertHelpers.AlmostEqual(a[8], -0.113636363636364, 5);
}
/// <summary>
/// Can compute the inverse of a matrix using LU factorization
/// with a work array.
/// </summary>
[Test]
public void CanComputeLuInverseWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new float[matrix.RowCount*matrix.RowCount];
Array.Copy(matrix.Values, a, a.Length);
#if CUDA
float[] work = null;
#else
var work = new float[matrix.RowCount];
#endif
Control.LinearAlgebraProvider.LUInverse(a, matrix.RowCount, work);
AssertHelpers.AlmostEqual(a[0], -0.454545454545454, 5);
AssertHelpers.AlmostEqual(a[1], -0.909090909090908, 5);
AssertHelpers.AlmostEqual(a[2], 0.454545454545454, 5);
AssertHelpers.AlmostEqual(a[3], -0.340909090909090, 5);
AssertHelpers.AlmostEqual(a[4], -2.045454545454543, 5);
AssertHelpers.AlmostEqual(a[5], 1.477272727272726, 5);
AssertHelpers.AlmostEqual(a[6], -0.113636363636364, 5);
AssertHelpers.AlmostEqual(a[7], 0.227272727272727, 5);
AssertHelpers.AlmostEqual(a[8], -0.113636363636364, 5);
}
/// <summary>
/// Can compute the inverse of a matrix using LU factorization
/// using a previously factored matrix with a work array.
/// </summary>
[Test]
public void CanComputeLuInverseOnFactoredMatrixWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new float[matrix.RowCount*matrix.RowCount];
Array.Copy(matrix.Values, a, a.Length);
var ipiv = new int[matrix.RowCount];
Control.LinearAlgebraProvider.LUFactor(a, matrix.RowCount, ipiv);
#if CUDA
float[] work = null;
#else
var work = new float[matrix.RowCount];
#endif
Control.LinearAlgebraProvider.LUInverseFactored(a, matrix.RowCount, ipiv, work);
AssertHelpers.AlmostEqual(a[0], -0.454545454545454, 5);
AssertHelpers.AlmostEqual(a[1], -0.909090909090908, 5);
AssertHelpers.AlmostEqual(a[2], 0.454545454545454, 5);
AssertHelpers.AlmostEqual(a[3], -0.340909090909090, 5);
AssertHelpers.AlmostEqual(a[4], -2.045454545454543, 5);
AssertHelpers.AlmostEqual(a[5], 1.477272727272726, 5);
AssertHelpers.AlmostEqual(a[6], -0.113636363636364, 5);
AssertHelpers.AlmostEqual(a[7], 0.227272727272727, 5);
AssertHelpers.AlmostEqual(a[8], -0.113636363636364, 5);
}
/// <summary>
/// Can solve Ax=b using LU factorization.
/// </summary>
@ -694,90 +632,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Single
}
}
/// <summary>
/// Can compute QR factorization of a square matrix using a work array.
/// </summary>
[Test]
public void CanComputeQRFactorSquareMatrixWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var r = new float[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, r, r.Length);
var tau = new float[3];
var q = new float[matrix.RowCount*matrix.RowCount];
var work = new float[matrix.ColumnCount*Control.BlockSize];
Control.LinearAlgebraProvider.QRFactor(r, matrix.RowCount, matrix.ColumnCount, q, tau, work);
var mq = new DenseMatrix(matrix.RowCount, matrix.RowCount, q);
var mr = new DenseMatrix(matrix.RowCount, matrix.ColumnCount, r).UpperTriangle();
var a = mq*mr;
for (var row = 0; row < matrix.RowCount; row++)
{
for (var col = 0; col < matrix.ColumnCount; col++)
{
AssertHelpers.AlmostEqualRelative(matrix[row, col], a[row, col], 5);
}
}
}
/// <summary>
/// Can compute QR factorization of a tall matrix using a work matrix.
/// </summary>
[Test]
public void CanComputeQRFactorTallMatrixWithWorkArray()
{
var matrix = _matrices["Tall3x2"];
var r = new float[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, r, r.Length);
var tau = new float[3];
var q = new float[matrix.RowCount*matrix.RowCount];
var work = new float[matrix.ColumnCount*Control.BlockSize];
Control.LinearAlgebraProvider.QRFactor(r, matrix.RowCount, matrix.ColumnCount, q, tau, work);
var mr = new DenseMatrix(matrix.RowCount, matrix.ColumnCount, r).UpperTriangle();
var mq = new DenseMatrix(matrix.RowCount, matrix.RowCount, q);
var a = mq*mr;
for (var row = 0; row < matrix.RowCount; row++)
{
for (var col = 0; col < matrix.ColumnCount; col++)
{
AssertHelpers.AlmostEqualRelative(matrix[row, col], a[row, col], 5);
}
}
}
/// <summary>
/// Can compute QR factorization of a wide matrix using a work matrix.
/// </summary>
[Test]
public void CanComputeQRFactorWideMatrixWithWorkArray()
{
var matrix = _matrices["Wide2x3"];
var r = new float[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, r, r.Length);
var tau = new float[3];
var q = new float[matrix.RowCount*matrix.RowCount];
var work = new float[matrix.ColumnCount*Control.BlockSize];
Control.LinearAlgebraProvider.QRFactor(r, matrix.RowCount, matrix.ColumnCount, q, tau, work);
var mr = new DenseMatrix(matrix.RowCount, matrix.ColumnCount, r).UpperTriangle();
var mq = new DenseMatrix(matrix.RowCount, matrix.RowCount, q);
var a = mq*mr;
for (var row = 0; row < matrix.RowCount; row++)
{
for (var col = 0; col < matrix.ColumnCount; col++)
{
AssertHelpers.AlmostEqualRelative(matrix[row, col], a[row, col], 5);
}
}
}
/// <summary>
/// Can compute thin QR factorization of a square matrix.
/// </summary>
@ -832,61 +686,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Single
}
}
/// <summary>
/// Can compute thin QR factorization of a square matrix using a work array.
/// </summary>
[Test]
public void CanComputeThinQRFactorSquareMatrixWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var r = new float[matrix.ColumnCount*matrix.ColumnCount];
var tau = new float[3];
var q = new float[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, q, q.Length);
var work = new float[matrix.ColumnCount*Control.BlockSize];
Control.LinearAlgebraProvider.ThinQRFactor(q, matrix.RowCount, matrix.ColumnCount, r, tau, work);
var mq = new DenseMatrix(matrix.RowCount, matrix.ColumnCount, q);
var mr = new DenseMatrix(matrix.ColumnCount, matrix.ColumnCount, r);
var a = mq*mr;
for (var row = 0; row < matrix.RowCount; row++)
{
for (var col = 0; col < matrix.ColumnCount; col++)
{
AssertHelpers.AlmostEqualRelative(matrix[row, col], a[row, col], 5);
}
}
}
/// <summary>
/// Can compute thin QR factorization of a tall matrix using a work matrix.
/// </summary>
[Test]
public void CanComputeThinQRFactorTallMatrixWithWorkArray()
{
var matrix = _matrices["Tall3x2"];
var r = new float[matrix.ColumnCount*matrix.ColumnCount];
var tau = new float[3];
var q = new float[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, q, q.Length);
var work = new float[matrix.ColumnCount*Control.BlockSize];
Control.LinearAlgebraProvider.ThinQRFactor(q, matrix.RowCount, matrix.ColumnCount, r, tau, work);
var mq = new DenseMatrix(matrix.RowCount, matrix.ColumnCount, q);
var mr = new DenseMatrix(matrix.ColumnCount, matrix.ColumnCount, r);
var a = mq*mr;
for (var row = 0; row < matrix.RowCount; row++)
{
for (var col = 0; col < matrix.ColumnCount; col++)
{
AssertHelpers.AlmostEqualRelative(matrix[row, col], a[row, col], 5);
}
}
}
/// <summary>
/// Can solve Ax=b using QR factorization with a square A matrix.
/// </summary>
@ -939,62 +738,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Single
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 5);
}
/// <summary>
/// Can solve Ax=b using QR factorization with a square A matrix
/// using a work array.
/// </summary>
[Test]
public void CanSolveUsingQRSquareMatrixUsingWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new float[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var b = new[] {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
var x = new float[matrix.ColumnCount*2];
var work = new float[matrix.RowCount*matrix.RowCount];
Control.LinearAlgebraProvider.QRSolve(a, matrix.RowCount, matrix.ColumnCount, b, 2, x, work);
NotModified(3, 3, a, matrix);
var mx = new DenseMatrix(matrix.ColumnCount, 2, x);
var mb = matrix*mx;
AssertHelpers.AlmostEqualRelative(mb[0, 0], b[0], 5);
AssertHelpers.AlmostEqualRelative(mb[1, 0], b[1], 5);
AssertHelpers.AlmostEqualRelative(mb[2, 0], b[2], 5);
AssertHelpers.AlmostEqualRelative(mb[0, 1], b[3], 5);
AssertHelpers.AlmostEqualRelative(mb[1, 1], b[4], 4);
AssertHelpers.AlmostEqualRelative(mb[2, 1], b[5], 4);
}
/// <summary>
/// Can solve Ax=b using QR factorization with a tall A matrix
/// using a work array.
/// </summary>
[Test]
public void CanSolveUsingQRTallMatrixUsingWorkArray()
{
var matrix = _matrices["Tall3x2"];
var a = new float[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var b = new[] {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
var x = new float[matrix.ColumnCount*2];
var work = new float[matrix.RowCount*matrix.RowCount];
Control.LinearAlgebraProvider.QRSolve(a, matrix.RowCount, matrix.ColumnCount, b, 2, x, work);
NotModified(3, 2, a, matrix);
var mb = new DenseMatrix(matrix.RowCount, 2, b);
var test = (matrix.Transpose()*matrix).Inverse()*matrix.Transpose()*mb;
AssertHelpers.AlmostEqualRelative(test[0, 0], x[0], 5);
AssertHelpers.AlmostEqualRelative(test[1, 0], x[1], 5);
AssertHelpers.AlmostEqualRelative(test[0, 1], x[2], 5);
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 5);
}
/// <summary>
/// Can solve Ax=b using QR factorization with a square A matrix
/// using a factored A matrix.
@ -1053,66 +796,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Single
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 5);
}
/// <summary>
/// Can solve Ax=b using QR factorization with a square A matrix
/// using a factored A matrix with a work array.
/// </summary>
[Test]
public void CanSolveUsingQRSquareMatrixOnFactoredMatrixWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new float[matrix.RowCount*matrix.RowCount];
Array.Copy(matrix.Values, a, a.Length);
var tau = new float[matrix.ColumnCount];
var q = new float[matrix.ColumnCount*matrix.ColumnCount];
var work = new float[2048];
Control.LinearAlgebraProvider.QRFactor(a, matrix.RowCount, matrix.ColumnCount, q, tau, work);
var b = new[] {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
var x = new float[matrix.ColumnCount*2];
Control.LinearAlgebraProvider.QRSolveFactored(q, a, matrix.RowCount, matrix.ColumnCount, tau, b, 2, x, work);
var mx = new DenseMatrix(matrix.ColumnCount, 2, x);
var mb = matrix*mx;
AssertHelpers.AlmostEqualRelative(mb[0, 0], b[0], 5);
AssertHelpers.AlmostEqualRelative(mb[1, 0], b[1], 5);
AssertHelpers.AlmostEqualRelative(mb[2, 0], b[2], 5);
AssertHelpers.AlmostEqualRelative(mb[0, 1], b[3], 5);
AssertHelpers.AlmostEqualRelative(mb[1, 1], b[4], 4);
AssertHelpers.AlmostEqualRelative(mb[2, 1], b[5], 4);
}
/// <summary>
/// Can solve Ax=b using QR factorization with a tall A matrix
/// using a factored A matrix with a work array.
/// </summary>
[Test]
public void CanSolveUsingQRTallMatrixOnFactoredMatrixWithWorkArray()
{
var matrix = _matrices["Tall3x2"];
var a = new float[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var tau = new float[matrix.ColumnCount];
var q = new float[matrix.RowCount*matrix.RowCount];
var work = new float[2048];
Control.LinearAlgebraProvider.QRFactor(a, matrix.RowCount, matrix.ColumnCount, q, tau, work);
var b = new[] {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
var x = new float[matrix.ColumnCount*2];
Control.LinearAlgebraProvider.QRSolveFactored(q, a, matrix.RowCount, matrix.ColumnCount, tau, b, 2, x, work);
var mb = new DenseMatrix(matrix.RowCount, 2, b);
var test = (matrix.Transpose()*matrix).Inverse()*matrix.Transpose()*mb;
AssertHelpers.AlmostEqualRelative(test[0, 0], x[0], 5);
AssertHelpers.AlmostEqualRelative(test[1, 0], x[1], 5);
AssertHelpers.AlmostEqualRelative(test[0, 1], x[2], 5);
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 5);
}
/// <summary>
/// Can solve Ax=b using thin QR factorization with a square A matrix.
/// </summary>
@ -1165,62 +848,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Single
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 5);
}
/// <summary>
/// Can solve Ax=b using thin QR factorization with a square A matrix
/// using a work array.
/// </summary>
[Test]
public void CanSolveUsingThinQRSquareMatrixUsingWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new float[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var b = new[] {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
var x = new float[matrix.ColumnCount*2];
var work = new float[matrix.RowCount*matrix.ColumnCount];
Control.LinearAlgebraProvider.QRSolve(a, matrix.RowCount, matrix.ColumnCount, b, 2, x, work, QRMethod.Thin);
NotModified(3, 3, a, matrix);
var mx = new DenseMatrix(matrix.ColumnCount, 2, x);
var mb = matrix*mx;
AssertHelpers.AlmostEqualRelative(mb[0, 0], b[0], 5);
AssertHelpers.AlmostEqualRelative(mb[1, 0], b[1], 5);
AssertHelpers.AlmostEqualRelative(mb[2, 0], b[2], 5);
AssertHelpers.AlmostEqualRelative(mb[0, 1], b[3], 5);
AssertHelpers.AlmostEqualRelative(mb[1, 1], b[4], 4);
AssertHelpers.AlmostEqualRelative(mb[2, 1], b[5], 4);
}
/// <summary>
/// Can solve Ax=b using thin QR factorization with a tall A matrix
/// using a work array.
/// </summary>
[Test]
public void CanSolveUsingThinQRTallMatrixUsingWorkArray()
{
var matrix = _matrices["Tall3x2"];
var a = new float[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var b = new[] {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
var x = new float[matrix.ColumnCount*2];
var work = new float[matrix.RowCount*matrix.ColumnCount];
Control.LinearAlgebraProvider.QRSolve(a, matrix.RowCount, matrix.ColumnCount, b, 2, x, work, QRMethod.Thin);
NotModified(3, 2, a, matrix);
var mb = new DenseMatrix(matrix.RowCount, 2, b);
var test = (matrix.Transpose()*matrix).Inverse()*matrix.Transpose()*mb;
AssertHelpers.AlmostEqualRelative(test[0, 0], x[0], 5);
AssertHelpers.AlmostEqualRelative(test[1, 0], x[1], 5);
AssertHelpers.AlmostEqualRelative(test[0, 1], x[2], 5);
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 5);
}
/// <summary>
/// Can solve Ax=b using thin QR factorization with a square A matrix
/// using a factored A matrix.
@ -1279,66 +906,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Single
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 5);
}
/// <summary>
/// Can solve Ax=b using thin QR factorization with a square A matrix
/// using a factored A matrix with a work array.
/// </summary>
[Test]
public void CanSolveUsingThinQRSquareMatrixOnFactoredMatrixWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new float[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var tau = new float[matrix.ColumnCount];
var r = new float[matrix.ColumnCount*matrix.ColumnCount];
var work = new float[2048];
Control.LinearAlgebraProvider.ThinQRFactor(a, matrix.RowCount, matrix.ColumnCount, r, tau, work);
var b = new[] {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
var x = new float[matrix.ColumnCount*2];
Control.LinearAlgebraProvider.QRSolveFactored(a, r, matrix.RowCount, matrix.ColumnCount, tau, b, 2, x, work, QRMethod.Thin);
var mx = new DenseMatrix(matrix.ColumnCount, 2, x);
var mb = matrix*mx;
AssertHelpers.AlmostEqualRelative(mb[0, 0], b[0], 5);
AssertHelpers.AlmostEqualRelative(mb[1, 0], b[1], 5);
AssertHelpers.AlmostEqualRelative(mb[2, 0], b[2], 5);
AssertHelpers.AlmostEqualRelative(mb[0, 1], b[3], 5);
AssertHelpers.AlmostEqualRelative(mb[1, 1], b[4], 4);
AssertHelpers.AlmostEqualRelative(mb[2, 1], b[5], 4);
}
/// <summary>
/// Can solve Ax=b using thin QR factorization with a tall A matrix
/// using a factored A matrix with a work array.
/// </summary>
[Test]
public void CanSolveUsingThinQRTallMatrixOnFactoredMatrixWithWorkArray()
{
var matrix = _matrices["Tall3x2"];
var a = new float[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var tau = new float[matrix.ColumnCount];
var r = new float[matrix.ColumnCount*matrix.ColumnCount];
var work = new float[2048];
Control.LinearAlgebraProvider.ThinQRFactor(a, matrix.RowCount, matrix.ColumnCount, r, tau, work);
var b = new[] {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
var x = new float[matrix.ColumnCount*2];
Control.LinearAlgebraProvider.QRSolveFactored(a, r, matrix.RowCount, matrix.ColumnCount, tau, b, 2, x, work, QRMethod.Thin);
var mb = new DenseMatrix(matrix.RowCount, 2, b);
var test = (matrix.Transpose()*matrix).Inverse()*matrix.Transpose()*mb;
AssertHelpers.AlmostEqualRelative(test[0, 0], x[0], 5);
AssertHelpers.AlmostEqualRelative(test[1, 0], x[1], 5);
AssertHelpers.AlmostEqualRelative(test[0, 1], x[2], 5);
AssertHelpers.AlmostEqualRelative(test[1, 1], x[3], 5);
}
/// <summary>
/// Can compute the SVD factorization of a square matrix.
/// </summary>
@ -1444,129 +1011,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Single
AssertHelpers.AlmostEqualRelative(matrix[1, 2], result[1, 2], 5);
}
/// <summary>
/// Can compute the SVD factorization of a square matrix using
/// a work array.
/// </summary>
[Test]
public void CanComputeSVDFactorizationOfSquareMatrixWithWorkArray()
{
var matrix = _matrices["Square3x3"];
var a = new float[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var s = new float[matrix.RowCount];
var u = new float[matrix.RowCount*matrix.RowCount];
var vt = new float[matrix.ColumnCount*matrix.ColumnCount];
#if CUDA
float[] work = null;
#else
var work = new float[100];
#endif
Control.LinearAlgebraProvider.SingularValueDecomposition(true, a, matrix.RowCount, matrix.ColumnCount, s, u, vt, work);
var w = new DenseMatrix(matrix.RowCount, matrix.ColumnCount);
for (var index = 0; index < s.Length; index++)
{
w[index, index] = s[index];
}
var mU = new DenseMatrix(matrix.RowCount, matrix.RowCount, u);
var mV = new DenseMatrix(matrix.ColumnCount, matrix.ColumnCount, vt);
var result = mU*w*mV;
AssertHelpers.AlmostEqualRelative(matrix[0, 0], result[0, 0], 5);
AssertHelpers.AlmostEqualRelative(matrix[1, 0], result[1, 0], 5);
AssertHelpers.AlmostEqualRelative(matrix[2, 0], result[2, 0], 5);
AssertHelpers.AlmostEqualRelative(matrix[0, 1], result[0, 1], 5);
AssertHelpers.AlmostEqualRelative(matrix[1, 1], result[1, 1], 5);
AssertHelpers.AlmostEqualRelative(matrix[2, 1], result[2, 1], 5);
AssertHelpers.AlmostEqualRelative(matrix[0, 2], result[0, 2], 5);
AssertHelpers.AlmostEqualRelative(matrix[1, 2], result[1, 2], 5);
AssertHelpers.AlmostEqualRelative(matrix[2, 2], result[2, 2], 5);
}
/// <summary>
/// Can compute the SVD factorization of a tall matrix using
/// a work array.
/// </summary>
[Test]
public void CanComputeSVDFactorizationOfTallMatrixWithWorkArray()
{
var matrix = _matrices["Tall3x2"];
var a = new float[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var s = new float[matrix.ColumnCount];
var u = new float[matrix.RowCount*matrix.RowCount];
var vt = new float[matrix.ColumnCount*matrix.ColumnCount];
#if CUDA
float[] work = null;
#else
var work = new float[100];
#endif
Control.LinearAlgebraProvider.SingularValueDecomposition(true, a, matrix.RowCount, matrix.ColumnCount, s, u, vt, work);
var w = new DenseMatrix(matrix.RowCount, matrix.ColumnCount);
for (var index = 0; index < s.Length; index++)
{
w[index, index] = s[index];
}
var mU = new DenseMatrix(matrix.RowCount, matrix.RowCount, u);
var mV = new DenseMatrix(matrix.ColumnCount, matrix.ColumnCount, vt);
var result = mU*w*mV;
AssertHelpers.AlmostEqualRelative(matrix[0, 0], result[0, 0], 5);
AssertHelpers.AlmostEqualRelative(matrix[1, 0], result[1, 0], 5);
AssertHelpers.AlmostEqualRelative(matrix[2, 0], result[2, 0], 5);
AssertHelpers.AlmostEqualRelative(matrix[0, 1], result[0, 1], 5);
AssertHelpers.AlmostEqualRelative(matrix[1, 1], result[1, 1], 5);
AssertHelpers.AlmostEqualRelative(matrix[2, 1], result[2, 1], 5);
}
/// <summary>
/// Can compute the SVD factorization of a wide matrix using
/// a work array.
/// </summary>
[Test]
public void CanComputeSVDFactorizationOfWideMatrixWithWorkArray()
{
var matrix = _matrices["Wide2x3"];
var a = new float[matrix.RowCount*matrix.ColumnCount];
Array.Copy(matrix.Values, a, a.Length);
var s = new float[matrix.RowCount];
var u = new float[matrix.RowCount*matrix.RowCount];
var vt = new float[matrix.ColumnCount*matrix.ColumnCount];
#if CUDA
float[] work = null;
#else
var work = new float[100];
#endif
Control.LinearAlgebraProvider.SingularValueDecomposition(true, a, matrix.RowCount, matrix.ColumnCount, s, u, vt, work);
var w = new DenseMatrix(matrix.RowCount, matrix.ColumnCount);
for (var index = 0; index < s.Length; index++)
{
w[index, index] = s[index];
}
var mU = new DenseMatrix(matrix.RowCount, matrix.RowCount, u);
var mV = new DenseMatrix(matrix.ColumnCount, matrix.ColumnCount, vt);
var result = mU*w*mV;
AssertHelpers.AlmostEqualRelative(matrix[0, 0], result[0, 0], 5);
AssertHelpers.AlmostEqualRelative(matrix[1, 0], result[1, 0], 5);
AssertHelpers.AlmostEqualRelative(matrix[0, 1], result[0, 1], 5);
AssertHelpers.AlmostEqualRelative(matrix[1, 1], result[1, 1], 5);
AssertHelpers.AlmostEqualRelative(matrix[0, 2], result[0, 2], 5);
AssertHelpers.AlmostEqualRelative(matrix[1, 2], result[1, 2], 5);
}
/// <summary>
/// Can solve Ax=b using SVD factorization with a square A matrix.
/// </summary>

4
src/UnitTests/UnitTests-CUDA.csproj

@ -336,6 +336,10 @@
<Project>{b7cae5f4-a23f-4438-b5be-41226618b695}</Project>
<Name>Numerics</Name>
</ProjectReference>
<ProjectReference Include="..\TestData\TestData.csproj">
<Project>{af3253c9-4db5-45a0-98cf-c105fda9da47}</Project>
<Name>TestData</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<ItemGroup>

329
src/UnitTests/UnitTests-MKL.csproj

@ -52,8 +52,328 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="**\*.cs" Exclude="Properties\Settings.Designer.cs">
</Compile>
<Compile Include="ArrayHelpers.cs" />
<Compile Include="AssertHelpers.cs" />
<Compile Include="CombinatoricsTests\CombinatoricsCountingTest.cs" />
<Compile Include="ComplexTests\Complex32Test.cs" />
<Compile Include="ComplexTests\Complex32Test.TextHandling.cs" />
<Compile Include="ComplexTests\ComplexTest.cs" />
<Compile Include="ComplexTests\ComplexTest.TextHandling.cs" />
<Compile Include="DifferentiationTests\FiniteDifferenceCoefficientsTests.cs" />
<Compile Include="DifferentiationTests\NumericalDerivativeTests.cs" />
<Compile Include="DifferentiationTests\NumericalHessianTests.cs" />
<Compile Include="DifferentiationTests\NumericalJacobianTests.cs" />
<Compile Include="DistanceTests.cs" />
<Compile Include="DistributionTests\CommonDistributionTests.cs" />
<Compile Include="DistributionTests\Continuous\BetaTests.cs" />
<Compile Include="DistributionTests\Continuous\CauchyTests.cs" />
<Compile Include="DistributionTests\Continuous\ChiSquareTests.cs" />
<Compile Include="DistributionTests\Continuous\ChiTests.cs" />
<Compile Include="DistributionTests\Continuous\ContinuousUniformTests.cs" />
<Compile Include="DistributionTests\Continuous\ErlangTests.cs" />
<Compile Include="DistributionTests\Continuous\ExponentialTests.cs" />
<Compile Include="DistributionTests\Continuous\FisherSnedecorTests.cs" />
<Compile Include="DistributionTests\Continuous\GammaTests.cs" />
<Compile Include="DistributionTests\Continuous\InverseGammaTests.cs" />
<Compile Include="DistributionTests\Continuous\LaplaceTests.cs" />
<Compile Include="DistributionTests\Continuous\LogNormalTests.cs" />
<Compile Include="DistributionTests\Continuous\NormalTests.cs" />
<Compile Include="DistributionTests\Continuous\ParetoTests.cs" />
<Compile Include="DistributionTests\Continuous\RayleighTests.cs" />
<Compile Include="DistributionTests\Continuous\StableTests.cs" />
<Compile Include="DistributionTests\Continuous\StudentTTests.cs" />
<Compile Include="DistributionTests\Continuous\TriangularTests.cs" />
<Compile Include="DistributionTests\Continuous\WeibullTests.cs" />
<Compile Include="DistributionTests\Discrete\BernoulliTests.cs" />
<Compile Include="DistributionTests\Discrete\BinomialTests.cs" />
<Compile Include="DistributionTests\Discrete\CategoricalTests.cs" />
<Compile Include="DistributionTests\Discrete\ConwayMaxwellPoissonTests.cs" />
<Compile Include="DistributionTests\Discrete\DiscreteUniformTests.cs" />
<Compile Include="DistributionTests\Discrete\GeometricTests.cs" />
<Compile Include="DistributionTests\Discrete\HypergeometricTests.cs" />
<Compile Include="DistributionTests\Discrete\NegativeBinomialTests.cs" />
<Compile Include="DistributionTests\Discrete\PoissonTests.cs" />
<Compile Include="DistributionTests\Discrete\ZipfTests.cs" />
<Compile Include="DistributionTests\Multivariate\DirichletTests.cs" />
<Compile Include="DistributionTests\Multivariate\InverseWishartTests.cs" />
<Compile Include="DistributionTests\Multivariate\MatrixNormalTests.cs" />
<Compile Include="DistributionTests\Multivariate\MultinomialTests.cs" />
<Compile Include="DistributionTests\Multivariate\NormalGammaTests.cs" />
<Compile Include="DistributionTests\Multivariate\WishartTests.cs" />
<Compile Include="EuclidTests\GcdRelatedTest.cs" />
<Compile Include="EuclidTests\GcdRelatedTestBigInteger.cs" />
<Compile Include="EuclidTests\IntegerTheoryTest.cs" />
<Compile Include="ExcelTests.cs" />
<Compile Include="FinancialTests\DownsideDeviationTests.cs" />
<Compile Include="FinancialTests\GainLossRatioTests.cs" />
<Compile Include="FinancialTests\GainMeanTests.cs" />
<Compile Include="FinancialTests\GainStandardDeviationTests.cs" />
<Compile Include="FinancialTests\LossMeanTests.cs" />
<Compile Include="FinancialTests\LossStandardDeviationTests.cs" />
<Compile Include="FinancialTests\SemiDeviationTests.cs" />
<Compile Include="FitTests.cs" />
<Compile Include="GenerateTests.cs" />
<Compile Include="GenericMath.cs" />
<Compile Include="GoodnessOfFit\RSquaredTest.cs" />
<Compile Include="IntegralTransformsTests\FourierTest.cs" />
<Compile Include="IntegralTransformsTests\HartleyTest.cs" />
<Compile Include="IntegralTransformsTests\InverseTransformTest.cs" />
<Compile Include="IntegralTransformsTests\MatchingNaiveTransformTest.cs" />
<Compile Include="IntegralTransformsTests\ParsevalTheoremTest.cs" />
<Compile Include="IntegrationTests\IntegrationTest.cs" />
<Compile Include="InterpolationTests\AkimaSplineTest.cs" />
<Compile Include="InterpolationTests\BulirschStoerRationalTest.cs" />
<Compile Include="InterpolationTests\CubicSplineTest.cs" />
<Compile Include="InterpolationTests\EquidistantPolynomialTest.cs" />
<Compile Include="InterpolationTests\FloaterHormannRationalTest.cs" />
<Compile Include="InterpolationTests\LinearInterpolationCase.cs" />
<Compile Include="InterpolationTests\LinearSplineTest.cs" />
<Compile Include="InterpolationTests\NevillePolynomialTest.cs" />
<Compile Include="InterpolationTests\StepInterpolationTest.cs" />
<Compile Include="LinearAlgebraProviderTests\Complex32\LinearAlgebraProviderTests.cs" />
<Compile Include="LinearAlgebraProviderTests\Complex\LinearAlgebraProviderTests.cs" />
<Compile Include="LinearAlgebraProviderTests\Double\LinearAlgebraProviderTests.cs" />
<Compile Include="LinearAlgebraProviderTests\Single\LinearAlgebraProviderTests.cs" />
<Compile Include="LinearAlgebraTests\Complex32\DenseMatrixTests.cs" />
<Compile Include="LinearAlgebraTests\Complex32\DenseVectorTests.cs" />
<Compile Include="LinearAlgebraTests\Complex32\DiagonalMatrixTests.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Factorization\CholeskyTests.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Factorization\EvdTests.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Factorization\GramSchmidtTests.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Factorization\LUTests.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Factorization\QRTests.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Factorization\SvdTests.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Factorization\UserCholeskyTests.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Factorization\UserEvdTests.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Factorization\UserGramSchmidtTests.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Factorization\UserLUTests.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Factorization\UserQRTests.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Factorization\UserSvdTests.cs" />
<Compile Include="LinearAlgebraTests\Complex32\MatrixLoader.cs" />
<Compile Include="LinearAlgebraTests\Complex32\MatrixStructureTheory.cs" />
<Compile Include="LinearAlgebraTests\Complex32\MatrixTests.Arithmetic.cs" />
<Compile Include="LinearAlgebraTests\Complex32\MatrixTests.cs" />
<Compile Include="LinearAlgebraTests\Complex32\ReturnTypeTests.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Solvers\Iterative\BiCgStabTest.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Solvers\Iterative\GpBiCgTest.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Solvers\Iterative\MlkBiCgStabTest.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Solvers\Iterative\TFQMRTest.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Solvers\IteratorTest.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Solvers\Preconditioners\DiagonalTest.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Solvers\Preconditioners\IluptElementSorterTest.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Solvers\Preconditioners\IlutpTest.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Solvers\Preconditioners\IncompleteLUTest.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Solvers\Preconditioners\PreConditionerTest.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Solvers\Preconditioners\UnitPreconditionerTest.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Solvers\StopCriterion\DivergenceStopCriteriumTest.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Solvers\StopCriterion\FailureStopCriteriumTest.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Solvers\StopCriterion\IterationCountStopCriteriumTest.cs" />
<Compile Include="LinearAlgebraTests\Complex32\Solvers\StopCriterion\ResidualStopCriteriumTest.cs" />
<Compile Include="LinearAlgebraTests\Complex32\SparseMatrixTests.cs" />
<Compile Include="LinearAlgebraTests\Complex32\SparseVectorTest.cs" />
<Compile Include="LinearAlgebraTests\Complex32\TestData.cs" />
<Compile Include="LinearAlgebraTests\Complex32\UserDefinedMatrix.cs" />
<Compile Include="LinearAlgebraTests\Complex32\UserDefinedMatrixTests.cs" />
<Compile Include="LinearAlgebraTests\Complex32\UserDefinedVector.cs" />
<Compile Include="LinearAlgebraTests\Complex32\UserDefinedVectorTests.cs" />
<Compile Include="LinearAlgebraTests\Complex32\VectorArithmeticTheory.cs" />
<Compile Include="LinearAlgebraTests\Complex32\VectorTests.Arithmetic.cs" />
<Compile Include="LinearAlgebraTests\Complex32\VectorTests.cs" />
<Compile Include="LinearAlgebraTests\Complex32\VectorTests.Norm.cs" />
<Compile Include="LinearAlgebraTests\Complex\DenseMatrixTests.cs" />
<Compile Include="LinearAlgebraTests\Complex\DenseVectorTests.cs" />
<Compile Include="LinearAlgebraTests\Complex\DiagonalMatrixTests.cs" />
<Compile Include="LinearAlgebraTests\Complex\Factorization\CholeskyTests.cs" />
<Compile Include="LinearAlgebraTests\Complex\Factorization\EvdTests.cs" />
<Compile Include="LinearAlgebraTests\Complex\Factorization\GramSchmidtTests.cs" />
<Compile Include="LinearAlgebraTests\Complex\Factorization\LUTests.cs" />
<Compile Include="LinearAlgebraTests\Complex\Factorization\QRTests.cs" />
<Compile Include="LinearAlgebraTests\Complex\Factorization\SvdTests.cs" />
<Compile Include="LinearAlgebraTests\Complex\Factorization\UserCholeskyTests.cs" />
<Compile Include="LinearAlgebraTests\Complex\Factorization\UserEvdTests.cs" />
<Compile Include="LinearAlgebraTests\Complex\Factorization\UserGramSchmidtTests.cs" />
<Compile Include="LinearAlgebraTests\Complex\Factorization\UserLUTests.cs" />
<Compile Include="LinearAlgebraTests\Complex\Factorization\UserQRTests.cs" />
<Compile Include="LinearAlgebraTests\Complex\Factorization\UserSvdTests.cs" />
<Compile Include="LinearAlgebraTests\Complex\MatrixLoader.cs" />
<Compile Include="LinearAlgebraTests\Complex\MatrixStructureTheory.cs" />
<Compile Include="LinearAlgebraTests\Complex\MatrixTests.Arithmetic.cs" />
<Compile Include="LinearAlgebraTests\Complex\MatrixTests.cs" />
<Compile Include="LinearAlgebraTests\Complex\ReturnTypeTests.cs" />
<Compile Include="LinearAlgebraTests\Complex\Solvers\Iterative\BiCgStabTest.cs" />
<Compile Include="LinearAlgebraTests\Complex\Solvers\Iterative\GpBiCgTest.cs" />
<Compile Include="LinearAlgebraTests\Complex\Solvers\Iterative\MlkBiCgStabTest.cs" />
<Compile Include="LinearAlgebraTests\Complex\Solvers\Iterative\TFQMRTest.cs" />
<Compile Include="LinearAlgebraTests\Complex\Solvers\IteratorTest.cs" />
<Compile Include="LinearAlgebraTests\Complex\Solvers\Preconditioners\DiagonalTest.cs" />
<Compile Include="LinearAlgebraTests\Complex\Solvers\Preconditioners\IluptElementSorterTest.cs" />
<Compile Include="LinearAlgebraTests\Complex\Solvers\Preconditioners\IlutpTest.cs" />
<Compile Include="LinearAlgebraTests\Complex\Solvers\Preconditioners\IncompleteLUTest.cs" />
<Compile Include="LinearAlgebraTests\Complex\Solvers\Preconditioners\PreConditionerTest.cs" />
<Compile Include="LinearAlgebraTests\Complex\Solvers\Preconditioners\UnitPreconditionerTest.cs" />
<Compile Include="LinearAlgebraTests\Complex\Solvers\StopCriterion\DivergenceStopCriteriumTest.cs" />
<Compile Include="LinearAlgebraTests\Complex\Solvers\StopCriterion\FailureStopCriteriumTest.cs" />
<Compile Include="LinearAlgebraTests\Complex\Solvers\StopCriterion\IterationCountStopCriteriumTest.cs" />
<Compile Include="LinearAlgebraTests\Complex\Solvers\StopCriterion\ResidualStopCriteriumTest.cs" />
<Compile Include="LinearAlgebraTests\Complex\SparseMatrixTests.cs" />
<Compile Include="LinearAlgebraTests\Complex\SparseVectorTest.cs" />
<Compile Include="LinearAlgebraTests\Complex\TestData.cs" />
<Compile Include="LinearAlgebraTests\Complex\UserDefinedMatrix.cs" />
<Compile Include="LinearAlgebraTests\Complex\UserDefinedMatrixTests.cs" />
<Compile Include="LinearAlgebraTests\Complex\UserDefinedVector.cs" />
<Compile Include="LinearAlgebraTests\Complex\UserDefinedVectorTests.cs" />
<Compile Include="LinearAlgebraTests\Complex\VectorArithmeticTheory.cs" />
<Compile Include="LinearAlgebraTests\Complex\VectorTests.Arithmetic.cs" />
<Compile Include="LinearAlgebraTests\Complex\VectorTests.cs" />
<Compile Include="LinearAlgebraTests\Complex\VectorTests.Norm.cs" />
<Compile Include="LinearAlgebraTests\Double\DenseMatrixTests.cs" />
<Compile Include="LinearAlgebraTests\Double\DenseVectorTests.cs" />
<Compile Include="LinearAlgebraTests\Double\DiagonalMatrixTests.cs" />
<Compile Include="LinearAlgebraTests\Double\Factorization\CholeskyTests.cs" />
<Compile Include="LinearAlgebraTests\Double\Factorization\EvdTests.cs" />
<Compile Include="LinearAlgebraTests\Double\Factorization\GramSchmidtTests.cs" />
<Compile Include="LinearAlgebraTests\Double\Factorization\LUTests.cs" />
<Compile Include="LinearAlgebraTests\Double\Factorization\QRTests.cs" />
<Compile Include="LinearAlgebraTests\Double\Factorization\SvdTests.cs" />
<Compile Include="LinearAlgebraTests\Double\Factorization\UserCholeskyTests.cs" />
<Compile Include="LinearAlgebraTests\Double\Factorization\UserEvdTests.cs" />
<Compile Include="LinearAlgebraTests\Double\Factorization\UserGramSchmidtTests.cs" />
<Compile Include="LinearAlgebraTests\Double\Factorization\UserLUTests.cs" />
<Compile Include="LinearAlgebraTests\Double\Factorization\UserQRTests.cs" />
<Compile Include="LinearAlgebraTests\Double\Factorization\UserSvdTests.cs" />
<Compile Include="LinearAlgebraTests\Double\MatrixLoader.cs" />
<Compile Include="LinearAlgebraTests\Double\MatrixStructureTheory.cs" />
<Compile Include="LinearAlgebraTests\Double\MatrixTests.Arithmetic.cs" />
<Compile Include="LinearAlgebraTests\Double\MatrixTests.cs" />
<Compile Include="LinearAlgebraTests\Double\ReturnTypeTests.cs" />
<Compile Include="LinearAlgebraTests\Double\Solvers\Iterative\BiCgStabTest.cs" />
<Compile Include="LinearAlgebraTests\Double\Solvers\Iterative\GpBiCgTest.cs" />
<Compile Include="LinearAlgebraTests\Double\Solvers\Iterative\MlkBiCgStabTest.cs" />
<Compile Include="LinearAlgebraTests\Double\Solvers\Iterative\TFQMRTest.cs" />
<Compile Include="LinearAlgebraTests\Double\Solvers\IteratorTest.cs" />
<Compile Include="LinearAlgebraTests\Double\Solvers\Preconditioners\DiagonalTest.cs" />
<Compile Include="LinearAlgebraTests\Double\Solvers\Preconditioners\IluptElementSorterTest.cs" />
<Compile Include="LinearAlgebraTests\Double\Solvers\Preconditioners\IlutpTest.cs" />
<Compile Include="LinearAlgebraTests\Double\Solvers\Preconditioners\IncompleteLUTest.cs" />
<Compile Include="LinearAlgebraTests\Double\Solvers\Preconditioners\PreConditionerTest.cs" />
<Compile Include="LinearAlgebraTests\Double\Solvers\Preconditioners\UnitPreconditionerTest.cs" />
<Compile Include="LinearAlgebraTests\Double\Solvers\StopCriterion\DivergenceStopCriteriumTest.cs" />
<Compile Include="LinearAlgebraTests\Double\Solvers\StopCriterion\FailureStopCriteriumTest.cs" />
<Compile Include="LinearAlgebraTests\Double\Solvers\StopCriterion\IterationCountStopCriteriumTest.cs" />
<Compile Include="LinearAlgebraTests\Double\Solvers\StopCriterion\ResidualStopCriteriumTest.cs" />
<Compile Include="LinearAlgebraTests\Double\SparseMatrixTests.cs" />
<Compile Include="LinearAlgebraTests\Double\SparseVectorTest.cs" />
<Compile Include="LinearAlgebraTests\Double\TestData.cs" />
<Compile Include="LinearAlgebraTests\Double\UserDefinedMatrix.cs" />
<Compile Include="LinearAlgebraTests\Double\UserDefinedMatrixTests.cs" />
<Compile Include="LinearAlgebraTests\Double\UserDefinedVector.cs" />
<Compile Include="LinearAlgebraTests\Double\UserDefinedVectorTests.cs" />
<Compile Include="LinearAlgebraTests\Double\VectorArithmeticTheory.cs" />
<Compile Include="LinearAlgebraTests\Double\VectorTests.Arithmetic.cs" />
<Compile Include="LinearAlgebraTests\Double\VectorTests.cs" />
<Compile Include="LinearAlgebraTests\Double\VectorTests.Norm.cs" />
<Compile Include="LinearAlgebraTests\MatrixHelpers.cs" />
<Compile Include="LinearAlgebraTests\MatrixStorageCombinatorsTests.cs" />
<Compile Include="LinearAlgebraTests\MatrixStructureTheory.Access.cs" />
<Compile Include="LinearAlgebraTests\MatrixStructureTheory.cs" />
<Compile Include="LinearAlgebraTests\MatrixStructureTheory.Functional.cs" />
<Compile Include="LinearAlgebraTests\MatrixStructureTheory.Reform.cs" />
<Compile Include="LinearAlgebraTests\Single\DenseMatrixTests.cs" />
<Compile Include="LinearAlgebraTests\Single\DenseVectorTests.cs" />
<Compile Include="LinearAlgebraTests\Single\DiagonalMatrixTests.cs" />
<Compile Include="LinearAlgebraTests\Single\Factorization\CholeskyTests.cs" />
<Compile Include="LinearAlgebraTests\Single\Factorization\EvdTests.cs" />
<Compile Include="LinearAlgebraTests\Single\Factorization\GramSchmidtTests.cs" />
<Compile Include="LinearAlgebraTests\Single\Factorization\LUTests.cs" />
<Compile Include="LinearAlgebraTests\Single\Factorization\QRTests.cs" />
<Compile Include="LinearAlgebraTests\Single\Factorization\SvdTests.cs" />
<Compile Include="LinearAlgebraTests\Single\Factorization\UserCholeskyTests.cs" />
<Compile Include="LinearAlgebraTests\Single\Factorization\UserEvdTests.cs" />
<Compile Include="LinearAlgebraTests\Single\Factorization\UserGramSchmidtTests.cs" />
<Compile Include="LinearAlgebraTests\Single\Factorization\UserLUTests.cs" />
<Compile Include="LinearAlgebraTests\Single\Factorization\UserQRTests.cs" />
<Compile Include="LinearAlgebraTests\Single\Factorization\UserSvdTests.cs" />
<Compile Include="LinearAlgebraTests\Single\MatrixLoader.cs" />
<Compile Include="LinearAlgebraTests\Single\MatrixStructureTheory.cs" />
<Compile Include="LinearAlgebraTests\Single\MatrixTests.Arithmetic.cs" />
<Compile Include="LinearAlgebraTests\Single\MatrixTests.cs" />
<Compile Include="LinearAlgebraTests\Single\ReturnTypeTests.cs" />
<Compile Include="LinearAlgebraTests\Single\Solvers\Iterative\BiCgStabTest.cs" />
<Compile Include="LinearAlgebraTests\Single\Solvers\Iterative\GpBiCgTest.cs" />
<Compile Include="LinearAlgebraTests\Single\Solvers\Iterative\MlkBiCgStabTest.cs" />
<Compile Include="LinearAlgebraTests\Single\Solvers\Iterative\TFQMRTest.cs" />
<Compile Include="LinearAlgebraTests\Single\Solvers\IteratorTest.cs" />
<Compile Include="LinearAlgebraTests\Single\Solvers\Preconditioners\DiagonalTest.cs" />
<Compile Include="LinearAlgebraTests\Single\Solvers\Preconditioners\IluptElementSorterTest.cs" />
<Compile Include="LinearAlgebraTests\Single\Solvers\Preconditioners\IlutpTest.cs" />
<Compile Include="LinearAlgebraTests\Single\Solvers\Preconditioners\IncompleteLUTest.cs" />
<Compile Include="LinearAlgebraTests\Single\Solvers\Preconditioners\PreConditionerTest.cs" />
<Compile Include="LinearAlgebraTests\Single\Solvers\Preconditioners\UnitPreconditionerTest.cs" />
<Compile Include="LinearAlgebraTests\Single\Solvers\StopCriterion\DivergenceStopCriteriumTest.cs" />
<Compile Include="LinearAlgebraTests\Single\Solvers\StopCriterion\FailureStopCriteriumTest.cs" />
<Compile Include="LinearAlgebraTests\Single\Solvers\StopCriterion\IterationCountStopCriteriumTest.cs" />
<Compile Include="LinearAlgebraTests\Single\Solvers\StopCriterion\ResidualStopCriteriumTest.cs" />
<Compile Include="LinearAlgebraTests\Single\SparseMatrixTests.cs" />
<Compile Include="LinearAlgebraTests\Single\SparseVectorTest.cs" />
<Compile Include="LinearAlgebraTests\Single\TestData.cs" />
<Compile Include="LinearAlgebraTests\Single\UserDefinedMatrix.cs" />
<Compile Include="LinearAlgebraTests\Single\UserDefinedMatrixTests.cs" />
<Compile Include="LinearAlgebraTests\Single\UserDefinedVector.cs" />
<Compile Include="LinearAlgebraTests\Single\UserDefinedVectorTests.cs" />
<Compile Include="LinearAlgebraTests\Single\VectorArithmeticTheory.cs" />
<Compile Include="LinearAlgebraTests\Single\VectorTests.Arithmetic.cs" />
<Compile Include="LinearAlgebraTests\Single\VectorTests.cs" />
<Compile Include="LinearAlgebraTests\Single\VectorTests.Norm.cs" />
<Compile Include="LinearAlgebraTests\TestData.cs" />
<Compile Include="LinearAlgebraTests\VectorArithmeticTheory.cs" />
<Compile Include="LinearAlgebraTests\VectorStorageCombinatorsTests.cs" />
<Compile Include="PermutationTest.cs" />
<Compile Include="PrecisionTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Random\CryptoRandomSourceTests.cs" />
<Compile Include="Random\Mcg31m1Tests.cs" />
<Compile Include="Random\Mcg59Tests.cs" />
<Compile Include="Random\MersenneTwisterTests.cs" />
<Compile Include="Random\Mrg32k3aTests.cs" />
<Compile Include="Random\PalfTests.cs" />
<Compile Include="Random\RandomExtensionTests.cs" />
<Compile Include="Random\RandomTests.cs" />
<Compile Include="Random\SystemRandomSourceTests.cs" />
<Compile Include="Random\WH1982Tests.cs" />
<Compile Include="Random\WH2006Tests.cs" />
<Compile Include="Random\XorshiftTests.cs" />
<Compile Include="RootFindingTests\BisectionTest.cs" />
<Compile Include="RootFindingTests\BrentTest.cs" />
<Compile Include="RootFindingTests\BroydenTest.cs" />
<Compile Include="RootFindingTests\CubicTest.cs" />
<Compile Include="RootFindingTests\FindRootsTest.cs" />
<Compile Include="RootFindingTests\NewtonRaphsonTest.cs" />
<Compile Include="RootFindingTests\RobustNewtonRaphsonTest.cs" />
<Compile Include="SortingTests.cs" />
<Compile Include="SpecialFunctionsTests\ErfTests.cs" />
<Compile Include="SpecialFunctionsTests\ExponentialIntegralTests.cs" />
<Compile Include="SpecialFunctionsTests\FactorialTest.cs" />
<Compile Include="SpecialFunctionsTests\GammaTests.cs" />
<Compile Include="SpecialFunctionsTests\ModifiedBesselTests.cs" />
<Compile Include="SpecialFunctionsTests\ModifiedStruveTests.cs" />
<Compile Include="SpecialFunctionsTests\SpecialFunctionsTests.cs" />
<Compile Include="StatisticsTests\CorrelationTests.cs" />
<Compile Include="StatisticsTests\DescriptiveStatisticsTests.cs" />
<Compile Include="StatisticsTests\HistogramTests.cs" />
<Compile Include="StatisticsTests\MCMCTests\HybridMCTest.cs" />
<Compile Include="StatisticsTests\MCMCTests\MCMCDiagnosticsTest.cs" />
<Compile Include="StatisticsTests\MCMCTests\MetropolisHastingsSamplerTests.cs" />
<Compile Include="StatisticsTests\MCMCTests\MetropolisSamplerTests.cs" />
<Compile Include="StatisticsTests\MCMCTests\RejectionSamplerTests.cs" />
<Compile Include="StatisticsTests\MCMCTests\UnivariateHybridMCTest.cs" />
<Compile Include="StatisticsTests\MCMCTests\UnivariateSliceSamplerTests.cs" />
<Compile Include="StatisticsTests\MovingStatisticsTests.cs" />
<Compile Include="StatisticsTests\PercentileTests.cs" />
<Compile Include="StatisticsTests\RunningStatisticsTests.cs" />
<Compile Include="StatisticsTests\StatisticsTests.cs" />
<Compile Include="StatisticsTests\StatTestData.cs" />
<Compile Include="TrigonometryTest.cs" />
<Compile Include="UseLinearAlgebraProvider.cs" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\data\Codeplex-5667.csv">
@ -336,6 +656,10 @@
<Project>{b7cae5f4-a23f-4438-b5be-41226618b695}</Project>
<Name>Numerics</Name>
</ProjectReference>
<ProjectReference Include="..\TestData\TestData.csproj">
<Project>{af3253c9-4db5-45a0-98cf-c105fda9da47}</Project>
<Name>TestData</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<ItemGroup>
@ -348,4 +672,5 @@
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup />
</Project>

4
src/UnitTests/UnitTests-OpenBLAS.csproj

@ -336,6 +336,10 @@
<Project>{b7cae5f4-a23f-4438-b5be-41226618b695}</Project>
<Name>Numerics</Name>
</ProjectReference>
<ProjectReference Include="..\TestData\TestData.csproj">
<Project>{af3253c9-4db5-45a0-98cf-c105fda9da47}</Project>
<Name>TestData</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<ItemGroup>

Loading…
Cancel
Save