Browse Source

Native pull: native Evd, updated provider

Squashed commit of the following:

commit 03291ba72c61e66e02c7a315e401210f96f9f20c
Author: Marcus Cuda <marcus@cuda.org>
Date:   Thu Apr 18 11:18:03 2013 +0300

    Tweaked managed EVD to be native compatible (use 1D arrays) and added naive EvD

commit d7bd0e7c93ba0284a7e8bee22f7d0c56f451febc
Author: Marcus Cuda <marcus@cuda.org>
Date:   Wed Feb 6 12:46:53 2013 +0200

    beginnings go an ATLAS provider

commit c4470fb99d5217a75526fc99e12c9119c12c3ec7
Author: Marcus Cuda <marcus@cuda.org>
Date:   Tue Feb 5 08:13:25 2013 -0800

    tested 32bit version

commit ea58e3bd936a6886130954e7ade63f066d6197cb
Author: Marcus Cuda <marcus@cuda.org>
Date:   Tue Feb 5 05:26:20 2013 -0800

    tweaked code and file name to compile with GCC and to run with mono on linux
pull/112/merge
Christoph Ruegg 13 years ago
parent
commit
ee2c0bec65
  1. 101
      src/NativeWrappers/ATLAS/blas.c
  2. 543
      src/NativeWrappers/ATLAS/lapack.cpp
  3. 3
      src/NativeWrappers/Common/lapack_common.h
  4. 8
      src/NativeWrappers/Common/resource.rc
  5. 9
      src/NativeWrappers/Linux/build.sh
  6. 7
      src/NativeWrappers/MKL/blas.c
  7. 1145
      src/NativeWrappers/MKL/lapack.cpp
  8. 7
      src/NativeWrappers/MKL/vector_functions.c
  9. 160
      src/NativeWrappers/Windows/ATLASWrapper/ATLASWrapper.vcxproj
  10. 33
      src/NativeWrappers/Windows/ATLASWrapper/ATLASWrapper.vcxproj.filters
  11. 5
      src/NativeWrappers/Windows/MKL/MKLWrapper.vcxproj
  12. 5
      src/NativeWrappers/Windows/MKL/MKLWrapper.vcxproj.filters
  13. 18
      src/NativeWrappers/Windows/NativeWrappers.sln
  14. 46
      src/Numerics/Algorithms/LinearAlgebra/ILinearAlgebraProvider.cs
  15. 572
      src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.Complex.cs
  16. 91
      src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.Complex32.cs
  17. 99
      src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.Double.cs
  18. 98
      src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.Single.cs
  19. 2
      src/Numerics/Algorithms/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Complex.cs
  20. 143
      src/Numerics/Algorithms/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Complex32.cs
  21. 203
      src/Numerics/Algorithms/LinearAlgebra/Mkl/MklLinearAlgebraProvider.double.cs
  22. 198
      src/Numerics/Algorithms/LinearAlgebra/Mkl/MklLinearAlgebraProvider.float.cs
  23. 14
      src/Numerics/Algorithms/LinearAlgebra/Mkl/SafeNativeMethods.cs
  24. 385
      src/Numerics/LinearAlgebra/Complex/Factorization/DenseEvd.cs
  25. 4
      src/Numerics/LinearAlgebra/Complex/Factorization/UserEvd.cs
  26. 412
      src/Numerics/LinearAlgebra/Complex32/Factorization/DenseEvd.cs
  27. 4
      src/Numerics/LinearAlgebra/Complex32/Factorization/UserEvd.cs
  28. 579
      src/Numerics/LinearAlgebra/Double/Factorization/DenseEvd.cs
  29. 4
      src/Numerics/LinearAlgebra/Double/Factorization/UserEvd.cs
  30. 600
      src/Numerics/LinearAlgebra/Single/Factorization/DenseEvd.cs
  31. 4
      src/Numerics/LinearAlgebra/Single/Factorization/UserEvd.cs
  32. 2
      src/UnitTests/LinearAlgebraProviderTests/Complex32/LinearAlgebraProviderTests.cs
  33. 1
      src/UnitTests/LinearAlgebraTests/Complex/Factorization/EvdTests.cs
  34. 12
      src/UnitTests/LinearAlgebraTests/Complex32/Factorization/EvdTests.cs
  35. 4
      src/UnitTests/LinearAlgebraTests/Double/Factorization/EvdTests.cs
  36. 7
      src/UnitTests/LinearAlgebraTests/Single/Factorization/EvdTests.cs

101
src/NativeWrappers/ATLAS/blas.c

@ -0,0 +1,101 @@
#include "wrapper_common.h"
#include "blas.h"
#if GCC
extern "C" {
#endif
DLLEXPORT void s_axpy(const int n, const float alpha, const float x[], float y[]){
cblas_saxpy(n, alpha, x, 1, y, 1);
}
DLLEXPORT void d_axpy(const int n, const double alpha, const double x[], double y[]){
cblas_daxpy(n, alpha, x, 1, y, 1);
}
DLLEXPORT void c_axpy(const int n, const Complex8 alpha, const Complex8 x[], Complex8 y[]){
cblas_caxpy(n, &alpha, x, 1, y, 1);
}
DLLEXPORT void z_axpy(const int n, const Complex16 alpha, const Complex16 x[], Complex16 y[]){
cblas_zaxpy(n, &alpha, x, 1, y, 1);
}
DLLEXPORT void s_scale(const int n, const float alpha, float x[]){
cblas_sscal(n, alpha, x, 1);
}
DLLEXPORT void d_scale(const int n, const double alpha, double x[]){
cblas_dscal(n, alpha, x, 1);
}
DLLEXPORT void c_scale(const int n, const Complex8 alpha, Complex8 x[]){
cblas_cscal(n, &alpha, x, 1);
}
DLLEXPORT void z_scale(const int n, const Complex16 alpha, Complex16 x[]){
cblas_zscal(n, &alpha, x, 1);
}
DLLEXPORT float s_dot_product(const int n, const float x[], const float y[]){
return cblas_sdot(n, x, 1, y, 1);
}
DLLEXPORT double d_dot_product(const int n, const double x[], const double y[]){
return cblas_ddot(n, x, 1, y, 1);
}
DLLEXPORT Complex8 c_dot_product(const int n, const Complex8 x[], const Complex8 y[]){
Complex8 ret;
cblas_cdotu_sub(n, x, 1, y, 1, &ret);
return ret;
}
DLLEXPORT Complex16 z_dot_product(const int n, const Complex16 x[], const Complex16 y[]){
Complex16 ret;
cblas_zdotu_sub(n, x, 1, y, 1, &ret);
return ret;
}
DLLEXPORT void s_matrix_multiply(const enum CBLAS_TRANSPOSE transA, const enum CBLAS_TRANSPOSE transB, const int m, const int n, const int k, const float alpha, const float x[], const float y[], const float beta, float c[]){
int lda = transA == CblasNoTrans ? m : k;
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(const enum CBLAS_TRANSPOSE transA, const enum CBLAS_TRANSPOSE transB, const int m, const int n, const int k, const double alpha, const double x[], const double y[], const double beta, double c[]){
int lda = transA == CblasNoTrans ? m : k;
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(const enum CBLAS_TRANSPOSE transA, const enum CBLAS_TRANSPOSE transB, const int m, const int n, const int k, const Complex8 alpha, const Complex8 x[], const Complex8 y[], const Complex8 beta, Complex8 c[]){
int lda = transA == CblasNoTrans ? m : k;
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(const enum CBLAS_TRANSPOSE transA, const enum CBLAS_TRANSPOSE transB, const int m, const int n, const int k, const Complex16 alpha, const Complex16 x[], const Complex16 y[], const Complex16 beta, Complex16 c[]){
int lda = transA == CblasNoTrans ? m : k;
int ldb = transB == CblasNoTrans ? k : n;
cblas_zgemm(CblasColMajor, transA, transB, m, n, k, &alpha, x, lda, y, ldb, &beta, c, m);
}
/*char getTransChar(enum TRANSPOSE trans){
char cTrans;
switch( trans ){
case CblasNoTrans : cTrans = 'N';
break;
case CblasTrans : cTrans = 'T';
break;
case CblasConjTrans : cTrans = 'C';
break;
}
return cTrans;
}*/
#if GCC
}
#endif

543
src/NativeWrappers/ATLAS/lapack.cpp

@ -1,64 +1,525 @@
#include "common.h"
#include "lapack_common.h"
#include "wrapper_common.h"
#include "blas.h"
#include <algorithm>
extern "C" {
#include "clapack.h"
// to get atlas to link
float _sqrtf(float x) {return sqrt(x);}
}
extern "C" {
template<typename T, typename K>
inline int lu_factor(int m, T a[], int ipiv[],
int (*getrf) (CBLAS_ORDER, const int, const int, K*, const int, int*))
{
int info = getrf(CblasColMajor, m, m, a, m, ipiv);
shift_ipiv_down(m, ipiv);
return info;
};
DLLEXPORT int s_cholesky_factor(int n, float a[]){
int info = clapack_spotrf(CblasColMajor, CblasLower, n, a, n);
for (int i = 0; i < n; ++i)
{
int index = i * n;
for (int j = 0; j < n && i > j; ++j)
{
a[index + j] = 0;
}
}
template<typename T, typename K>
inline int lu_inverse(int n, T a[],
int (*getrf) (CBLAS_ORDER, const int, const int, K*, const int, int*),
int (*getri) (CBLAS_ORDER, const int, K*, const int, const int*))
{
int* ipiv = new int[n];
int info = getrf(CblasColMajor, n, n, a, n, ipiv);
if (info != 0){
delete[] ipiv;
return info;
}
DLLEXPORT int d_cholesky_factor(int n, double* a){
int info = clapack_dpotrf(CblasColMajor, CblasLower, n, a, n);
for (int i = 0; i < n; ++i)
info = getri(CblasColMajor, n, a, n, ipiv);
delete[] ipiv;
return info;
};
template<typename T, typename K>
inline int lu_inverse_factored(int n, T a[], int ipiv[],
int (*getri) (CBLAS_ORDER, const int, K*, const int, const int*))
{
shift_ipiv_up(n, ipiv);
int info = getri(CblasColMajor,n, a, n, ipiv);
shift_ipiv_down(n, ipiv);
return info;
}
template<typename T, typename K>
inline int lu_solve_factored(int n, int nrhs, T a[], int ipiv[], T b[],
int (*getrs) (CBLAS_ORDER, CBLAS_TRANSPOSE, const int, const int, const K*, const int, const int*, K*, const int))
{
shift_ipiv_up(n, ipiv);
int info = getrs(CblasColMajor, CblasNoTrans, n, nrhs, a, n, ipiv, b, n);
shift_ipiv_down(n, ipiv);
return info;
}
template<typename T, typename K>
inline int lu_solve(int n, int nrhs, T a[], T b[],
int (*getrf) (CBLAS_ORDER, const int, const int, K*, const int, int*),
int (*getrs) (CBLAS_ORDER, CBLAS_TRANSPOSE, const int, const int, const K*, const int, const int*, K*, const int))
{
T* clone = Clone(n, n, a);
int* ipiv = new int[n];
int info = getrf(CblasColMajor, n, n, clone, n, ipiv);
if (info != 0){
delete[] ipiv;
delete[] clone;
return info;
}
info = getrs(CblasColMajor, CblasNoTrans, n, nrhs, clone, n, ipiv, b, n);
delete[] ipiv;
delete[] clone;
return info;
}
template<typename T, typename K>
inline int cholesky_factor(int n, T* a, int (*potrf) (CBLAS_ORDER, CBLAS_UPLO, const int, K*, const int))
{
int info = potrf(CblasColMajor, CblasLower, n, a, n);
T zero = T();
for (int i = 0; i < n; ++i)
{
int index = i * n;
for (int j = 0; j < n && i > j; ++j)
{
int index = i * n;
for (int j = 0; j < n && i > j; ++j)
{
a[index + j] = 0;
}
a[index + j] = zero;
}
}
return info;
}
template<typename T, typename K>
inline int cholesky_solve(int n, int nrhs, T a[], T b[],
int (*potrf) (CBLAS_ORDER, CBLAS_UPLO, const int, K*, const int),
int (*potrs) (CBLAS_ORDER, CBLAS_UPLO, const int, const int, const K*, const int, K*, const int))
{
T* clone = Clone(n, n, a);
int info = potrf(CblasColMajor, CblasLower, n, clone, n);
if (info != 0){
delete[] clone;
return info;
}
DLLEXPORT int c_cholesky_factor(int n, Complex8 a[]){
int info = clapack_cpotrf(CblasColMajor, CblasLower, n, a, n);
Complex8 zero;
zero.real = 0.0;
zero.real = 0.0;
for (int i = 0; i < n; ++i)
info = potrs(CblasColMajor, CblasLower, n, nrhs, clone, n, b, n);
delete[] clone;
return info;
}
template<typename T, typename K>
inline int cholesky_solve_factored(int n, int nrhs, T a[], T b[],
int (*potrs) (CBLAS_ORDER, CBLAS_UPLO, const int, const int, const K*, const int, K*, const int))
{
return potrs(CblasColMajor, CblasLower, n, nrhs, a, n, b, n);
}
template<typename T, typename K>
inline int qr_factor(int m, int n, T r[], T tau[], T q[], T work[], int len,
int (*geqrf) (const int, const int, K*, const int, T*),
int (*orgqr) (const int, const int, const int, K*, const int, const K*))
{
int info = geqrf(m, n, r, m, tau);
for (int i = 0; i < m; ++i)
{
for (int j = 0; j < m && j < n; ++j)
{
int index = i * n;
for (int j = 0; j < n && i > j; ++j)
if (i > j)
{
a[index + j] = zero;
q[j * m + i] = r[j * m + i];
}
}
return info;
}
DLLEXPORT int z_cholesky_factor(int n, Complex16 a[]){
int info = clapack_zpotrf(CblasColMajor, CblasLower, n, a, n);
Complex16 zero;
zero.real = 0.0;
zero.real = 0.0;
for (int i = 0; i < n; ++i)
//compute the q elements explicitly
if (m <= n)
{
info = orgqr(m, m, m, q, m, tau);
}
else
{
info = orgqr(m, m, n, q, m, tau);
}
return info;
}
template<typename T>
inline int qr_thin_factor(int m, int n, T q[], T tau[], T r[], T work[], int len,
void (*geqrf) (const int*, const int*, T*, const int*, T*, T*, const int*, int*),
void (*orgqr) (const int*, const int*, const int*, T*, const int*, const T*, T*, const int*, int*))
{
int info = 0;
geqrf(&m, &n, q, &m, tau, work, &len, &info);
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n; ++j)
{
int index = i * n;
for (int j = 0; j < n && i > j; ++j)
{
a[index + j] = zero;
if( i <= j) {
r[j * n + i] = q[j * m + i];
}
}
return info;
}
orgqr(&m, &n, &n, q, &m, tau, work, &len, &info);
return info;
}
template<typename T>
inline int qr_solve(int m, int n, int bn, T a[], T b[], T x[], T work[], int len,
void (*gels) (const char*, const int*, const int*, const int*, T*,
const int*, T* b, const int*, T*, const int*, int*))
{
T* clone_a = new T[m*n];
std::memcpy(clone_a, a, m*n*sizeof(T));
T* clone_b = new T[m*bn];
std::memcpy(clone_b, b, m*bn*sizeof(T));
char N = 'N';
int info = 0;
gels(&N, &m, &n, &bn, clone_a, &m, clone_b, &m, work, &len, &info);
copyBtoX(n, n, bn, clone_b, x);
delete[] clone_a;
delete[] clone_b;
return info;
}
template<typename T>
inline int qr_solve_factored(int m, int n, int bn, T r[], T b[], T tau[], T x[], T work[], int len,
void (*ormqr) (const char*, const char*, const int*, const int*, const int*,
const T*, const int*, const T*, T*, const int*, T*, const int*, int* info),
void (*trsm) (const CBLAS_ORDER, const CBLAS_SIDE, const CBLAS_UPLO, const CBLAS_TRANSPOSE, const CBLAS_DIAG,
const int, const int, const T, const T*, const int, T*, const int))
{
T* clone_b = new T[m*bn];
std::memcpy(clone_b, b, m*bn*sizeof(T));
char side ='L';
char tran = 'T';
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(n, n, bn, clone_b, x);
delete[] clone_b;
return info;
}
template<typename T>
inline int complex_qr_solve_factored(int m, int n, int bn, T r[], T b[], T tau[], T x[], T work[], int len,
void (*unmqr) (const char*, const char*, const int*, const int*, const int*,
const T*, const int*, const T*, T*, const int*, T*, const int*, int* info),
void (*trsm) (const CBLAS_ORDER, const CBLAS_SIDE, const CBLAS_UPLO, const CBLAS_TRANSPOSE, const CBLAS_DIAG,
const int, const int, const void*, const void*, const int, void*, const int ldb))
{
T* clone_b = new T[m*bn];
std::memcpy(clone_b, b, m*bn*sizeof(T));
char side ='L';
char tran = 'C';
int info = 0;
unmqr(&side, &tran, &m, &bn, &n, r, &m, tau, clone_b, &m, work, &len, &info);
T one = {1.0f, 0.0f};
trsm(CblasColMajor, CblasLeft, CblasUpper, CblasNoTrans, CblasNonUnit, n, bn, &one, r, m, clone_b, m);
copyBtoX(n, n, bn, clone_b, x);
delete[] clone_b;
return info;
}
template<typename T>
inline int svd_factor(bool compute_vectors, int m, int n, T a[], T s[], T u[], T v[], T work[], int len,
void (*gesvd) (const char*, const char*, const int*, const int*, T*, const int*,
T*, T*, const int*, T*, const int*, T*, const int*, int*))
{
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>
inline int complex_svd_factor(bool compute_vectors, int m, int n, T a[], T s[], T u[], T v[], T work[], int len,
void (*gesvd) (const char*, const char*, const int*, const int*, T*, const int*,
R*, T*, const int*, T*, const int*, T*, const int*, R*, int*))
{
int info = 0;
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(int index = 0; index < dim_s; ++index){
T value = {s_local[index], 0.0f};
s[index] = value;
}
delete[] rwork;
delete[] s_local;
return info;
}
extern "C" {
DLLEXPORT int s_lu_factor(int m, float a[], int ipiv[]) {
return lu_factor<float, float>(m, a, ipiv, clapack_sgetrf);
}
DLLEXPORT int d_lu_factor(int m, double a[], int ipiv[]) {
return lu_factor<double, double>(m, a, ipiv, clapack_dgetrf);
}
DLLEXPORT int c_lu_factor(int m, Complex8 a[], int ipiv[]) {
return lu_factor<Complex8, void>(m, a, ipiv, clapack_cgetrf);
}
DLLEXPORT int z_lu_factor(int m, Complex16 a[], int ipiv[]) {
return lu_factor(m, a, ipiv, clapack_zgetrf);
}
DLLEXPORT int s_lu_inverse(int n, float a[])
{
return lu_inverse<float, float>(n, a, clapack_sgetrf, clapack_sgetri);
}
DLLEXPORT int d_lu_inverse(int n, double a[])
{
return lu_inverse<double, double>(n, a, clapack_dgetrf, clapack_dgetri);
}
DLLEXPORT int c_lu_inverse(int n, Complex8 a[])
{
return lu_inverse<Complex8, void>(n, a, clapack_cgetrf, clapack_cgetri);
}
DLLEXPORT int z_lu_inverse(int n, Complex16 a[])
{
return lu_inverse<Complex16, void>(n, a, clapack_zgetrf, clapack_zgetri);
}
DLLEXPORT int s_lu_inverse_factored(int n, float a[], int ipiv[], float work[], int lwork)
{
return lu_inverse_factored<float, float>(n, a, ipiv, clapack_sgetri);
}
DLLEXPORT int d_lu_inverse_factored(int n, double a[], int ipiv[], double work[], int lwork)
{
return lu_inverse_factored<double, double>(n, a, ipiv, clapack_dgetri);
}
DLLEXPORT int c_lu_inverse_factored(int n, Complex8 a[], int ipiv[], Complex8 work[], int lwork)
{
return lu_inverse_factored<Complex8, void>(n, a, ipiv, clapack_cgetri);
}
DLLEXPORT int z_lu_inverse_factored(int n, Complex16 a[], int ipiv[], Complex16 work[], int lwork)
{
return lu_inverse_factored<Complex16, void>(n, a, ipiv, clapack_zgetri);
}
DLLEXPORT int s_lu_solve_factored(int n, int nrhs, float a[], int ipiv[], float b[])
{
return lu_solve_factored<float, float>(n, nrhs, a, ipiv, b, clapack_sgetrs);
}
DLLEXPORT int d_lu_solve_factored(int n, int nrhs, double a[], int ipiv[], double b[])
{
return lu_solve_factored<double, double>(n, nrhs, a, ipiv, b, clapack_dgetrs);
}
DLLEXPORT int c_lu_solve_factored(int n, int nrhs, Complex8 a[], int ipiv[], Complex8 b[])
{
return lu_solve_factored<Complex8, void>(n, nrhs, a, ipiv, b, clapack_cgetrs);
}
DLLEXPORT int z_lu_solve_factored(int n, int nrhs, Complex16 a[], int ipiv[], Complex16 b[])
{
return lu_solve_factored<Complex16, void>(n, nrhs, a, ipiv, b, clapack_zgetrs);
}
DLLEXPORT int s_lu_solve(int n, int nrhs, float a[], float b[])
{
return lu_solve<float, float>(n, nrhs, a, b, clapack_sgetrf, clapack_sgetrs);
}
DLLEXPORT int d_lu_solve(int n, int nrhs, double a[], double b[])
{
return lu_solve<double, double>(n, nrhs, a, b, clapack_dgetrf, clapack_dgetrs);
}
DLLEXPORT int c_lu_solve(int n, int nrhs, Complex8 a[], Complex8 b[])
{
return lu_solve<Complex8, void>(n, nrhs, a, b, clapack_cgetrf, clapack_cgetrs);
}
DLLEXPORT int z_lu_solve(int n, int nrhs, Complex16 a[], Complex16 b[])
{
return lu_solve<Complex16, void>(n, nrhs, a, b, clapack_zgetrf, clapack_zgetrs);
}
DLLEXPORT int s_cholesky_factor(int n, float a[]){
return cholesky_factor<float, float>(n, a, clapack_spotrf);
}
DLLEXPORT int d_cholesky_factor(int n, double* a){
return cholesky_factor<double, double>(n, a, clapack_dpotrf);
}
DLLEXPORT int c_cholesky_factor(int n, Complex8 a[]){
return cholesky_factor<Complex8, void>(n, a, clapack_cpotrf);
}
DLLEXPORT int z_cholesky_factor(int n, Complex16 a[]){
return cholesky_factor<Complex16, void>(n, a, clapack_zpotrf);
}
DLLEXPORT int s_cholesky_solve(int n, int nrhs, float a[], float b[])
{
return cholesky_solve<float, float>(n, nrhs, a, b, clapack_spotrf, clapack_spotrs);
}
DLLEXPORT int d_cholesky_solve(int n, int nrhs, double a[], double b[])
{
return cholesky_solve<double, double>(n, nrhs, a, b, clapack_dpotrf, clapack_dpotrs);
}
DLLEXPORT int c_cholesky_solve(int n, int nrhs, Complex8 a[], Complex8 b[])
{
return cholesky_solve<Complex8, void>(n, nrhs, a, b, clapack_cpotrf, clapack_cpotrs);
}
DLLEXPORT int z_cholesky_solve(int n, int nrhs, Complex16 a[], Complex16 b[])
{
return cholesky_solve<Complex16, void>(n, nrhs, a, b, clapack_zpotrf, clapack_zpotrs);
}
DLLEXPORT int s_cholesky_solve_factored(int n, int nrhs, float a[], float b[])
{
return cholesky_solve_factored<float, float>(n, nrhs, a, b, clapack_spotrs);
}
DLLEXPORT int d_cholesky_solve_factored(int n, int nrhs, double a[], double b[])
{
return cholesky_solve_factored<double, double>(n, nrhs, a, b, clapack_dpotrs);
}
DLLEXPORT int c_cholesky_solve_factored(int n, int nrhs, Complex8 a[], Complex8 b[])
{
return cholesky_solve_factored<Complex8, void>(n, nrhs, a, b, clapack_cpotrs);
}
DLLEXPORT int z_cholesky_solve_factored(int n, int nrhs, Complex16 a[], Complex16 b[])
{
return cholesky_solve_factored<Complex16, void>(n, nrhs, a, b, clapack_zpotrs);
}
/*DLLEXPORT int s_qr_factor(int m, int n, float r[], float tau[], float q[], float work[], int len)
{
return qr_factor<float, float>(m, n, r, tau, q, work, len, clapack_sgeqrf, clapack_sorgqr);
}
DLLEXPORT int s_qr_thin_factor(int m, int n, float q[], float tau[], float r[], float work[], int len)
{
return qr_thin_factor<float>(m, n, q, tau, r, work, len, clapack_sgeqrf, clapack_sorgqr);
}
DLLEXPORT int d_qr_factor(int m, int n, double r[], double tau[], double q[], double work[], int len)
{
return qr_factor<double>(m, n, r, tau, q, work, len, clapack_dgeqrf, clapack_dorgqr);
}
DLLEXPORT int d_qr_thin_factor(int m, int n, double q[], double tau[], double r[], double work[], int len)
{
return qr_thin_factor<double>(m, n, q, tau, r, work, len, clapack_dgeqrf, clapack_dorgqr);
}
DLLEXPORT int c_qr_factor(int m, int n, Complex8 r[], Complex8 tau[], Complex8 q[], Complex8 work[], int len)
{
return qr_factor<Complex8>(m, n, r, tau, q, work, len, clapack_cgeqrf, clapack_cungqr);
}
DLLEXPORT int c_qr_thin_factor(int m, int n, Complex8 q[], Complex8 tau[], Complex8 r[], Complex8 work[], int len)
{
return qr_thin_factor<Complex8>(m, n, q, tau, r, work, len, clapack_cgeqrf, clapack_cungqr);
}
DLLEXPORT int z_qr_factor(int m, int n, Complex16 r[], Complex16 tau[], Complex16 q[])
{
return qr_factor<Complex16>(m, n, r, tau, q, work, len, clapack_zgeqrf, clapack_zungqr);
}
DLLEXPORT int z_qr_thin_factor(int m, int n, Complex16 q[], Complex16 tau[], Complex16 r[])
{
return qr_thin_factor<Complex16>(m, n, q, tau, r, work, len, clapack_zgeqrf, clapack_zungqr);
}
DLLEXPORT int s_qr_solve(int m, int n, int bn, float a[], float b[], float x[], float work[], int len)
{
return qr_solve<float>(m, n, bn, a, b, x, work, len, sgels);
}
DLLEXPORT int d_qr_solve(int m, int n, int bn, double a[], double b[], double x[], double work[], int len)
{
return qr_solve<double>(m, n, bn, a, b, x, work, len, dgels);
}
DLLEXPORT int c_qr_solve(int m, int n, int bn, Complex8 a[], Complex8 b[], Complex8 x[], Complex8 work[], int len)
{
return qr_solve<Complex8>(m, n, bn, a, b, x, work, len, cgels);
}
DLLEXPORT int z_qr_solve(int m, int n, int bn, Complex16 a[], Complex16 b[], Complex16 x[], Complex16 work[], int len)
{
return qr_solve<Complex16>(m, n, bn, a, b, x, work, len, zgels);
}
DLLEXPORT int s_qr_solve_factored(int m, int n, int bn, float r[], float b[], float tau[], float x[], float work[], int len)
{
return qr_solve_factored<float>(m, n, bn, r, b, tau, x, work, len, sormqr, cblas_strsm);
}
DLLEXPORT int d_qr_solve_factored(int m, int n, int bn, double r[], double b[], double tau[], double x[], double work[], int len)
{
return qr_solve_factored<double>(m, n, bn, r, b, tau, x, work, len, dormqr, cblas_dtrsm);
}
DLLEXPORT int c_qr_solve_factored(int m, int n, int bn, Complex8 r[], Complex8 b[], Complex8 tau[], Complex8 x[], Complex8 work[], int len)
{
return complex_qr_solve_factored<Complex8>(m, n, bn, r, b, tau, x, work, len, cunmqr, cblas_ctrsm);
}
DLLEXPORT int z_qr_solve_factored(int m, int n, int bn, Complex16 r[], Complex16 b[], Complex16 tau[], Complex16 x[], Complex16 work[], int len)
{
return complex_qr_solve_factored<Complex16>(m, n, bn, r, b, tau, x, work, len, zunmqr, cblas_ztrsm);
}
DLLEXPORT int s_svd_factor(bool compute_vectors, int m, int n, float a[], float s[], float u[], float v[], float work[], int len)
{
return svd_factor<float>(compute_vectors, m, n, a, s, u, v, work, len, sgesvd);
}
DLLEXPORT int d_svd_factor(bool compute_vectors, int m, int n, double a[], double s[], double u[], double v[], double work[], int len)
{
return svd_factor<double>(compute_vectors, m, n, a, s, u, v, work, len, dgesvd);
}
DLLEXPORT int c_svd_factor(bool compute_vectors, int m, int n, Complex8 a[], Complex8 s[], Complex8 u[], Complex8 v[], Complex8 work[], int len)
{
return complex_svd_factor<Complex8, float>(compute_vectors, m, n, a, s, u, v, work, len, cgesvd);
}
DLLEXPORT int z_svd_factor(bool compute_vectors, int m, int n, Complex16 a[], Complex16 s[], Complex16 u[], Complex16 v[], Complex16 work[], int len)
{
return complex_svd_factor<Complex16, double>(compute_vectors, m, n, a, s, u, v, work, len, zgesvd);
}*/
}

3
src/NativeWrappers/Common/lapack_common.h

@ -18,8 +18,7 @@ inline void shift_ipiv_up(int m, int ipiv[]){
}
template<typename T>
inline T* Clone(const int m, const int n, const T* a)
{
inline T* Clone(const int m, const int n, const T* a){
T* clone = new T[m*n];
memcpy(clone, a, m*n*sizeof(T));
return clone;

8
src/NativeWrappers/Common/resource.rc

@ -51,8 +51,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,2,1,0
PRODUCTVERSION 1,2,1,0
FILEVERSION 1,3,0,0
PRODUCTVERSION 1,3,0,0
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -70,12 +70,12 @@ BEGIN
VALUE "Comments", "http://numerics.mathdotnet.com/"
VALUE "CompanyName", "Math.NET"
VALUE "FileDescription", "MathNET Numerics Native Wrapper"
VALUE "FileVersion", "1.2.1.0"
VALUE "FileVersion", "1.3.0.0"
VALUE "InternalName", "Math.NET"
VALUE "LegalCopyright", "Copyright (C) Math.NET 2009-2013"
VALUE "OriginalFilename", "MathNet.Numerics"
VALUE "ProductName", "Math.NET Numerics"
VALUE "ProductVersion", "1.2.1.0"
VALUE "ProductVersion", "1.3.0.0"
END
END
BLOCK "VarFileInfo"

9
src/NativeWrappers/Linux/build.sh

@ -1,6 +1,11 @@
export INTEL=/opt/intel
export MKL=$INTEL/mkl
export OPENMP=$INTEL/composerxe/lib
g++ --shared -fPIC -o ./x64/MathNet.Numerics.MKL.so -I$MKL/include -I../Common ../MKL/vector_functions.c ../MKL/blas.c ../MKL/lapack.cpp $INTEL/lib/intel64/libiomp5.a $MKL/lib/intel64/libmkl_intel_lp64.a $MKL/lib/intel64/libmkl_intel_thread.a $MKL/lib/intel64/libmkl_core.a
g++ -DGCC -m64 --shared -fPIC -o ../../../../MKL/Linux/x64/MathNet.Numerics.MKL.dll -I$MKL/include -I../Common ../MKL/vector_functions.c ../MKL/blas.c ../MKL/lapack.cpp -Wl,--start-group $MKL/lib/intel64/libmkl_intel_lp64.a $MKL/lib/intel64/libmkl_intel_thread.a $MKL/lib/intel64/libmkl_core.a -Wl,--end-group -L$OPENMP/intel64 -liomp5 -lpthread -lm
g++ -m32 --shared -fPIC -o ./x86/MathNet.Numerics.MKL.so -I$MKL/include -I../Common ../MKL/vector_functions.c ../MKL/blas.c ../MKL/lapack.cpp $INTEL/lib/ia32/libiomp5.a $MKL/lib/ia32/libmkl_intel.a $MKL/lib/ia32/libmkl_intel_thread.a $MKL/lib/ia32/libmkl_core.a
cp $OPENMP/intel64/libiomp5.so ../../../../MKL/Linux/x64/
g++ -DGCC -m32 --shared -fPIC -o ../../../../MKL/Linux/x86/MathNet.Numerics.MKL.dll -I$MKL/include -I../Common ../MKL/vector_functions.c ../MKL/blas.c ../MKL/lapack.cpp -Wl,--start-group $MKL/lib/ia32/libmkl_intel.a $MKL/lib/ia32/libmkl_intel_thread.a $MKL/lib/ia32/libmkl_core.a -Wl,--end-group -L$OPENMP/ia32 -liomp5 -lpthread -lm
cp $OPENMP/ia32/libiomp5.so ../../../../MKL/Linux/x86/

7
src/NativeWrappers/MKL/blas.c

@ -1,6 +1,9 @@
#include "mkl_cblas.h"
#include "wrapper_common.h"
#if GCC
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);
}
@ -80,3 +83,7 @@ DLLEXPORT void z_matrix_multiply(CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB,
cblas_zgemm(CblasColMajor, transA, transB, m, n, k, &alpha, x, lda, y, ldb, &beta, c, m);
}
#if GCC
}
#endif

1145
src/NativeWrappers/MKL/lapack.cpp

File diff suppressed because it is too large

7
src/NativeWrappers/MKL/vector_functions.c

@ -1,7 +1,9 @@
#include "mkl_vml.h"
#include "wrapper_common.h"
#if GCC
extern "C" {
#endif
DLLEXPORT void s_vector_add( const int n, const float x[], const float y[], float result[] ){
vsAdd( n, x, y, result );
}
@ -65,3 +67,6 @@ DLLEXPORT void z_vector_multiply( const int n, const MKL_Complex16 x[], const MK
DLLEXPORT void z_vector_divide( const int n, const MKL_Complex16 x[], const MKL_Complex16 y[], MKL_Complex16 result[] ){
vzDiv( n, x, y, result );
}
#if GCC
}
#endif

160
src/NativeWrappers/Windows/ATLASWrapper/ATLASWrapper.vcxproj

@ -0,0 +1,160 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{2362B8AC-C52B-45E4-A1BF-C682A4DB4220}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>ATLASWrapper</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>D:\Source\ATLAS\include;..\..\Common;$(IncludePath)</IncludePath>
<OutDir>$(SolutionDir)..\..\..\..\ATLAS\Windows\x86\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>D:\Source\ATLAS\include;..\..\Common;$(IncludePath)</IncludePath>
<OutDir>$(SolutionDir)..\..\..\..\ATLAS\Windows\x64\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>D:\Source\ATLAS\include;..\..\Common;$(IncludePath)</IncludePath>
<OutDir>$(SolutionDir)..\..\..\..\ATLAS\Windows\x86\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>D:\Source\ATLAS\include;..\..\Common;$(IncludePath)</IncludePath>
<OutDir>$(SolutionDir)..\..\..\..\ATLAS\Windows\x64\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;ATLASWRAPPER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>libptcblas.a;libatlas.a;libptlapack.a;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;ATLASWRAPPER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>libptcblas.a;libatlas.a;libptlapack.a;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;ATLASWRAPPER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>libptcblas.a;libatlas.a;libptlapack.a;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;ATLASWRAPPER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>libptcblas.a;libatlas.a;libptlapack.a;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ResourceCompile Include="..\..\Common\resource.rc" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\ATLAS\blas.c" />
<ClCompile Include="..\..\ATLAS\lapack.cpp" />
<ClCompile Include="..\..\Common\WindowsDLL.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

33
src/NativeWrappers/Windows/ATLASWrapper/ATLASWrapper.vcxproj.filters

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="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;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\Common\resource.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\Common\WindowsDLL.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\ATLAS\blas.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\ATLAS\lapack.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

5
src/NativeWrappers/Windows/MKL/MKLWrapper.vcxproj

@ -241,6 +241,7 @@
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs>
<AdditionalOptions>/Qvec-report:1 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<AdditionalDependencies>libiomp5md.lib;mkl_intel_c.lib;mkl_intel_thread.lib;mkl_core.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -271,6 +272,7 @@
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs>
<AdditionalOptions>/Qvec-report:1 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<AdditionalDependencies>libiomp5md.lib;mkl_intel_lp64.lib;mkl_intel_thread.lib;mkl_core.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -292,9 +294,6 @@
<ClCompile Include="..\..\MKL\lapack.cpp" />
<ClCompile Include="..\..\MKL\vector_functions.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\Common\wrapper_common.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\Common\resource.rc" />
</ItemGroup>

5
src/NativeWrappers/Windows/MKL/MKLWrapper.vcxproj.filters

@ -28,11 +28,6 @@
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\Common\wrapper_common.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\Common\resource.rc">
<Filter>Resource Files</Filter>

18
src/NativeWrappers/Windows/NativeWrappers.sln

@ -12,22 +12,40 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Common", "Common", "{5A0892
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MKLWrapper", "MKL\MKLWrapper.vcxproj", "{C0B0DBA9-7FB0-4C87-BDB1-3EED19DC2B8F}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ATLASWrapper", "ATLASWrapper\ATLASWrapper.vcxproj", "{2362B8AC-C52B-45E4-A1BF-C682A4DB4220}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Mixed Platforms = Debug|Mixed Platforms
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Mixed Platforms = Release|Mixed Platforms
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C0B0DBA9-7FB0-4C87-BDB1-3EED19DC2B8F}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{C0B0DBA9-7FB0-4C87-BDB1-3EED19DC2B8F}.Debug|Mixed Platforms.Build.0 = Debug|Win32
{C0B0DBA9-7FB0-4C87-BDB1-3EED19DC2B8F}.Debug|Win32.ActiveCfg = Debug|Win32
{C0B0DBA9-7FB0-4C87-BDB1-3EED19DC2B8F}.Debug|Win32.Build.0 = Debug|Win32
{C0B0DBA9-7FB0-4C87-BDB1-3EED19DC2B8F}.Debug|x64.ActiveCfg = Debug|x64
{C0B0DBA9-7FB0-4C87-BDB1-3EED19DC2B8F}.Debug|x64.Build.0 = Debug|x64
{C0B0DBA9-7FB0-4C87-BDB1-3EED19DC2B8F}.Release|Mixed Platforms.ActiveCfg = Release|Win32
{C0B0DBA9-7FB0-4C87-BDB1-3EED19DC2B8F}.Release|Mixed Platforms.Build.0 = Release|Win32
{C0B0DBA9-7FB0-4C87-BDB1-3EED19DC2B8F}.Release|Win32.ActiveCfg = Release|Win32
{C0B0DBA9-7FB0-4C87-BDB1-3EED19DC2B8F}.Release|Win32.Build.0 = Release|Win32
{C0B0DBA9-7FB0-4C87-BDB1-3EED19DC2B8F}.Release|x64.ActiveCfg = Release|x64
{C0B0DBA9-7FB0-4C87-BDB1-3EED19DC2B8F}.Release|x64.Build.0 = Release|x64
{2362B8AC-C52B-45E4-A1BF-C682A4DB4220}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{2362B8AC-C52B-45E4-A1BF-C682A4DB4220}.Debug|Mixed Platforms.Build.0 = Debug|Win32
{2362B8AC-C52B-45E4-A1BF-C682A4DB4220}.Debug|Win32.ActiveCfg = Debug|Win32
{2362B8AC-C52B-45E4-A1BF-C682A4DB4220}.Debug|Win32.Build.0 = Debug|Win32
{2362B8AC-C52B-45E4-A1BF-C682A4DB4220}.Debug|x64.ActiveCfg = Debug|Win32
{2362B8AC-C52B-45E4-A1BF-C682A4DB4220}.Release|Mixed Platforms.ActiveCfg = Release|Win32
{2362B8AC-C52B-45E4-A1BF-C682A4DB4220}.Release|Mixed Platforms.Build.0 = Release|Win32
{2362B8AC-C52B-45E4-A1BF-C682A4DB4220}.Release|Win32.ActiveCfg = Release|Win32
{2362B8AC-C52B-45E4-A1BF-C682A4DB4220}.Release|Win32.Build.0 = Release|Win32
{2362B8AC-C52B-45E4-A1BF-C682A4DB4220}.Release|x64.ActiveCfg = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

46
src/Numerics/Algorithms/LinearAlgebra/ILinearAlgebraProvider.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2010 Math.NET
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -93,5 +93,49 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
/// The requested <see cref="Norm"/> of the matrix.
/// </returns>
Complex MatrixNorm(Norm norm, int rows, int columns, Complex[] matrix, double[] work);
/// <summary>
/// Computes the eigenvalues and eigenvectors of a matrix.
/// </summary>
/// <param name="isSymmetric">Wether the matrix is symmetric or not.</param>
/// <param name="order">The order of the matrix.</param>
/// <param name="matrix">The matrix to decompose. The lenth of the array must be order * order.</param>
/// <param name="matrixEv">On output, the matrix contains the eigen vectors. The lenth of the array must be order * order.</param>
/// <param name="vectorEv">On output, the eigen values (λ) of matrix in ascending value. The length of the arry must <paramref name="order"/>.</param>
/// <param name="matrixD">On output, the block diagonal eigenvalue matrix. The lenth of the array must be order * order.</param>
void EigenDecomp(bool isSymmetric, int order, float[] matrix, float[] matrixEv, Complex[] vectorEv, float[] matrixD);
/// <summary>
/// Computes the eigenvalues and eigenvectors of a matrix.
/// </summary>
/// <param name="isSymmetric">Wether the matrix is symmetric or not.</param>
/// <param name="order">The order of the matrix.</param>
/// <param name="matrix">The matrix to decompose. The lenth of the array must be order * order.</param>
/// <param name="matrixEv">On output, the matrix contains the eigen vectors. The lenth of the array must be order * order.</param>
/// <param name="vectorEv">On output, the eigen values (λ) of matrix in ascending value. The length of the arry must <paramref name="order"/>.</param>
/// <param name="matrixD">On output, the block diagonal eigenvalue matrix. The lenth of the array must be order * order.</param>
void EigenDecomp(bool isSymmetric, int order, double[] matrix, double[] matrixEv, Complex[] vectorEv, double[] matrixD);
/// <summary>
/// Computes the eigenvalues and eigenvectors of a matrix.
/// </summary>
/// <param name="isSymmetric">Wether the matrix is symmetric or not.</param>
/// <param name="order">The order of the matrix.</param>
/// <param name="matrix">The matrix to decompose. The lenth of the array must be order * order.</param>
/// <param name="matrixEv">On output, the matrix contains the eigen vectors. The lenth of the array must be order * order.</param>
/// <param name="vectorEv">On output, the eigen values (λ) of matrix in ascending value. The length of the arry must <paramref name="order"/>.</param>
/// <param name="matrixD">On output, the block diagonal eigenvalue matrix. The lenth of the array must be order * order.</param>
void EigenDecomp(bool isSymmetric, int order, Complex32[] matrix, Complex32[] matrixEv, Complex[] vectorEv, Complex32[] matrixD);
/// <summary>
/// Computes the eigenvalues and eigenvectors of a matrix.
/// </summary>
/// <param name="isSymmetric">Wether the matrix is symmetric or not.</param>
/// <param name="order">The order of the matrix.</param>
/// <param name="matrix">The matrix to decompose. The lenth of the array must be order * order.</param>
/// <param name="matrixEv">On output, the matrix contains the eigen vectors. The lenth of the array must be order * order.</param>
/// <param name="vectorEv">On output, the eigen values (λ) of matrix in ascending value. The length of the arry must <paramref name="order"/>.</param>
/// <param name="matrixD">On output, the block diagonal eigenvalue matrix. The lenth of the array must be order * order.</param>
void EigenDecomp(bool isSymmetric, int order, Complex[] matrix, Complex[] matrixEv, Complex[] vectorEv, Complex[] matrixD);
}
}

572
src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.Complex.cs

File diff suppressed because it is too large

91
src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.Complex32.cs

@ -3,7 +3,7 @@
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
// Copyright (c) 2009-2010 Math.NET
// Copyright (c) 2009-2013 Math.NET
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
@ -24,14 +24,15 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System.Numerics;
using MathNet.Numerics.LinearAlgebra.Generic.Factorization;
namespace MathNet.Numerics.Algorithms.LinearAlgebra
{
using System;
using Properties;
using Threading;
using System.Numerics;
using Numerics.LinearAlgebra.Complex32.Factorization;
using Numerics.LinearAlgebra.Generic.Factorization;
using Numerics.LinearAlgebra.Complex32;
/// <summary>
/// The managed linear algebra provider.
@ -2984,5 +2985,87 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
}
}
}
/// <summary>
/// Computes the eigenvalues and eigenvectors of a matrix.
/// </summary>
/// <param name="isSymmetric">Wether the matrix is symmetric or not.</param>
/// <param name="order">The order of the matrix.</param>
/// <param name="matrix">The matrix to decompose. The lenth of the array must be order * order.</param>
/// <param name="matrixEv">On output, the matrix contains the eigen vectors. The lenth of the array must be order * order.</param>
/// <param name="vectorEv">On output, the eigen values (λ) of matrix in ascending value. The length of the arry must <paramref name="order"/>.</param>
/// <param name="matrixD">On output, the block diagonal eigenvalue matrix. The lenth of the array must be order * order.</param>
public virtual void EigenDecomp(bool isSymmetric, int order, Complex32[] matrix, Complex32[] matrixEv, Complex[] vectorEv, Complex32[] matrixD)
{
if (matrix == null)
{
throw new ArgumentNullException("matrix");
}
if (matrix.Length != order * order )
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order * order), "matrix");
}
if (matrixEv == null)
{
throw new ArgumentNullException("matrixEv");
}
if (matrixEv.Length != order * order )
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order * order), "matrixEv");
}
if (vectorEv == null)
{
throw new ArgumentNullException("vectorEv");
}
if (vectorEv.Length != order)
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order), "vectorEv");
}
if (matrixD == null)
{
throw new ArgumentNullException("matrixD");
}
if (matrixD.Length != order * order )
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order * order), "matrixD");
}
var matrixCopy = new Complex32[matrix.Length];
Array.Copy(matrix, matrixCopy, matrix.Length);
var v = new DenseVector(order);
if (isSymmetric)
{
var tau = new Complex32[order];
var d = new float[order];
var e = new float[order];
DenseEvd.SymmetricTridiagonalize(matrixCopy, d, e, tau, order);
DenseEvd.SymmetricDiagonalize(matrixEv, d, e, order);
DenseEvd.SymmetricUntridiagonalize(matrixEv, matrixCopy, tau, order);
for (var i = 0; i < order; i++)
{
vectorEv[i] = new Complex(d[i], e[i]);
matrixD[i * order + i] = new Complex32(d[i], e[i]);
}
}
else
{
DenseEvd.NonsymmetricReduceToHessenberg(matrixEv, matrixCopy, order);
DenseEvd.NonsymmetricReduceHessenberToRealSchur(v.Values, matrixEv, matrixCopy, order);
for (var i = 0; i < order; i++)
{
vectorEv[i] = new Complex(v[i].Real, v[i].Imaginary);
matrixD[i * order + i] = v[i];
}
}
}
}
}

99
src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.Double.cs

@ -3,7 +3,7 @@
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
// Copyright (c) 2009-2010 Math.NET
// Copyright (c) 2009-2013 Math.NET
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
@ -24,11 +24,11 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using MathNet.Numerics.LinearAlgebra.Generic.Factorization;
namespace MathNet.Numerics.Algorithms.LinearAlgebra
{
using System;
using System.Numerics;
using Numerics.LinearAlgebra.Generic.Factorization;
using Properties;
using Threading;
@ -2933,5 +2933,98 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
}
}
}
/// <summary>
/// Computes the eigenvalues and eigenvectors of a matrix.
/// </summary>
/// <param name="isSymmetric">Wether the matrix is symmetric or not.</param>
/// <param name="order">The order of the matrix.</param>
/// <param name="matrix">The matrix to decompose. The lenth of the array must be order * order.</param>
/// <param name="matrixEv">On output, the matrix contains the eigen vectors. The lenth of the array must be order * order.</param>
/// <param name="vectorEv">On output, the eigen values (λ) of matrix in ascending value. The length of the arry must <paramref name="order"/>.</param>
/// <param name="matrixD">On output, the block diagonal eigenvalue matrix. The lenth of the array must be order * order.</param>
public virtual void EigenDecomp(bool isSymmetric, int order, double[] matrix, double[] matrixEv, Complex[] vectorEv, double[] matrixD)
{
if (matrix == null)
{
throw new ArgumentNullException("matrix");
}
if (matrix.Length != order * order )
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order * order), "matrix");
}
if (matrixEv == null)
{
throw new ArgumentNullException("matrixEv");
}
if (matrixEv.Length != order * order )
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order * order), "matrixEv");
}
if (vectorEv == null)
{
throw new ArgumentNullException("vectorEv");
}
if (vectorEv.Length != order)
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order), "vectorEv");
}
if (matrixD == null)
{
throw new ArgumentNullException("matrixD");
}
if (matrixD.Length != order * order )
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order * order), "matrixD");
}
var d = new double[order];
var e = new double[order];
if (isSymmetric)
{
Buffer.BlockCopy(matrix, 0, matrixEv, 0, matrix.Length * Constants.SizeOfDouble);
var om1 = order - 1;
for (var i = 0; i < order; i++)
{
d[i] = matrixEv[i*order + om1];
}
Numerics.LinearAlgebra.Double.Factorization.DenseEvd.SymmetricTridiagonalize(matrixEv, d, e, order);
Numerics.LinearAlgebra.Double.Factorization.DenseEvd.SymmetricDiagonalize(matrixEv, d, e, order);
}
else
{
var matrixH = new double[matrix.Length];
Buffer.BlockCopy(matrix, 0, matrixH, 0, matrix.Length * Constants.SizeOfDouble);
Numerics.LinearAlgebra.Double.Factorization.DenseEvd.NonsymmetricReduceToHessenberg(matrixEv, matrixH, order);
Numerics.LinearAlgebra.Double.Factorization.DenseEvd.NonsymmetricReduceHessenberToRealSchur(matrixEv, matrixH, d, e, order);
}
for (var i = 0; i < order; i++)
{
vectorEv[i] = new Complex(d[i], e[i]);
var io = i * order;
matrixD[io + i] = d[i];
if (e[i] > 0)
{
matrixD[io + order + i] = e[i];
matrixD[(i+1) * order + i] = e[i];
}
else if (e[i] < 0)
{
matrixD[io - order + i] = e[i];
}
}
}
}
}

98
src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.Single.cs

@ -3,7 +3,7 @@
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
// Copyright (c) 2009-2010 Math.NET
// Copyright (c) 2009-2013 Math.NET
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
@ -24,11 +24,11 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using MathNet.Numerics.LinearAlgebra.Generic.Factorization;
namespace MathNet.Numerics.Algorithms.LinearAlgebra
{
using System;
using System.Numerics;
using Numerics.LinearAlgebra.Generic.Factorization;
using Properties;
using Threading;
@ -2936,5 +2936,97 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
}
}
}
/// <summary>
/// Computes the eigenvalues and eigenvectors of a matrix.
/// </summary>
/// <param name="isSymmetric">Wether the matrix is symmetric or not.</param>
/// <param name="order">The order of the matrix.</param>
/// <param name="matrix">The matrix to decompose. The lenth of the array must be order * order.</param>
/// <param name="matrixEv">On output, the matrix contains the eigen vectors. The lenth of the array must be order * order.</param>
/// <param name="vectorEv">On output, the eigen values (λ) of matrix in ascending value. The length of the arry must <paramref name="order"/>.</param>
/// <param name="matrixD">On output, the block diagonal eigenvalue matrix. The lenth of the array must be order * order.</param>
public virtual void EigenDecomp(bool isSymmetric, int order, float[] matrix, float[] matrixEv, Complex[] vectorEv, float[] matrixD)
{
if (matrix == null)
{
throw new ArgumentNullException("matrix");
}
if (matrix.Length != order * order)
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order * order), "matrix");
}
if (matrixEv == null)
{
throw new ArgumentNullException("matrixEv");
}
if (matrixEv.Length != order * order)
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order * order), "matrixEv");
}
if (vectorEv == null)
{
throw new ArgumentNullException("vectorEv");
}
if (vectorEv.Length != order)
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order), "vectorEv");
}
if (matrixD == null)
{
throw new ArgumentNullException("matrixD");
}
if (matrixD.Length != order * order)
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order * order), "matrixD");
}
var d = new float[order];
var e = new float[order];
if (isSymmetric)
{
Buffer.BlockCopy(matrix, 0, matrixEv, 0, matrix.Length * Constants.SizeOfFloat);
var om1 = order - 1;
for (var i = 0; i < order; i++)
{
d[i] = matrixEv[i * order + om1];
}
Numerics.LinearAlgebra.Single.Factorization.DenseEvd.SymmetricTridiagonalize(matrixEv, d, e, order);
Numerics.LinearAlgebra.Single.Factorization.DenseEvd.SymmetricDiagonalize(matrixEv, d, e, order);
}
else
{
var matrixH = new float[matrix.Length];
Buffer.BlockCopy(matrix, 0, matrixH, 0, matrix.Length * Constants.SizeOfFloat);
Numerics.LinearAlgebra.Single.Factorization.DenseEvd.NonsymmetricReduceToHessenberg(matrixEv, matrixH, order);
Numerics.LinearAlgebra.Single.Factorization.DenseEvd.NonsymmetricReduceHessenberToRealSchur(matrixEv, matrixH, d, e, order);
}
for (var i = 0; i < order; i++)
{
vectorEv[i] = new Complex(d[i], e[i]);
var io = i * order;
matrixD[io + i] = d[i];
if (e[i] > 0)
{
matrixD[io + order + i] = e[i];
}
else if (e[i] < 0)
{
matrixD[io - order + i] = e[i];
}
}
}
}
}

2
src/Numerics/Algorithms/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Complex.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2011 Math.NET
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

143
src/Numerics/Algorithms/LinearAlgebra/Mkl/MklLinearAlgebraProvider.Complex32.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2011 Math.NET
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -28,14 +28,13 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using MathNet.Numerics.LinearAlgebra.Generic.Factorization;
namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{
using System;
using System.Security;
using Numerics.LinearAlgebra.Generic.Factorization;
using Properties;
/// <summary>
/// Intel's Math Kernel Library (MKL) linear algebra provider.
/// </summary>
@ -68,7 +67,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
return SafeNativeMethods.c_dot_product(x.Length, x, y);
}
/// <summary>
/// Adds a scaled vector to another: <c>result = y + alpha*x</c>.
/// </summary>
@ -121,8 +120,8 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
if (x == null)
{
throw new ArgumentNullException("x");
}
}
if (!ReferenceEquals(x, result))
{
Array.Copy(x, 0, result, 0, x.Length);
@ -190,9 +189,9 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
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);
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
if (k != l)
@ -225,7 +224,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("ipiv");
}
if (data.Length != order * order)
if (data.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "data");
}
@ -234,7 +233,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
SafeNativeMethods.c_lu_factor(order, data, ipiv);
}
@ -252,13 +251,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("a");
}
if (a.Length != order * order)
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);
SafeNativeMethods.c_lu_inverse(order, a, work, work.Length);
}
/// <summary>
@ -281,7 +280,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("ipiv");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
@ -292,7 +291,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
}
var work = new Complex32[order];
SafeNativeMethods.c_lu_inverse_factored(order, a, ipiv, work, order);
SafeNativeMethods.c_lu_inverse_factored(order, a, ipiv, work, order);
}
/// <summary>
@ -312,7 +311,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("a");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
@ -327,7 +326,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
SafeNativeMethods.c_lu_inverse(order, a, work, work.Length);
SafeNativeMethods.c_lu_inverse(order, a, work, work.Length);
}
/// <summary>
@ -353,7 +352,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("ipiv");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
@ -373,7 +372,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
SafeNativeMethods.c_lu_inverse_factored(order, a, ipiv, work, order);
SafeNativeMethods.c_lu_inverse_factored(order, a, ipiv, work, order);
}
/// <summary>
@ -392,22 +391,22 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
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");
}
if (ReferenceEquals(a, b))
{
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.c_lu_solve(order, columnsOfB, a, b);
SafeNativeMethods.c_lu_solve(order, columnsOfB, a, b);
}
/// <summary>
@ -432,7 +431,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("ipiv");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
@ -442,7 +441,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
if (b.Length != columnsOfB * order)
if (b.Length != columnsOfB*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
@ -452,7 +451,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.c_lu_solve_factored(order, columnsOfB, a, ipiv, b);
SafeNativeMethods.c_lu_solve_factored(order, columnsOfB, a, ipiv, b);
}
/// <summary>
@ -475,7 +474,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentMustBePositive, "order");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
@ -510,7 +509,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("b");
}
if (b.Length != orderA * columnsB)
if (b.Length != orderA*columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
@ -520,7 +519,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.c_cholesky_solve(orderA, columnsB, a, b);
SafeNativeMethods.c_cholesky_solve(orderA, columnsB, a, b);
}
/// <summary>
@ -544,7 +543,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("b");
}
if (b.Length != orderA * columnsB)
if (b.Length != orderA*columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
@ -554,7 +553,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.c_cholesky_solve_factored(orderA, columnsB, a, b);
SafeNativeMethods.c_cholesky_solve_factored(orderA, columnsB, a, b);
}
/// <summary>
@ -582,7 +581,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("q");
}
if (r.Length != rowsR * columnsR)
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r");
}
@ -592,12 +591,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
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");
}
var work = new Complex32[columnsR * Control.BlockSize];
var work = new Complex32[columnsR*Control.BlockSize];
SafeNativeMethods.c_qr_factor(rowsR, columnsR, r, tau, q, work, work.Length);
}
@ -634,7 +633,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("work");
}
if (r.Length != rowsR * columnsR)
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r");
}
@ -644,14 +643,14 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
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)
if (work.Length < columnsR*Control.BlockSize)
{
work[0] = columnsR * Control.BlockSize;
work[0] = columnsR*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
@ -672,7 +671,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
[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];
var work = new Complex32[columns*Control.BlockSize];
QRSolve(a, rows, columns, b, columnsB, x, work, method);
}
@ -713,17 +712,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
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");
}
@ -735,7 +734,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
if (work.Length < 1)
{
work[0] = rows * Control.BlockSize;
work[0] = rows*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
@ -759,7 +758,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
[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];
var work = new Complex32[columnsR*Control.BlockSize];
QRSolveFactored(q, r, rowsR, columnsR, tau, b, columnsB, x, work, method);
}
@ -821,29 +820,29 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
columnsQ = rowsR = columnsR = columnsA;
}
if (r.Length != rowsR * columnsR)
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR * columnsR), "r");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR*columnsR), "r");
}
if (q.Length != rowsQ * columnsQ)
if (q.Length != rowsQ*columnsQ)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ * columnsQ), "q");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ*columnsQ), "q");
}
if (b.Length != rowsA * columnsB)
if (b.Length != rowsA*columnsB)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA * columnsB), "b");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA*columnsB), "b");
}
if (x.Length != columnsA * columnsB)
if (x.Length != columnsA*columnsB)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA * columnsB), "x");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA*columnsB), "x");
}
if (work.Length < 1)
{
work[0] = rowsA * Control.BlockSize;
work[0] = rowsA*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
@ -895,12 +894,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("vt");
}
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");
}
@ -910,7 +909,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s");
}
var work = new Complex32[(2 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA)];
var work = new Complex32[(2*Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA)];
SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, work);
}
@ -940,20 +939,20 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
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 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);
@ -1005,12 +1004,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
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");
}
@ -1025,9 +1024,9 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentSingleDimensionArray, "work");
}
if (work.Length < (2 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA))
if (work.Length < (2*Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA))
{
work[0] = (2 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA);
work[0] = (2*Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA);
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
@ -1060,7 +1059,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{
throw new ArgumentException(Resources.ArgumentArraysSameLength);
}
if (x.Length != result.Length)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength);
@ -1095,12 +1094,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{
throw new ArgumentException(Resources.ArgumentArraysSameLength);
}
if (x.Length != result.Length)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength);
}
SafeNativeMethods.c_vector_subtract(x.Length, x, y, result);
}
@ -1130,12 +1129,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{
throw new ArgumentException(Resources.ArgumentArraysSameLength);
}
if (x.Length != result.Length)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength);
}
SafeNativeMethods.c_vector_multiply(x.Length, x, y, result);
}
@ -1165,12 +1164,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{
throw new ArgumentException(Resources.ArgumentArraysSameLength);
}
if (x.Length != result.Length)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength);
}
SafeNativeMethods.c_vector_divide(x.Length, x, y, result);
}
}

203
src/Numerics/Algorithms/LinearAlgebra/Mkl/MklLinearAlgebraProvider.double.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2011 Math.NET
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -28,14 +28,14 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using MathNet.Numerics.LinearAlgebra.Generic.Factorization;
namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{
using System;
using System.Numerics;
using System.Security;
using Numerics.LinearAlgebra.Generic.Factorization;
using Properties;
/// <summary>
/// Intel's Math Kernel Library (MKL) linear algebra provider.
/// </summary>
@ -121,8 +121,8 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
if (x == null)
{
throw new ArgumentNullException("x");
}
}
if (!ReferenceEquals(x, result))
{
Array.Copy(x, 0, result, 0, x.Length);
@ -190,9 +190,9 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
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);
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
if (k != l)
@ -225,7 +225,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("ipiv");
}
if (data.Length != order * order)
if (data.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "data");
}
@ -234,7 +234,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
SafeNativeMethods.d_lu_factor(order, data, ipiv);
}
@ -252,13 +252,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("a");
}
if (a.Length != order * order)
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);
SafeNativeMethods.d_lu_inverse(order, a, work, work.Length);
}
/// <summary>
@ -281,7 +281,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("ipiv");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
@ -292,7 +292,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
}
var work = new double[order];
SafeNativeMethods.d_lu_inverse_factored(order, a, ipiv, work, order);
SafeNativeMethods.d_lu_inverse_factored(order, a, ipiv, work, order);
}
/// <summary>
@ -312,7 +312,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("a");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
@ -327,7 +327,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
SafeNativeMethods.d_lu_inverse(order, a, work, work.Length);
SafeNativeMethods.d_lu_inverse(order, a, work, work.Length);
}
/// <summary>
@ -353,7 +353,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("ipiv");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
@ -373,7 +373,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
SafeNativeMethods.d_lu_inverse_factored(order, a, ipiv, work, order);
SafeNativeMethods.d_lu_inverse_factored(order, a, ipiv, work, order);
}
/// <summary>
@ -392,22 +392,22 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
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");
}
if (ReferenceEquals(a, b))
{
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.d_lu_solve(order, columnsOfB, a, b);
SafeNativeMethods.d_lu_solve(order, columnsOfB, a, b);
}
/// <summary>
@ -432,7 +432,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("ipiv");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
@ -442,7 +442,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
if (b.Length != columnsOfB * order)
if (b.Length != columnsOfB*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
@ -452,7 +452,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.d_lu_solve_factored(order, columnsOfB, a, ipiv, b);
SafeNativeMethods.d_lu_solve_factored(order, columnsOfB, a, ipiv, b);
}
/// <summary>
@ -475,7 +475,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentMustBePositive, "order");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
@ -510,7 +510,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("b");
}
if (b.Length != orderA * columnsB)
if (b.Length != orderA*columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
@ -520,7 +520,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.d_cholesky_solve(orderA, columnsB, a, b);
SafeNativeMethods.d_cholesky_solve(orderA, columnsB, a, b);
}
/// <summary>
@ -544,7 +544,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("b");
}
if (b.Length != orderA * columnsB)
if (b.Length != orderA*columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
@ -554,7 +554,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.d_cholesky_solve_factored(orderA, columnsB, a, b);
SafeNativeMethods.d_cholesky_solve_factored(orderA, columnsB, a, b);
}
/// <summary>
@ -582,7 +582,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("q");
}
if (r.Length != rowsR * columnsR)
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r");
}
@ -592,12 +592,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
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");
}
var work = new double[columnsR * Control.BlockSize];
var work = new double[columnsR*Control.BlockSize];
SafeNativeMethods.d_qr_factor(rowsR, columnsR, r, tau, q, work, work.Length);
}
@ -634,7 +634,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("work");
}
if (r.Length != rowsR * columnsR)
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r");
}
@ -644,14 +644,14 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
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)
if (work.Length < columnsR*Control.BlockSize)
{
work[0] = columnsR * Control.BlockSize;
work[0] = columnsR*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
@ -683,7 +683,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("q");
}
if (q.Length != rowsA * columnsA)
if (q.Length != rowsA*columnsA)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "q");
}
@ -698,9 +698,8 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "columnsA * columnsA"), "r");
}
var work = new double[columnsA * Control.BlockSize];
var work = new double[columnsA*Control.BlockSize];
SafeNativeMethods.d_qr_thin_factor(rowsA, columnsA, q, tau, r, work, work.Length);
}
@ -776,7 +775,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
[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];
var work = new double[columns*Control.BlockSize];
QRSolve(a, rows, columns, b, columnsB, x, work, method);
}
@ -817,17 +816,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
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");
}
@ -839,7 +838,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
if (work.Length < 1)
{
work[0] = rows * Control.BlockSize;
work[0] = rows*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
@ -863,7 +862,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
[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];
var work = new double[columnsR*Control.BlockSize];
QRSolveFactored(q, r, rowsR, columnsR, tau, b, columnsB, x, work, method);
}
@ -914,7 +913,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
}
int rowsQ, columnsQ, rowsR, columnsR;
if( method == QRMethod.Full)
if (method == QRMethod.Full)
{
rowsQ = columnsQ = rowsR = rowsA;
columnsR = columnsA;
@ -925,29 +924,29 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
columnsQ = rowsR = columnsR = columnsA;
}
if (r.Length != rowsR * columnsR)
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR * columnsR), "r");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR*columnsR), "r");
}
if (q.Length != rowsQ * columnsQ)
if (q.Length != rowsQ*columnsQ)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ * columnsQ), "q");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ*columnsQ), "q");
}
if (b.Length != rowsA * columnsB)
if (b.Length != rowsA*columnsB)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA * columnsB), "b");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA*columnsB), "b");
}
if (x.Length != columnsA * columnsB)
if (x.Length != columnsA*columnsB)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA * columnsB), "x");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA*columnsB), "x");
}
if (work.Length < 1)
{
work[0] = rowsA * Control.BlockSize;
work[0] = rowsA*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
@ -999,12 +998,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("vt");
}
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");
}
@ -1014,7 +1013,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
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))];
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);
}
@ -1044,20 +1043,20 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
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 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);
@ -1109,12 +1108,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
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");
}
@ -1129,9 +1128,9 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentSingleDimensionArray, "work");
}
if (work.Length < Math.Max((3 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA), 5 * Math.Min(rowsA, columnsA)))
if (work.Length < Math.Max((3*Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA), 5*Math.Min(rowsA, columnsA)))
{
work[0] = Math.Max((3 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA), 5 * Math.Min(rowsA, columnsA));
work[0] = Math.Max((3*Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA), 5*Math.Min(rowsA, columnsA));
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
@ -1164,7 +1163,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{
throw new ArgumentException(Resources.ArgumentArraysSameLength);
}
if (x.Length != result.Length)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength);
@ -1199,12 +1198,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{
throw new ArgumentException(Resources.ArgumentArraysSameLength);
}
if (x.Length != result.Length)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength);
}
SafeNativeMethods.d_vector_subtract(x.Length, x, y, result);
}
@ -1234,12 +1233,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{
throw new ArgumentException(Resources.ArgumentArraysSameLength);
}
if (x.Length != result.Length)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength);
}
SafeNativeMethods.d_vector_multiply(x.Length, x, y, result);
}
@ -1269,13 +1268,67 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{
throw new ArgumentException(Resources.ArgumentArraysSameLength);
}
if (x.Length != result.Length)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength);
}
SafeNativeMethods.d_vector_divide(x.Length, x, y, result);
}
/// <summary>
/// Computes the eigenvalues and eigenvectors of a matrix.
/// </summary>
/// <param name="isSymmetric">Wether the matrix is symmetric or not.</param>
/// <param name="order">The order of the matrix.</param>
/// <param name="matrix">The matrix to decompose. The lenth of the array must be order * order.</param>
/// <param name="matrixEv">On output, the matrix contains the eigen vectors. The lenth of the array must be order * order.</param>
/// <param name="vectorEv">On output, the eigen values (λ) of matrix in ascending value. The length of the arry must <paramref name="order"/>.</param>
/// <param name="matrixD">On output, the block diagonal eigenvalue matrix. The lenth of the array must be order * order.</param>
public override void EigenDecomp(bool isSymmetric, int order, double[] matrix, double[] matrixEv, Complex[] vectorEv, double[] matrixD)
{
if (matrix == null)
{
throw new ArgumentNullException("matrix");
}
if (matrix.Length != order*order)
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order*order), "matrix");
}
if (matrixEv == null)
{
throw new ArgumentNullException("matrixEv");
}
if (matrixEv.Length != order*order)
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order*order), "matrixEv");
}
if (vectorEv == null)
{
throw new ArgumentNullException("vectorEv");
}
if (vectorEv.Length != order)
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order), "vectorEv");
}
if (matrixD == null)
{
throw new ArgumentNullException("matrixD");
}
if (matrixD.Length != order*order)
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order*order), "matrixD");
}
SafeNativeMethods.d_eigen(isSymmetric, order, matrix, matrixEv, vectorEv, matrixD);
}
}
}

198
src/Numerics/Algorithms/LinearAlgebra/Mkl/MklLinearAlgebraProvider.float.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2011 Math.NET
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -28,18 +28,14 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
/* This file is automatically generated - do not modify it.
Last generated on UTC 2011-04-17 06:45:23Z
*/
using MathNet.Numerics.LinearAlgebra.Generic.Factorization;
namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{
using System;
using System.Numerics;
using System.Security;
using Numerics.LinearAlgebra.Generic.Factorization;
using Properties;
/// <summary>
/// Intel's Math Kernel Library (MKL) linear algebra provider.
/// </summary>
@ -72,7 +68,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
return SafeNativeMethods.s_dot_product(x.Length, x, y);
}
/// <summary>
/// Adds a scaled vector to another: <c>result = y + alpha*x</c>.
/// </summary>
@ -125,8 +121,8 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
if (x == null)
{
throw new ArgumentNullException("x");
}
}
if (!ReferenceEquals(x, result))
{
Array.Copy(x, 0, result, 0, x.Length);
@ -194,9 +190,9 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
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);
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
if (k != l)
@ -229,7 +225,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("ipiv");
}
if (data.Length != order * order)
if (data.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "data");
}
@ -238,7 +234,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
SafeNativeMethods.s_lu_factor(order, data, ipiv);
}
@ -256,13 +252,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
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);
SafeNativeMethods.s_lu_inverse(order, a, work, work.Length);
}
/// <summary>
@ -285,7 +281,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("ipiv");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
@ -316,7 +312,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("a");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
@ -331,7 +327,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
SafeNativeMethods.s_lu_inverse(order, a, work, work.Length);
SafeNativeMethods.s_lu_inverse(order, a, work, work.Length);
}
/// <summary>
@ -357,7 +353,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("ipiv");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
@ -396,22 +392,22 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
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");
}
if (ReferenceEquals(a, b))
{
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.s_lu_solve(order, columnsOfB, a, b);
SafeNativeMethods.s_lu_solve(order, columnsOfB, a, b);
}
/// <summary>
@ -436,7 +432,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("ipiv");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
@ -446,7 +442,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
}
if (b.Length != columnsOfB * order)
if (b.Length != columnsOfB*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
@ -456,7 +452,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.s_lu_solve_factored(order, columnsOfB, a, ipiv, b);
SafeNativeMethods.s_lu_solve_factored(order, columnsOfB, a, ipiv, b);
}
/// <summary>
@ -479,7 +475,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentMustBePositive, "order");
}
if (a.Length != order * order)
if (a.Length != order*order)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
}
@ -514,7 +510,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("b");
}
if (b.Length != orderA * columnsB)
if (b.Length != orderA*columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
@ -524,7 +520,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.s_cholesky_solve(orderA, columnsB, a, b);
SafeNativeMethods.s_cholesky_solve(orderA, columnsB, a, b);
}
/// <summary>
@ -548,7 +544,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("b");
}
if (b.Length != orderA * columnsB)
if (b.Length != orderA*columnsB)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
}
@ -558,7 +554,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent);
}
SafeNativeMethods.s_cholesky_solve_factored(orderA, columnsB, a, b);
SafeNativeMethods.s_cholesky_solve_factored(orderA, columnsB, a, b);
}
/// <summary>
@ -586,7 +582,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("q");
}
if (r.Length != rowsR * columnsR)
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r");
}
@ -596,12 +592,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
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");
}
var work = new float[columnsR * Control.BlockSize];
var work = new float[columnsR*Control.BlockSize];
SafeNativeMethods.s_qr_factor(rowsR, columnsR, r, tau, q, work, work.Length);
}
@ -638,7 +634,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("work");
}
if (r.Length != rowsR * columnsR)
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "r");
}
@ -648,14 +644,14 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
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)
if (work.Length < columnsR*Control.BlockSize)
{
work[0] = columnsR * Control.BlockSize;
work[0] = columnsR*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
@ -676,7 +672,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
[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];
var work = new float[columns*Control.BlockSize];
QRSolve(a, rows, columns, b, columnsB, x, work, method);
}
@ -717,17 +713,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
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");
}
@ -739,7 +735,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
if (work.Length < 1)
{
work[0] = rows * Control.BlockSize;
work[0] = rows*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
@ -763,7 +759,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
[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];
var work = new float[columnsR*Control.BlockSize];
QRSolveFactored(q, r, rowsR, columnsR, tau, b, columnsB, x, work, method);
}
@ -825,29 +821,29 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
columnsQ = rowsR = columnsR = columnsA;
}
if (r.Length != rowsR * columnsR)
if (r.Length != rowsR*columnsR)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR * columnsR), "r");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsR*columnsR), "r");
}
if (q.Length != rowsQ * columnsQ)
if (q.Length != rowsQ*columnsQ)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ * columnsQ), "q");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsQ*columnsQ), "q");
}
if (b.Length != rowsA * columnsB)
if (b.Length != rowsA*columnsB)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA * columnsB), "b");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, rowsA*columnsB), "b");
}
if (x.Length != columnsA * columnsB)
if (x.Length != columnsA*columnsB)
{
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA * columnsB), "x");
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, columnsA*columnsB), "x");
}
if (work.Length < 1)
{
work[0] = rowsA * Control.BlockSize;
work[0] = rowsA*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
@ -899,12 +895,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("vt");
}
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");
}
@ -914,7 +910,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
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))];
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);
}
@ -944,20 +940,20 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
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 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);
@ -1009,12 +1005,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
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");
}
@ -1029,9 +1025,9 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentSingleDimensionArray, "work");
}
if (work.Length < Math.Max(((3 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA)), 5 * Math.Min(rowsA, columnsA)))
if (work.Length < Math.Max(((3*Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA)), 5*Math.Min(rowsA, columnsA)))
{
work[0] = Math.Max(((3 * Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA)), 5 * Math.Min(rowsA, columnsA));
work[0] = Math.Max(((3*Math.Min(rowsA, columnsA)) + Math.Max(rowsA, columnsA)), 5*Math.Min(rowsA, columnsA));
throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
}
@ -1064,7 +1060,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{
throw new ArgumentException(Resources.ArgumentArraysSameLength);
}
if (x.Length != result.Length)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength);
@ -1099,12 +1095,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{
throw new ArgumentException(Resources.ArgumentArraysSameLength);
}
if (x.Length != result.Length)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength);
}
SafeNativeMethods.s_vector_subtract(x.Length, x, y, result);
}
@ -1134,12 +1130,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{
throw new ArgumentException(Resources.ArgumentArraysSameLength);
}
if (x.Length != result.Length)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength);
}
SafeNativeMethods.s_vector_multiply(x.Length, x, y, result);
}
@ -1169,13 +1165,67 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{
throw new ArgumentException(Resources.ArgumentArraysSameLength);
}
if (x.Length != result.Length)
{
throw new ArgumentException(Resources.ArgumentArraysSameLength);
}
SafeNativeMethods.s_vector_divide(x.Length, x, y, result);
}
/// <summary>
/// Computes the eigenvalues and eigenvectors of a matrix.
/// </summary>
/// <param name="isSymmetric">Wether the matrix is symmetric or not.</param>
/// <param name="order">The order of the matrix.</param>
/// <param name="matrix">The matrix to decompose. The lenth of the array must be order * order.</param>
/// <param name="matrixEv">On output, the matrix contains the eigen vectors. The lenth of the array must be order * order.</param>
/// <param name="vectorEv">On output, the eigen values (λ) of matrix in ascending value. The length of the arry must <paramref name="order"/>.</param>
/// <param name="matrixD">On output, the block diagonal eigenvalue matrix. The lenth of the array must be order * order.</param>
public override void EigenDecomp(bool isSymmetric, int order, float[] matrix, float[] matrixEv, Complex[] vectorEv, float[] matrixD)
{
if (matrix == null)
{
throw new ArgumentNullException("matrix");
}
if (matrix.Length != order*order)
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order*order), "matrix");
}
if (matrixEv == null)
{
throw new ArgumentNullException("matrixEv");
}
if (matrixEv.Length != order*order)
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order*order), "matrixEv");
}
if (vectorEv == null)
{
throw new ArgumentNullException("vectorEv");
}
if (vectorEv.Length != order)
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order), "vectorEv");
}
if (matrixD == null)
{
throw new ArgumentNullException("matrixD");
}
if (matrixD.Length != order*order)
{
throw new ArgumentException(String.Format(Resources.ArgumentArrayWrongLength, order*order), "matrixD");
}
SafeNativeMethods.s_eigen(isSymmetric, order, matrix, matrixEv, vectorEv, matrixD);
}
}
}

14
src/Numerics/Algorithms/LinearAlgebra/Mkl/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-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -266,6 +266,18 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
[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);
[DllImport(DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int s_eigen(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] 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] 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] Complex[] a, [In, Out] Complex[] vectors, [In, Out] Complex[] values, [In, Out] Complex[] d);
#endregion LAPACK
#region Vector Functions

385
src/Numerics/LinearAlgebra/Complex/Factorization/DenseEvd.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2010 Math.NET
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -27,13 +27,13 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
{
using System;
using System.Numerics;
using Generic;
using Properties;
/// <summary>
/// Eigenvalues and eigenvectors of a complex matrix.
/// </summary>
@ -72,45 +72,23 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
var order = matrix.RowCount;
// Initialize matricies for eigenvalues and eigenvectors
// Initialize matrices for eigenvalues and eigenvectors
MatrixEv = DenseMatrix.Identity(order);
MatrixD = matrix.CreateMatrix(order, order);
VectorEv = new DenseVector(order);
IsSymmetric = true;
for (var i = 0; i < order & IsSymmetric; i++)
for (var i = 0; IsSymmetric && i < order; i++)
{
for (var j = 0; j < order & IsSymmetric; j++)
for (var j = 0; IsSymmetric && j < order; j++)
{
IsSymmetric &= matrix.At(i, j) == matrix.At(j, i).Conjugate();
}
}
if (IsSymmetric)
{
var matrixCopy = matrix.ToArray();
var tau = new Complex[order];
var d = new double[order];
var e = new double[order];
SymmetricTridiagonalize(matrixCopy, d, e, tau, order);
SymmetricDiagonalize(((DenseMatrix)MatrixEv).Values, d, e, order);
SymmetricUntridiagonalize(((DenseMatrix)MatrixEv).Values, matrixCopy, tau, order);
for (var i = 0; i < order; i++)
{
VectorEv[i] = new Complex(d[i], e[i]);
}
}
else
{
var matrixH = matrix.ToArray();
NonsymmetricReduceToHessenberg(((DenseMatrix)MatrixEv).Values, matrixH, order);
NonsymmetricReduceHessenberToRealSchur(((DenseVector)VectorEv).Values, ((DenseMatrix)MatrixEv).Values, matrixH, order);
}
MatrixD.SetDiagonal(VectorEv);
Control.LinearAlgebraProvider.EigenDecomp(IsSymmetric, order, matrix.Values, ((DenseMatrix) MatrixEv).Values,
((DenseVector) VectorEv).Values, ((DenseMatrix) MatrixD).Values);
}
/// <summary>
@ -125,14 +103,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// Smith, Boyle, Dongarra, Garbow, Ikebe, Klema, Moler, and Wilkinson, Handbook for
/// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
/// Fortran subroutine in EISPACK.</remarks>
private static void SymmetricTridiagonalize(Complex[,] matrixA, double[] d, double[] e, Complex[] tau, int order)
internal static void SymmetricTridiagonalize(System.Numerics.Complex[] matrixA, double[] d, double[] e, System.Numerics.Complex[] tau, int order)
{
double hh;
tau[order - 1] = Complex.One;
tau[order - 1] = System.Numerics.Complex.One;
for (var i = 0; i < order; i++)
{
d[i] = matrixA[i, i].Real;
d[i] = matrixA[i*order + i].Real;
}
// Householder reduction to tridiagonal form.
@ -144,95 +122,96 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
for (var k = 0; k < i; k++)
{
scale = scale + Math.Abs(matrixA[i, k].Real) + Math.Abs(matrixA[i, k].Imaginary);
scale = scale + Math.Abs(matrixA[k*order + i].Real) + Math.Abs(matrixA[k*order + i].Imaginary);
}
if (scale == 0.0)
{
tau[i - 1] = Complex.One;
tau[i - 1] = System.Numerics.Complex.One;
e[i] = 0.0;
}
else
{
for (var k = 0; k < i; k++)
{
matrixA[i, k] /= scale;
h += matrixA[i, k].MagnitudeSquared();
matrixA[k*order + i] /= scale;
h += matrixA[k*order + i].MagnitudeSquared();
}
Complex g = Math.Sqrt(h);
e[i] = scale * g.Real;
System.Numerics.Complex g = Math.Sqrt(h);
e[i] = scale*g.Real;
Complex temp;
var f = matrixA[i, i - 1];
System.Numerics.Complex temp;
var im1Oi = (i - 1)*order + i;
var f = matrixA[im1Oi];
if (f.Magnitude != 0)
{
temp = -(matrixA[i, i - 1].Conjugate() * tau[i].Conjugate()) / f.Magnitude;
h += f.Magnitude * g.Real;
g = 1.0 + (g / f.Magnitude);
matrixA[i, i - 1] *= g;
temp = -(matrixA[im1Oi].Conjugate()*tau[i].Conjugate())/f.Magnitude;
h += f.Magnitude*g.Real;
g = 1.0 + (g/f.Magnitude);
matrixA[im1Oi] *= g;
}
else
{
temp = -tau[i].Conjugate();
matrixA[i, i - 1] = g;
matrixA[im1Oi] = g;
}
if ((f.Magnitude == 0) || (i != 1))
{
f = Complex.Zero;
f = System.Numerics.Complex.Zero;
for (var j = 0; j < i; j++)
{
var tmp = Complex.Zero;
var tmp = System.Numerics.Complex.Zero;
var jO = j*order;
// Form element of A*U.
for (var k = 0; k <= j; k++)
{
tmp += matrixA[j, k] * matrixA[i, k].Conjugate();
tmp += matrixA[k*order + j]*matrixA[k*order + i].Conjugate();
}
for (var k = j + 1; k <= i - 1; k++)
{
tmp += matrixA[k, j].Conjugate() * matrixA[i, k].Conjugate();
tmp += matrixA[jO + k].Conjugate()*matrixA[k*order + i].Conjugate();
}
// Form element of P
tau[j] = tmp / h;
f += (tmp / h) * matrixA[i, j];
tau[j] = tmp/h;
f += (tmp/h)*matrixA[jO + i];
}
hh = f.Real / (h + h);
hh = f.Real/(h + h);
// Form the reduced A.
for (var j = 0; j < i; j++)
{
f = matrixA[i, j].Conjugate();
g = tau[j] - (hh * f);
f = matrixA[j*order + i].Conjugate();
g = tau[j] - (hh*f);
tau[j] = g.Conjugate();
for (var k = 0; k <= j; k++)
{
matrixA[j, k] -= (f * tau[k]) + (g * matrixA[i, k]);
matrixA[k*order + j] -= (f*tau[k]) + (g*matrixA[k*order + i]);
}
}
}
for (var k = 0; k < i; k++)
{
matrixA[i, k] *= scale;
matrixA[k*order + i] *= scale;
}
tau[i - 1] = temp.Conjugate();
}
hh = d[i];
d[i] = matrixA[i, i].Real;
matrixA[i, i] = new Complex(hh, scale * Math.Sqrt(h));
d[i] = matrixA[i*order + i].Real;
matrixA[i*order + i] = new System.Numerics.Complex(hh, scale*Math.Sqrt(h));
}
hh = d[0];
d[0] = matrixA[0, 0].Real;
matrixA[0, 0] = hh;
d[0] = matrixA[0].Real;
matrixA[0] = hh;
e[0] = 0.0;
}
@ -247,7 +226,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
/// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
/// Fortran subroutine in EISPACK.</remarks>
private static void SymmetricDiagonalize(Complex[] dataEv, double[] d, double[] e, int order)
internal static void SymmetricDiagonalize(System.Numerics.Complex[] dataEv, double[] d, double[] e, int order)
{
const int Maxiter = 1000;
@ -268,7 +247,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
var m = l;
while (m < order)
{
if (Math.Abs(e[m]) <= eps * tst1)
if (Math.Abs(e[m]) <= eps*tst1)
{
break;
}
@ -287,15 +266,15 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
// Compute implicit shift
var g = d[l];
var p = (d[l + 1] - g) / (2.0 * e[l]);
var p = (d[l + 1] - g)/(2.0*e[l]);
var r = SpecialFunctions.Hypotenuse(p, 1.0);
if (p < 0)
{
r = -r;
}
d[l] = e[l] / (p + r);
d[l + 1] = e[l] * (p + r);
d[l] = e[l]/(p + r);
d[l + 1] = e[l]*(p + r);
var dl1 = d[l + 1];
var h = g - d[l];
@ -319,27 +298,27 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
c3 = c2;
c2 = c;
s2 = s;
g = c * e[i];
h = c * p;
g = c*e[i];
h = c*p;
r = SpecialFunctions.Hypotenuse(p, e[i]);
e[i + 1] = s * r;
s = e[i] / r;
c = p / r;
p = (c * d[i]) - (s * g);
d[i + 1] = h + (s * ((c * g) + (s * d[i])));
e[i + 1] = s*r;
s = e[i]/r;
c = p/r;
p = (c*d[i]) - (s*g);
d[i + 1] = h + (s*((c*g) + (s*d[i])));
// Accumulate transformation.
for (var k = 0; k < order; k++)
{
h = dataEv[((i + 1) * order) + k].Real;
dataEv[((i + 1) * order) + k] = (s * dataEv[(i * order) + k].Real) + (c * h);
dataEv[(i * order) + k] = (c * dataEv[(i * order) + k].Real) - (s * h);
h = dataEv[((i + 1)*order) + k].Real;
dataEv[((i + 1)*order) + k] = (s*dataEv[(i*order) + k].Real) + (c*h);
dataEv[(i*order) + k] = (c*dataEv[(i*order) + k].Real) - (s*h);
}
}
p = (-s) * s2 * c3 * el1 * e[l] / dl1;
e[l] = s * p;
d[l] = c * p;
p = (-s)*s2*c3*el1*e[l]/dl1;
e[l] = s*p;
d[l] = c*p;
// Check for convergence. If too many iterations have been performed,
// throw exception that Convergence Failed
@ -347,8 +326,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
{
throw new ArgumentException(Resources.ConvergenceFailed);
}
}
while (Math.Abs(e[l]) > eps * tst1);
} while (Math.Abs(e[l]) > eps*tst1);
}
d[l] = d[l] + f;
@ -375,9 +353,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
d[i] = p;
for (var j = 0; j < order; j++)
{
p = dataEv[(i * order) + j].Real;
dataEv[(i * order) + j] = dataEv[(k * order) + j];
dataEv[(k * order) + j] = p;
p = dataEv[(i*order) + j].Real;
dataEv[(i*order) + j] = dataEv[(k*order) + j];
dataEv[(k*order) + j] = p;
}
}
}
@ -394,35 +372,35 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// by Smith, Boyle, Dongarra, Garbow, Ikebe, Klema, Moler, and Wilkinson, Handbook for
/// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
/// Fortran subroutine in EISPACK.</remarks>
private static void SymmetricUntridiagonalize(Complex[] dataEv, Complex[,] matrixA, Complex[] tau, int order)
internal static void SymmetricUntridiagonalize(System.Numerics.Complex[] dataEv, System.Numerics.Complex[] matrixA, System.Numerics.Complex[] tau, int order)
{
for (var i = 0; i < order; i++)
{
for (var j = 0; j < order; j++)
{
dataEv[(j * order) + i] = dataEv[(j * order) + i].Real * tau[i].Conjugate();
dataEv[(j*order) + i] = dataEv[(j*order) + i].Real*tau[i].Conjugate();
}
}
// Recover and apply the Householder matrices.
for (var i = 1; i < order; i++)
{
var h = matrixA[i, i].Imaginary;
var h = matrixA[i*order + i].Imaginary;
if (h != 0)
{
for (var j = 0; j < order; j++)
{
var s = Complex.Zero;
var s = System.Numerics.Complex.Zero;
for (var k = 0; k < i; k++)
{
s += dataEv[(j * order) + k] * matrixA[i, k];
s += dataEv[(j*order) + k]*matrixA[k*order + i];
}
s = (s / h) / h;
s = (s/h)/h;
for (var k = 0; k < i; k++)
{
dataEv[(j * order) + k] -= s * matrixA[i, k].Conjugate();
dataEv[(j*order) + k] -= s*matrixA[k*order + i].Conjugate();
}
}
}
@ -439,17 +417,18 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// by Martin and Wilkinson, Handbook for Auto. Comp.,
/// Vol.ii-Linear Algebra, and the corresponding
/// Fortran subroutines in EISPACK.</remarks>
private static void NonsymmetricReduceToHessenberg(Complex[] dataEv, Complex[,] matrixH, int order)
internal static void NonsymmetricReduceToHessenberg(System.Numerics.Complex[] dataEv, System.Numerics.Complex[] matrixH, int order)
{
var ort = new Complex[order];
var ort = new System.Numerics.Complex[order];
for (var m = 1; m < order - 1; m++)
{
// Scale column.
var scale = 0.0;
var mm1O = (m - 1)*order;
for (var i = m; i < order; i++)
{
scale += Math.Abs(matrixH[i, m - 1].Real) + Math.Abs(matrixH[i, m - 1].Imaginary);
scale += Math.Abs(matrixH[mm1O + i].Real) + Math.Abs(matrixH[mm1O + i].Imaginary);
}
if (scale != 0.0)
@ -458,57 +437,58 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
var h = 0.0;
for (var i = order - 1; i >= m; i--)
{
ort[i] = matrixH[i, m - 1] / scale;
ort[i] = matrixH[mm1O + i]/scale;
h += ort[i].MagnitudeSquared();
}
var g = Math.Sqrt(h);
if (ort[m].Magnitude != 0)
{
h = h + (ort[m].Magnitude * g);
h = h + (ort[m].Magnitude*g);
g /= ort[m].Magnitude;
ort[m] = (1.0 + g) * ort[m];
ort[m] = (1.0 + g)*ort[m];
}
else
{
ort[m] = g;
matrixH[m, m - 1] = scale;
matrixH[mm1O + m] = scale;
}
// Apply Householder similarity transformation
// H = (I-u*u'/h)*H*(I-u*u')/h)
for (var j = m; j < order; j++)
{
var f = Complex.Zero;
var f = System.Numerics.Complex.Zero;
var jO = j*order;
for (var i = order - 1; i >= m; i--)
{
f += ort[i].Conjugate() * matrixH[i, j];
f += ort[i].Conjugate()*matrixH[jO + i];
}
f = f / h;
f = f/h;
for (var i = m; i < order; i++)
{
matrixH[i, j] -= f * ort[i];
matrixH[jO + i] -= f*ort[i];
}
}
for (var i = 0; i < order; i++)
{
var f = Complex.Zero;
var f = System.Numerics.Complex.Zero;
for (var j = order - 1; j >= m; j--)
{
f += ort[j] * matrixH[i, j];
f += ort[j]*matrixH[j*order + i];
}
f = f / h;
f = f/h;
for (var j = m; j < order; j++)
{
matrixH[i, j] -= f * ort[j].Conjugate();
matrixH[j*order + i] -= f*ort[j].Conjugate();
}
}
ort[m] = scale * ort[m];
matrixH[m, m - 1] *= -g;
ort[m] = scale*ort[m];
matrixH[mm1O + m] *= -g;
}
}
@ -517,59 +497,65 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
{
for (var j = 0; j < order; j++)
{
dataEv[(j * order) + i] = i == j ? Complex.One : Complex.Zero;
dataEv[(j*order) + i] = i == j ? System.Numerics.Complex.One : System.Numerics.Complex.Zero;
}
}
for (var m = order - 2; m >= 1; m--)
{
if (matrixH[m, m - 1] != Complex.Zero && ort[m] != Complex.Zero)
var mm1O = (m - 1)*order;
var mm1Om = mm1O + m;
if (matrixH[mm1Om] != System.Numerics.Complex.Zero && ort[m] != System.Numerics.Complex.Zero)
{
var norm = (matrixH[m, m - 1].Real * ort[m].Real) + (matrixH[m, m - 1].Imaginary * ort[m].Imaginary);
var norm = (matrixH[mm1Om].Real*ort[m].Real) + (matrixH[mm1Om].Imaginary*ort[m].Imaginary);
for (var i = m + 1; i < order; i++)
{
ort[i] = matrixH[i, m - 1];
ort[i] = matrixH[mm1O + i];
}
for (var j = m; j < order; j++)
{
var g = Complex.Zero;
var g = System.Numerics.Complex.Zero;
for (var i = m; i < order; i++)
{
g += ort[i].Conjugate() * dataEv[(j * order) + i];
g += ort[i].Conjugate()*dataEv[(j*order) + i];
}
// Double division avoids possible underflow
g /= norm;
for (var i = m; i < order; i++)
{
dataEv[(j * order) + i] += g * ort[i];
dataEv[(j*order) + i] += g*ort[i];
}
}
}
}
// Create real subdiagonal elements.
for (var i = 1; i < order; i++)
{
if (matrixH[i, i - 1].Imaginary != 0.0)
var im1 = i - 1;
var im1O = im1*order;
var im1Oi = im1O + i;
var iO = i*order;
if (matrixH[im1Oi].Imaginary != 0.0)
{
var y = matrixH[i, i - 1] / matrixH[i, i - 1].Magnitude;
matrixH[i, i - 1] = matrixH[i, i - 1].Magnitude;
var y = matrixH[im1Oi]/matrixH[im1Oi].Magnitude;
matrixH[im1Oi] = matrixH[im1Oi].Magnitude;
for (var j = i; j < order; j++)
{
matrixH[i, j] *= y.Conjugate();
matrixH[j*order + i] *= y.Conjugate();
}
for (var j = 0; j <= Math.Min(i + 1, order - 1); j++)
{
matrixH[j, i] *= y;
matrixH[iO + j] *= y;
}
for (var j = 0; j < order; j++)
{
dataEv[(i * order) + j] *= y;
dataEv[(i*order) + j] *= y;
}
}
}
@ -586,14 +572,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// by Martin and Wilkinson, Handbook for Auto. Comp.,
/// Vol.ii-Linear Algebra, and the corresponding
/// Fortran subroutine in EISPACK.</remarks>
private static void NonsymmetricReduceHessenberToRealSchur(Complex[] vectorV, Complex[] dataEv, Complex[,] matrixH, int order)
internal static void NonsymmetricReduceHessenberToRealSchur(System.Numerics.Complex[] vectorV, System.Numerics.Complex[] dataEv, System.Numerics.Complex[] matrixH, int order)
{
// Initialize
var n = order - 1;
var eps = Precision.DoubleMachinePrecision;
double norm;
Complex x, y, z, exshift = Complex.Zero;
System.Numerics.Complex x, y, z, exshift = System.Numerics.Complex.Zero;
// Outer loop over eigenvalue index
var iter = 0;
@ -603,8 +589,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
var l = n;
while (l > 0)
{
var tst1 = Math.Abs(matrixH[l - 1, l - 1].Real) + Math.Abs(matrixH[l - 1, l - 1].Imaginary) + Math.Abs(matrixH[l, l].Real) + Math.Abs(matrixH[l, l].Imaginary);
if (Math.Abs(matrixH[l, l - 1].Real) < eps * tst1)
var lm1 = l - 1;
var lm1O = lm1*order;
var lO = l*order;
var tst1 = Math.Abs(matrixH[lm1O + lm1].Real) + Math.Abs(matrixH[lm1O + lm1].Imaginary) + Math.Abs(matrixH[lO + l].Real) + Math.Abs(matrixH[lO + l].Imaginary);
if (Math.Abs(matrixH[lm1O + l].Real) < eps*tst1)
{
break;
}
@ -612,46 +601,50 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
l--;
}
var nm1 = n - 1;
var nm1O = nm1*order;
var nO = n*order;
var nOn = nO + n;
// Check for convergence
// One root found
if (l == n)
{
matrixH[n, n] += exshift;
vectorV[n] = matrixH[n, n];
matrixH[nOn] += exshift;
vectorV[n] = matrixH[nOn];
n--;
iter = 0;
}
else
{
// Form shift
Complex s;
System.Numerics.Complex s;
if (iter != 10 && iter != 20)
{
s = matrixH[n, n];
x = matrixH[n - 1, n] * matrixH[n, n - 1].Real;
s = matrixH[nOn];
x = matrixH[nO + nm1]*matrixH[nm1O + n].Real;
if (x.Real != 0.0 || x.Imaginary != 0.0)
{
y = (matrixH[n - 1, n - 1] - s) / 2.0;
z = ((y * y) + x).SquareRoot();
if ((y.Real * z.Real) + (y.Imaginary * z.Imaginary) < 0.0)
y = (matrixH[nm1O + nm1] - s)/2.0;
z = ((y*y) + x).SquareRoot();
if ((y.Real*z.Real) + (y.Imaginary*z.Imaginary) < 0.0)
{
z *= -1.0;
}
x /= y + z;
x /= y + z;
s = s - x;
}
}
else
{
// Form exceptional shift
s = Math.Abs(matrixH[n, n - 1].Real) + Math.Abs(matrixH[n - 1, n - 2].Real);
s = Math.Abs(matrixH[nm1O + n].Real) + Math.Abs(matrixH[(n - 2)*order + nm1].Real);
}
for (var i = 0; i <= n; i++)
{
matrixH[i, i] -= s;
matrixH[i*order + i] -= s;
}
exshift += s;
@ -660,31 +653,35 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
// Reduce to triangle (rows)
for (var i = l + 1; i <= n; i++)
{
s = matrixH[i, i - 1].Real;
norm = SpecialFunctions.Hypotenuse(matrixH[i - 1, i - 1].Magnitude, s.Real);
x = matrixH[i - 1, i - 1] / norm;
var im1 = i - 1;
var im1O = im1*order;
var im1Oim1 = im1O + im1;
s = matrixH[im1O + i].Real;
norm = SpecialFunctions.Hypotenuse(matrixH[im1Oim1].Magnitude, s.Real);
x = matrixH[im1Oim1]/norm;
vectorV[i - 1] = x;
matrixH[i - 1, i - 1] = norm;
matrixH[i, i - 1] = new Complex(0.0, s.Real / norm);
matrixH[im1Oim1] = norm;
matrixH[im1O + i] = new System.Numerics.Complex(0.0, s.Real/norm);
for (var j = i; j < order; j++)
{
y = matrixH[i - 1, j];
z = matrixH[i, j];
matrixH[i - 1, j] = (x.Conjugate() * y) + (matrixH[i, i - 1].Imaginary * z);
matrixH[i, j] = (x * z) - (matrixH[i, i - 1].Imaginary * y);
var jO = j*order;
y = matrixH[jO + im1];
z = matrixH[jO + i];
matrixH[jO + im1] = (x.Conjugate()*y) + (matrixH[im1O + i].Imaginary*z);
matrixH[jO + i] = (x*z) - (matrixH[im1O + i].Imaginary*y);
}
}
s = matrixH[n, n];
s = matrixH[nOn];
if (s.Imaginary != 0.0)
{
s /= matrixH[n, n].Magnitude;
matrixH[n, n] = matrixH[n, n].Magnitude;
s /= matrixH[nOn].Magnitude;
matrixH[nOn] = matrixH[nOn].Magnitude;
for (var j = n + 1; j < order; j++)
{
matrixH[n, j] *= s.Conjugate();
matrixH[j*order + n] *= s.Conjugate();
}
}
@ -692,29 +689,34 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
for (var j = l + 1; j <= n; j++)
{
x = vectorV[j - 1];
var jO = j*order;
var jm1 = j - 1;
var jm1O = jm1*order;
var jm1Oj = jm1O + j;
for (var i = 0; i <= j; i++)
{
z = matrixH[i, j];
var jm1Oi = jm1O + i;
z = matrixH[jO + i];
if (i != j)
{
y = matrixH[i, j - 1];
matrixH[i, j - 1] = (x * y) + (matrixH[j, j - 1].Imaginary * z);
y = matrixH[jm1Oi];
matrixH[jm1Oi] = (x*y) + (matrixH[jm1O + j].Imaginary*z);
}
else
{
y = matrixH[i, j - 1].Real;
matrixH[i, j - 1] = new Complex((x.Real * y.Real) - (x.Imaginary * y.Imaginary) + (matrixH[j, j - 1].Imaginary * z.Real), matrixH[i, j - 1].Imaginary);
y = matrixH[jm1Oi].Real;
matrixH[jm1Oi] = new System.Numerics.Complex((x.Real*y.Real) - (x.Imaginary*y.Imaginary) + (matrixH[jm1O + j].Imaginary*z.Real), matrixH[jm1Oi].Imaginary);
}
matrixH[i, j] = (x.Conjugate() * z) - (matrixH[j, j - 1].Imaginary * y);
matrixH[jO + i] = (x.Conjugate()*z) - (matrixH[jm1O + j].Imaginary*y);
}
for (var i = 0; i < order; i++)
{
y = dataEv[((j - 1) * order) + i];
z = dataEv[(j * order) + i];
dataEv[((j - 1) * order) + i] = (x * y) + (matrixH[j, j - 1].Imaginary * z);
dataEv[(j * order) + i] = (x.Conjugate() * z) - (matrixH[j, j - 1].Imaginary * y);
y = dataEv[((j - 1)*order) + i];
z = dataEv[(j*order) + i];
dataEv[jm1O + i] = (x*y) + (matrixH[jm1Oj].Imaginary*z);
dataEv[jO + i] = (x.Conjugate()*z) - (matrixH[jm1Oj].Imaginary*y);
}
}
@ -722,12 +724,12 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
{
for (var i = 0; i <= n; i++)
{
matrixH[i, n] *= s;
matrixH[nO + i] *= s;
}
for (var i = 0; i < order; i++)
{
dataEv[(n * order) + i] *= s;
dataEv[nO + i] *= s;
}
}
}
@ -740,7 +742,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
{
for (var j = i; j < order; j++)
{
norm = Math.Max(norm, Math.Abs(matrixH[i, j].Real) + Math.Abs(matrixH[i, j].Imaginary));
norm = Math.Max(norm, Math.Abs(matrixH[j*order + i].Real) + Math.Abs(matrixH[j*order + i].Imaginary));
}
}
@ -756,32 +758,34 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
for (n = order - 1; n > 0; n--)
{
var nO = n*order;
var nOn = nO + n;
x = vectorV[n];
matrixH[n, n] = 1.0;
matrixH[nOn] = 1.0;
for (var i = n - 1; i >= 0; i--)
{
z = 0.0;
for (var j = i + 1; j <= n; j++)
{
z += matrixH[i, j] * matrixH[j, n];
z += matrixH[j*order + i]*matrixH[nO + j];
}
y = x - vectorV[i];
if (y.Real == 0.0 && y.Imaginary == 0.0)
{
y = eps * norm;
y = eps*norm;
}
matrixH[i, n] = z / y;
matrixH[nO + i] = z/y;
// Overflow control
var tr = Math.Abs(matrixH[i, n].Real) + Math.Abs(matrixH[i, n].Imaginary);
if ((eps * tr) * tr > 1)
var tr = Math.Abs(matrixH[nO + i].Real) + Math.Abs(matrixH[nO + i].Imaginary);
if ((eps*tr)*tr > 1)
{
for (var j = i; j <= n; j++)
{
matrixH[j, n] = matrixH[j, n] / tr;
matrixH[nO + j] = matrixH[nO + j]/tr;
}
}
}
@ -790,25 +794,26 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
// Back transformation to get eigenvectors of original matrix
for (var j = order - 1; j > 0; j--)
{
var jO = j*order;
for (var i = 0; i < order; i++)
{
z = Complex.Zero;
z = System.Numerics.Complex.Zero;
for (var k = 0; k <= j; k++)
{
z += dataEv[(k * order) + i] * matrixH[k, j];
z += dataEv[(k*order) + i]*matrixH[jO + k];
}
dataEv[(j * order) + i] = z;
dataEv[jO + i] = z;
}
}
}
/// <summary>
/// Solves a system of linear equations, <b>AX = B</b>, with A SVD factorized.
/// </summary>
/// <param name="input">The right hand side <see cref="Matrix{T}"/>, <b>B</b>.</param>
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param>
public override void Solve(Matrix<Complex> input, Matrix<Complex> result)
public override void Solve(Matrix<System.Numerics.Complex> input, Matrix<System.Numerics.Complex> result)
{
// Check for proper arguments.
if (input == null)
@ -842,18 +847,18 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
if (IsSymmetric)
{
var order = VectorEv.Count;
var tmp = new Complex[order];
var tmp = new System.Numerics.Complex[order];
for (var k = 0; k < order; k++)
{
for (var j = 0; j < order; j++)
{
Complex value = 0.0;
System.Numerics.Complex value = 0.0;
if (j < order)
{
for (var i = 0; i < order; i++)
{
value += ((DenseMatrix)MatrixEv).Values[(j * order) + i].Conjugate() * input.At(i, k);
value += ((DenseMatrix) MatrixEv).Values[(j*order) + i].Conjugate()*input.At(i, k);
}
value /= VectorEv[j].Real;
@ -864,10 +869,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
for (var j = 0; j < order; j++)
{
Complex value = 0.0;
System.Numerics.Complex value = 0.0;
for (var i = 0; i < order; i++)
{
value += ((DenseMatrix)MatrixEv).Values[(i * order) + j] * tmp[i];
value += ((DenseMatrix) MatrixEv).Values[(i*order) + j]*tmp[i];
}
result.At(j, k, value);
@ -876,7 +881,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
}
else
{
throw new ArgumentException(Resources.ArgumentMatrixSymmetric);
throw new ArgumentException(Resources.ArgumentMatrixSymmetric);
}
}
@ -885,7 +890,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// </summary>
/// <param name="input">The right hand side vector, <b>b</b>.</param>
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param>
public override void Solve(Vector<Complex> input, Vector<Complex> result)
public override void Solve(Vector<System.Numerics.Complex> input, Vector<System.Numerics.Complex> result)
{
if (input == null)
{
@ -914,8 +919,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
{
// Symmetric case -> x = V * inv(λ) * VH * b;
var order = VectorEv.Count;
var tmp = new Complex[order];
Complex value;
var tmp = new System.Numerics.Complex[order];
System.Numerics.Complex value;
for (var j = 0; j < order; j++)
{
@ -924,7 +929,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
{
for (var i = 0; i < order; i++)
{
value += ((DenseMatrix)MatrixEv).Values[(j * order) + i].Conjugate() * input[i];
value += ((DenseMatrix) MatrixEv).Values[(j*order) + i].Conjugate()*input[i];
}
value /= VectorEv[j].Real;
@ -936,9 +941,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
for (var j = 0; j < order; j++)
{
value = 0;
for (int i = 0; i < order; i++)
for (var i = 0; i < order; i++)
{
value += ((DenseMatrix)MatrixEv).Values[(i * order) + j] * tmp[i];
value += ((DenseMatrix) MatrixEv).Values[(i*order) + j]*tmp[i];
}
result[j] = value;
@ -950,4 +955,4 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
}
}
}
}
}

4
src/Numerics/LinearAlgebra/Complex/Factorization/UserEvd.cs

@ -79,9 +79,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
IsSymmetric = true;
for (var i = 0; i < order & IsSymmetric; i++)
for (var i = 0; IsSymmetric && i < order; i++)
{
for (var j = 0; j < order & IsSymmetric; j++)
for (var j = 0; IsSymmetric && j < order; j++)
{
IsSymmetric &= matrix.At(i, j) == matrix.At(j, i).Conjugate();
}

412
src/Numerics/LinearAlgebra/Complex32/Factorization/DenseEvd.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2010 Math.NET
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -27,12 +27,12 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
{
using System;
using System.Numerics;
using Generic;
using Numerics;
using Properties;
/// <summary>
@ -73,48 +73,23 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
var order = matrix.RowCount;
// Initialize matricies for eigenvalues and eigenvectors
// Initialize matrices for eigenvalues and eigenvectors
MatrixEv = DenseMatrix.Identity(order);
MatrixD = matrix.CreateMatrix(order, order);
VectorEv = new LinearAlgebra.Complex.DenseVector(order);
VectorEv = new Complex.DenseVector(order);
IsSymmetric = true;
for (var i = 0; i < order & IsSymmetric; i++)
for (var i = 0; IsSymmetric && i < order; i++)
{
for (var j = 0; j < order & IsSymmetric; j++)
for (var j = 0; IsSymmetric && j < order; j++)
{
IsSymmetric &= matrix.At(i, j) == matrix.At(j, i).Conjugate();
}
}
if (IsSymmetric)
{
var matrixCopy = matrix.ToArray();
var tau = new Complex32[order];
var d = new float[order];
var e = new float[order];
SymmetricTridiagonalize(matrixCopy, d, e, tau, order);
SymmetricDiagonalize(((DenseMatrix)MatrixEv).Values, d, e, order);
SymmetricUntridiagonalize(((DenseMatrix)MatrixEv).Values, matrixCopy, tau, order);
for (var i = 0; i < order; i++)
{
VectorEv[i] = new Complex(d[i], e[i]);
}
}
else
{
var matrixH = matrix.ToArray();
NonsymmetricReduceToHessenberg(((DenseMatrix)MatrixEv).Values, matrixH, order);
NonsymmetricReduceHessenberToRealSchur(((LinearAlgebra.Complex.DenseVector)VectorEv).Values, ((DenseMatrix)MatrixEv).Values, matrixH, order);
}
for (var i = 0; i < VectorEv.Count; i++)
{
MatrixD.At(i, i, (Complex32)VectorEv[i]);
}
Control.LinearAlgebraProvider.EigenDecomp(IsSymmetric, order, matrix.Values, ((DenseMatrix) MatrixEv).Values,
((Complex.DenseVector) VectorEv).Values, ((DenseMatrix) MatrixD).Values);
}
/// <summary>
@ -129,14 +104,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// Smith, Boyle, Dongarra, Garbow, Ikebe, Klema, Moler, and Wilkinson, Handbook for
/// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
/// Fortran subroutine in EISPACK.</remarks>
private static void SymmetricTridiagonalize(Complex32[,] matrixA, float[] d, float[] e, Complex32[] tau, int order)
internal static void SymmetricTridiagonalize(Numerics.Complex32[] matrixA, float[] d, float[] e, Numerics.Complex32[] tau, int order)
{
float hh;
tau[order - 1] = Complex32.One;
tau[order - 1] = Numerics.Complex32.One;
for (var i = 0; i < order; i++)
{
d[i] = matrixA[i, i].Real;
d[i] = matrixA[i*order + i].Real;
}
// Householder reduction to tridiagonal form.
@ -148,95 +123,96 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
for (var k = 0; k < i; k++)
{
scale = scale + Math.Abs(matrixA[i, k].Real) + Math.Abs(matrixA[i, k].Imaginary);
scale = scale + Math.Abs(matrixA[k*order + i].Real) + Math.Abs(matrixA[k*order + i].Imaginary);
}
if (scale == 0.0f)
{
tau[i - 1] = Complex32.One;
tau[i - 1] = Numerics.Complex32.One;
e[i] = 0.0f;
}
else
{
for (var k = 0; k < i; k++)
{
matrixA[i, k] /= scale;
h += matrixA[i, k].MagnitudeSquared;
matrixA[k*order + i] /= scale;
h += matrixA[k*order + i].MagnitudeSquared;
}
Complex32 g = (float)Math.Sqrt(h);
e[i] = scale * g.Real;
Numerics.Complex32 g = (float) Math.Sqrt(h);
e[i] = scale*g.Real;
Complex32 temp;
var f = matrixA[i, i - 1];
if (f.Magnitude != 0)
Numerics.Complex32 temp;
var im1Oi = (i - 1)*order + i;
var f = matrixA[im1Oi];
if (f.Magnitude != 0.0f)
{
temp = -(matrixA[i, i - 1].Conjugate() * tau[i].Conjugate()) / f.Magnitude;
h += f.Magnitude * g.Real;
g = 1.0f + (g / f.Magnitude);
matrixA[i, i - 1] *= g;
temp = -(matrixA[im1Oi].Conjugate()*tau[i].Conjugate())/f.Magnitude;
h += f.Magnitude*g.Real;
g = 1.0f + (g/f.Magnitude);
matrixA[im1Oi] *= g;
}
else
{
temp = -tau[i].Conjugate();
matrixA[i, i - 1] = g;
matrixA[im1Oi] = g;
}
if ((f.Magnitude == 0) || (i != 1))
if ((f.Magnitude == 0.0f) || (i != 1))
{
f = Complex32.Zero;
f = Numerics.Complex32.Zero;
for (var j = 0; j < i; j++)
{
var tmp = Complex32.Zero;
var tmp = Numerics.Complex32.Zero;
var jO = j*order;
// Form element of A*U.
for (var k = 0; k <= j; k++)
{
tmp += matrixA[j, k] * matrixA[i, k].Conjugate();
tmp += matrixA[k*order + j]*matrixA[k*order + i].Conjugate();
}
for (var k = j + 1; k <= i - 1; k++)
{
tmp += matrixA[k, j].Conjugate() * matrixA[i, k].Conjugate();
tmp += matrixA[jO + k].Conjugate()*matrixA[k*order + i].Conjugate();
}
// Form element of P
tau[j] = tmp / h;
f += (tmp / h) * matrixA[i, j];
tau[j] = tmp/h;
f += (tmp/h)*matrixA[jO + i];
}
hh = f.Real / (h + h);
hh = f.Real/(h + h);
// Form the reduced A.
for (var j = 0; j < i; j++)
{
f = matrixA[i, j].Conjugate();
g = tau[j] - (hh * f);
f = matrixA[j*order + i].Conjugate();
g = tau[j] - (hh*f);
tau[j] = g.Conjugate();
for (var k = 0; k <= j; k++)
{
matrixA[j, k] -= (f * tau[k]) + (g * matrixA[i, k]);
matrixA[k*order + j] -= (f*tau[k]) + (g*matrixA[k*order + i]);
}
}
}
for (var k = 0; k < i; k++)
{
matrixA[i, k] *= scale;
matrixA[k*order + i] *= scale;
}
tau[i - 1] = temp.Conjugate();
}
hh = d[i];
d[i] = matrixA[i, i].Real;
matrixA[i, i] = new Complex32(hh, scale * (float)Math.Sqrt(h));
d[i] = matrixA[i*order + i].Real;
matrixA[i*order + i] = new Numerics.Complex32(hh, scale*(float) Math.Sqrt(h));
}
hh = d[0];
d[0] = matrixA[0, 0].Real;
matrixA[0, 0] = hh;
d[0] = matrixA[0].Real;
matrixA[0] = hh;
e[0] = 0.0f;
}
@ -251,7 +227,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
/// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
/// Fortran subroutine in EISPACK.</remarks>
private static void SymmetricDiagonalize(Complex32[] dataEv, float[] d, float[] e, int order)
internal static void SymmetricDiagonalize(Numerics.Complex32[] dataEv, float[] d, float[] e, int order)
{
const int Maxiter = 1000;
@ -272,7 +248,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
var m = l;
while (m < order)
{
if (Math.Abs(e[m]) <= eps * tst1)
if (Math.Abs(e[m]) <= eps*tst1)
{
break;
}
@ -291,15 +267,15 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
// Compute implicit shift
var g = d[l];
var p = (d[l + 1] - g) / (2.0f * e[l]);
var p = (d[l + 1] - g)/(2.0f*e[l]);
var r = SpecialFunctions.Hypotenuse(p, 1.0f);
if (p < 0)
{
r = -r;
}
d[l] = e[l] / (p + r);
d[l + 1] = e[l] * (p + r);
d[l] = e[l]/(p + r);
d[l + 1] = e[l]*(p + r);
var dl1 = d[l + 1];
var h = g - d[l];
@ -323,27 +299,27 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
c3 = c2;
c2 = c;
s2 = s;
g = c * e[i];
h = c * p;
g = c*e[i];
h = c*p;
r = SpecialFunctions.Hypotenuse(p, e[i]);
e[i + 1] = s * r;
s = e[i] / r;
c = p / r;
p = (c * d[i]) - (s * g);
d[i + 1] = h + (s * ((c * g) + (s * d[i])));
e[i + 1] = s*r;
s = e[i]/r;
c = p/r;
p = (c*d[i]) - (s*g);
d[i + 1] = h + (s*((c*g) + (s*d[i])));
// Accumulate transformation.
for (var k = 0; k < order; k++)
{
h = dataEv[((i + 1) * order) + k].Real;
dataEv[((i + 1) * order) + k] = (s * dataEv[(i * order) + k].Real) + (c * h);
dataEv[(i * order) + k] = (c * dataEv[(i * order) + k].Real) - (s * h);
h = dataEv[((i + 1)*order) + k].Real;
dataEv[((i + 1)*order) + k] = (s*dataEv[(i*order) + k].Real) + (c*h);
dataEv[(i*order) + k] = (c*dataEv[(i*order) + k].Real) - (s*h);
}
}
p = (-s) * s2 * c3 * el1 * e[l] / dl1;
e[l] = s * p;
d[l] = c * p;
p = (-s)*s2*c3*el1*e[l]/dl1;
e[l] = s*p;
d[l] = c*p;
// Check for convergence. If too many iterations have been performed,
// throw exception that Convergence Failed
@ -351,8 +327,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
{
throw new ArgumentException(Resources.ConvergenceFailed);
}
}
while (Math.Abs(e[l]) > eps * tst1);
} while (Math.Abs(e[l]) > eps*tst1);
}
d[l] = d[l] + f;
@ -379,9 +354,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
d[i] = p;
for (var j = 0; j < order; j++)
{
p = dataEv[(i * order) + j].Real;
dataEv[(i * order) + j] = dataEv[(k * order) + j];
dataEv[(k * order) + j] = p;
p = dataEv[(i*order) + j].Real;
dataEv[(i*order) + j] = dataEv[(k*order) + j];
dataEv[(k*order) + j] = p;
}
}
}
@ -398,35 +373,35 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// by Smith, Boyle, Dongarra, Garbow, Ikebe, Klema, Moler, and Wilkinson, Handbook for
/// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
/// Fortran subroutine in EISPACK.</remarks>
private static void SymmetricUntridiagonalize(Complex32[] dataEv, Complex32[,] matrixA, Complex32[] tau, int order)
internal static void SymmetricUntridiagonalize(Numerics.Complex32[] dataEv, Numerics.Complex32[] matrixA, Numerics.Complex32[] tau, int order)
{
for (var i = 0; i < order; i++)
{
for (var j = 0; j < order; j++)
{
dataEv[(j * order) + i] = dataEv[(j * order) + i].Real * tau[i].Conjugate();
dataEv[(j*order) + i] = dataEv[(j*order) + i].Real*tau[i].Conjugate();
}
}
// Recover and apply the Householder matrices.
for (var i = 1; i < order; i++)
{
var h = matrixA[i, i].Imaginary;
var h = matrixA[i*order + i].Imaginary;
if (h != 0)
{
for (var j = 0; j < order; j++)
{
var s = Complex32.Zero;
var s = Numerics.Complex32.Zero;
for (var k = 0; k < i; k++)
{
s += dataEv[(j * order) + k] * matrixA[i, k];
s += dataEv[(j*order) + k]*matrixA[k*order + i];
}
s = (s / h) / h;
s = (s/h)/h;
for (var k = 0; k < i; k++)
{
dataEv[(j * order) + k] -= s * matrixA[i, k].Conjugate();
dataEv[(j*order) + k] -= s*matrixA[k*order + i].Conjugate();
}
}
}
@ -443,17 +418,18 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// by Martin and Wilkinson, Handbook for Auto. Comp.,
/// Vol.ii-Linear Algebra, and the corresponding
/// Fortran subroutines in EISPACK.</remarks>
private static void NonsymmetricReduceToHessenberg(Complex32[] dataEv, Complex32[,] matrixH, int order)
internal static void NonsymmetricReduceToHessenberg(Numerics.Complex32[] dataEv, Numerics.Complex32[] matrixH, int order)
{
var ort = new Complex32[order];
var ort = new Numerics.Complex32[order];
for (var m = 1; m < order - 1; m++)
{
// Scale column.
var scale = 0.0f;
var mm1O = (m - 1)*order;
for (var i = m; i < order; i++)
{
scale += Math.Abs(matrixH[i, m - 1].Real) + Math.Abs(matrixH[i, m - 1].Imaginary);
scale += Math.Abs(matrixH[mm1O + i].Real) + Math.Abs(matrixH[mm1O + i].Imaginary);
}
if (scale != 0.0f)
@ -462,57 +438,58 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
var h = 0.0f;
for (var i = order - 1; i >= m; i--)
{
ort[i] = matrixH[i, m - 1] / scale;
ort[i] = matrixH[mm1O + i]/scale;
h += ort[i].MagnitudeSquared;
}
var g = (float)Math.Sqrt(h);
var g = (float) Math.Sqrt(h);
if (ort[m].Magnitude != 0)
{
h = h + (ort[m].Magnitude * g);
h = h + (ort[m].Magnitude*g);
g /= ort[m].Magnitude;
ort[m] = (1.0f + g) * ort[m];
ort[m] = (1.0f + g)*ort[m];
}
else
{
ort[m] = g;
matrixH[m, m - 1] = scale;
matrixH[mm1O + m] = scale;
}
// Apply Householder similarity transformation
// H = (I-u*u'/h)*H*(I-u*u')/h)
for (var j = m; j < order; j++)
{
var f = Complex32.Zero;
var f = Numerics.Complex32.Zero;
var jO = j*order;
for (var i = order - 1; i >= m; i--)
{
f += ort[i].Conjugate() * matrixH[i, j];
f += ort[i].Conjugate()*matrixH[jO + i];
}
f = f / h;
f = f/h;
for (var i = m; i < order; i++)
{
matrixH[i, j] -= f * ort[i];
matrixH[jO + i] -= f*ort[i];
}
}
for (var i = 0; i < order; i++)
{
var f = Complex32.Zero;
var f = Numerics.Complex32.Zero;
for (var j = order - 1; j >= m; j--)
{
f += ort[j] * matrixH[i, j];
f += ort[j]*matrixH[j*order + i];
}
f = f / h;
f = f/h;
for (var j = m; j < order; j++)
{
matrixH[i, j] -= f * ort[j].Conjugate();
matrixH[j*order + i] -= f*ort[j].Conjugate();
}
}
ort[m] = scale * ort[m];
matrixH[m, m - 1] *= -g;
ort[m] = scale*ort[m];
matrixH[mm1O + m] *= -g;
}
}
@ -521,59 +498,65 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
{
for (var j = 0; j < order; j++)
{
dataEv[(j * order) + i] = i == j ? Complex32.One : Complex32.Zero;
dataEv[(j*order) + i] = i == j ? Numerics.Complex32.One : Numerics.Complex32.Zero;
}
}
for (var m = order - 2; m >= 1; m--)
{
if (matrixH[m, m - 1] != Complex32.Zero && ort[m] != Complex32.Zero)
var mm1O = (m - 1)*order;
var mm1Om = mm1O + m;
if (matrixH[mm1Om] != Numerics.Complex32.Zero && ort[m] != Numerics.Complex32.Zero)
{
var norm = (matrixH[m, m - 1].Real * ort[m].Real) + (matrixH[m, m - 1].Imaginary * ort[m].Imaginary);
var norm = (matrixH[mm1Om].Real*ort[m].Real) + (matrixH[mm1Om].Imaginary*ort[m].Imaginary);
for (var i = m + 1; i < order; i++)
{
ort[i] = matrixH[i, m - 1];
ort[i] = matrixH[mm1O + i];
}
for (var j = m; j < order; j++)
{
var g = Complex32.Zero;
var g = Numerics.Complex32.Zero;
for (var i = m; i < order; i++)
{
g += ort[i].Conjugate() * dataEv[(j * order) + i];
g += ort[i].Conjugate()*dataEv[(j*order) + i];
}
// Double division avoids possible underflow
g /= norm;
for (var i = m; i < order; i++)
{
dataEv[(j * order) + i] += g * ort[i];
dataEv[(j*order) + i] += g*ort[i];
}
}
}
}
// Create real subdiagonal elements.
for (var i = 1; i < order; i++)
{
if (matrixH[i, i - 1].Imaginary != 0.0f)
var im1 = i - 1;
var im1O = im1*order;
var im1Oi = im1O + i;
var iO = i*order;
if (matrixH[im1Oi].Imaginary != 0.0f)
{
var y = matrixH[i, i - 1] / matrixH[i, i - 1].Magnitude;
matrixH[i, i - 1] = matrixH[i, i - 1].Magnitude;
var y = matrixH[im1Oi]/matrixH[im1Oi].Magnitude;
matrixH[im1Oi] = matrixH[im1Oi].Magnitude;
for (var j = i; j < order; j++)
{
matrixH[i, j] *= y.Conjugate();
matrixH[j*order + i] *= y.Conjugate();
}
for (var j = 0; j <= Math.Min(i + 1, order - 1); j++)
{
matrixH[j, i] *= y;
matrixH[iO + j] *= y;
}
for (var j = 0; j < order; j++)
{
dataEv[(i * order) + j] *= y;
dataEv[(i*order) + j] *= y;
}
}
}
@ -590,14 +573,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// by Martin and Wilkinson, Handbook for Auto. Comp.,
/// Vol.ii-Linear Algebra, and the corresponding
/// Fortran subroutine in EISPACK.</remarks>
private static void NonsymmetricReduceHessenberToRealSchur(Complex[] vectorV, Complex32[] dataEv, Complex32[,] matrixH, int order)
internal static void NonsymmetricReduceHessenberToRealSchur(Numerics.Complex32[] vectorV, Numerics.Complex32[] dataEv, Numerics.Complex32[] matrixH, int order)
{
// Initialize
var n = order - 1;
var eps = (float)Precision.SingleMachinePrecision;
var eps = (float) Precision.SingleMachinePrecision;
float norm;
Complex32 x, y, z, exshift = Complex32.Zero;
Numerics.Complex32 x, y, z, exshift = Numerics.Complex32.Zero;
// Outer loop over eigenvalue index
var iter = 0;
@ -607,8 +590,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
var l = n;
while (l > 0)
{
var tst1 = Math.Abs(matrixH[l - 1, l - 1].Real) + Math.Abs(matrixH[l - 1, l - 1].Imaginary) + Math.Abs(matrixH[l, l].Real) + Math.Abs(matrixH[l, l].Imaginary);
if (Math.Abs(matrixH[l, l - 1].Real) < eps * tst1)
var lm1 = l - 1;
var lm1O = lm1*order;
var lO = l*order;
var tst1 = Math.Abs(matrixH[lm1O + lm1].Real) + Math.Abs(matrixH[lm1O + lm1].Imaginary) + Math.Abs(matrixH[lO + l].Real) + Math.Abs(matrixH[lO + l].Imaginary);
if (Math.Abs(matrixH[lm1O + l].Real) < eps*tst1)
{
break;
}
@ -616,46 +602,50 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
l--;
}
var nm1 = n - 1;
var nm1O = nm1*order;
var nO = n*order;
var nOn = nO + n;
// Check for convergence
// One root found
if (l == n)
{
matrixH[n, n] += exshift;
vectorV[n] = matrixH[n, n].ToComplex();
matrixH[nOn] += exshift;
vectorV[n] = matrixH[nOn];
n--;
iter = 0;
}
else
{
// Form shift
Complex32 s;
Numerics.Complex32 s;
if (iter != 10 && iter != 20)
{
s = matrixH[n, n];
x = matrixH[n - 1, n] * matrixH[n, n - 1].Real;
s = matrixH[nOn];
x = matrixH[nO + nm1]*matrixH[nm1O + n].Real;
if (x.Real != 0.0f || x.Imaginary != 0.0f)
{
y = (matrixH[n - 1, n - 1] - s) / 2.0f;
z = ((y * y) + x).SquareRoot();
if ((y.Real * z.Real) + (y.Imaginary * z.Imaginary) < 0.0f)
y = (matrixH[nm1O + nm1] - s)/2.0f;
z = ((y*y) + x).SquareRoot();
if ((y.Real*z.Real) + (y.Imaginary*z.Imaginary) < 0.0)
{
z *= -1.0f;
}
x /= y + z;
x /= y + z;
s = s - x;
}
}
else
{
// Form exceptional shift
s = Math.Abs(matrixH[n, n - 1].Real) + Math.Abs(matrixH[n - 1, n - 2].Real);
s = Math.Abs(matrixH[nm1O + n].Real) + Math.Abs(matrixH[(n - 2)*order + nm1].Real);
}
for (var i = 0; i <= n; i++)
{
matrixH[i, i] -= s;
matrixH[i*order + i] -= s;
}
exshift += s;
@ -664,61 +654,70 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
// Reduce to triangle (rows)
for (var i = l + 1; i <= n; i++)
{
s = matrixH[i, i - 1].Real;
norm = SpecialFunctions.Hypotenuse(matrixH[i - 1, i - 1].Magnitude, s.Real);
x = matrixH[i - 1, i - 1] / norm;
vectorV[i - 1] = x.ToComplex();
matrixH[i - 1, i - 1] = norm;
matrixH[i, i - 1] = new Complex32(0.0f, s.Real / norm);
var im1 = i - 1;
var im1O = im1*order;
var im1Oim1 = im1O + im1;
s = matrixH[im1O + i].Real;
norm = SpecialFunctions.Hypotenuse(matrixH[im1Oim1].Magnitude, s.Real);
x = matrixH[im1Oim1]/norm;
vectorV[i - 1] = x;
matrixH[im1Oim1] = norm;
matrixH[im1O + i] = new Numerics.Complex32(0.0f, s.Real/norm);
for (var j = i; j < order; j++)
{
y = matrixH[i - 1, j];
z = matrixH[i, j];
matrixH[i - 1, j] = (x.Conjugate() * y) + (matrixH[i, i - 1].Imaginary * z);
matrixH[i, j] = (x * z) - (matrixH[i, i - 1].Imaginary * y);
var jO = j*order;
y = matrixH[jO + im1];
z = matrixH[jO + i];
matrixH[jO + im1] = (x.Conjugate()*y) + (matrixH[im1O + i].Imaginary*z);
matrixH[jO + i] = (x*z) - (matrixH[im1O + i].Imaginary*y);
}
}
s = matrixH[n, n];
s = matrixH[nOn];
if (s.Imaginary != 0.0f)
{
s /= matrixH[n, n].Magnitude;
matrixH[n, n] = matrixH[n, n].Magnitude;
s /= matrixH[nOn].Magnitude;
matrixH[nOn] = matrixH[nOn].Magnitude;
for (var j = n + 1; j < order; j++)
{
matrixH[n, j] *= s.Conjugate();
matrixH[j*order + n] *= s.Conjugate();
}
}
// Inverse operation (columns).
for (var j = l + 1; j <= n; j++)
{
x = (Complex32)vectorV[j - 1];
x = vectorV[j - 1];
var jO = j*order;
var jm1 = j - 1;
var jm1O = jm1*order;
var jm1Oj = jm1O + j;
for (var i = 0; i <= j; i++)
{
z = matrixH[i, j];
var jm1Oi = jm1O + i;
z = matrixH[jO + i];
if (i != j)
{
y = matrixH[i, j - 1];
matrixH[i, j - 1] = (x * y) + (matrixH[j, j - 1].Imaginary * z);
y = matrixH[jm1Oi];
matrixH[jm1Oi] = (x*y) + (matrixH[jm1O + j].Imaginary*z);
}
else
{
y = matrixH[i, j - 1].Real;
matrixH[i, j - 1] = new Complex32((x.Real * y.Real) - (x.Imaginary * y.Imaginary) + (matrixH[j, j - 1].Imaginary * z.Real), matrixH[i, j - 1].Imaginary);
y = matrixH[jm1Oi].Real;
matrixH[jm1Oi] = new Numerics.Complex32((x.Real*y.Real) - (x.Imaginary*y.Imaginary) + (matrixH[jm1O + j].Imaginary*z.Real), matrixH[jm1Oi].Imaginary);
}
matrixH[i, j] = (x.Conjugate() * z) - (matrixH[j, j - 1].Imaginary * y);
matrixH[jO + i] = (x.Conjugate()*z) - (matrixH[jm1O + j].Imaginary*y);
}
for (var i = 0; i < order; i++)
{
y = dataEv[((j - 1) * order) + i];
z = dataEv[(j * order) + i];
dataEv[((j - 1) * order) + i] = (x * y) + (matrixH[j, j - 1].Imaginary * z);
dataEv[(j * order) + i] = (x.Conjugate() * z) - (matrixH[j, j - 1].Imaginary * y);
y = dataEv[((j - 1)*order) + i];
z = dataEv[(j*order) + i];
dataEv[jm1O + i] = (x*y) + (matrixH[jm1Oj].Imaginary*z);
dataEv[jO + i] = (x.Conjugate()*z) - (matrixH[jm1Oj].Imaginary*y);
}
}
@ -726,12 +725,12 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
{
for (var i = 0; i <= n; i++)
{
matrixH[i, n] *= s;
matrixH[nO + i] *= s;
}
for (var i = 0; i < order; i++)
{
dataEv[(n * order) + i] *= s;
dataEv[nO + i] *= s;
}
}
}
@ -744,7 +743,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
{
for (var j = i; j < order; j++)
{
norm = Math.Max(norm, Math.Abs(matrixH[i, j].Real) + Math.Abs(matrixH[i, j].Imaginary));
norm = Math.Max(norm, Math.Abs(matrixH[j*order + i].Real) + Math.Abs(matrixH[j*order + i].Imaginary));
}
}
@ -753,39 +752,41 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
return;
}
if (norm == 0.0f)
if (norm == 0.0)
{
return;
}
for (n = order - 1; n > 0; n--)
{
x = (Complex32)vectorV[n];
matrixH[n, n] = 1.0f;
var nO = n*order;
var nOn = nO + n;
x = vectorV[n];
matrixH[nOn] = 1.0f;
for (var i = n - 1; i >= 0; i--)
{
z = 0.0f;
for (var j = i + 1; j <= n; j++)
{
z += matrixH[i, j] * matrixH[j, n];
z += matrixH[j*order + i]*matrixH[nO + j];
}
y = x - (Complex32)vectorV[i];
y = x - vectorV[i];
if (y.Real == 0.0f && y.Imaginary == 0.0f)
{
y = eps * norm;
y = eps*norm;
}
matrixH[i, n] = z / y;
matrixH[nO + i] = z/y;
// Overflow control
var tr = Math.Abs(matrixH[i, n].Real) + Math.Abs(matrixH[i, n].Imaginary);
if ((eps * tr) * tr > 1)
var tr = Math.Abs(matrixH[nO + i].Real) + Math.Abs(matrixH[nO + i].Imaginary);
if ((eps*tr)*tr > 1)
{
for (var j = i; j <= n; j++)
{
matrixH[j, n] = matrixH[j, n] / tr;
matrixH[nO + j] = matrixH[nO + j]/tr;
}
}
}
@ -794,25 +795,26 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
// Back transformation to get eigenvectors of original matrix
for (var j = order - 1; j > 0; j--)
{
var jO = j*order;
for (var i = 0; i < order; i++)
{
z = Complex32.Zero;
z = Numerics.Complex32.Zero;
for (var k = 0; k <= j; k++)
{
z += dataEv[(k * order) + i] * matrixH[k, j];
z += dataEv[(k*order) + i]*matrixH[jO + k];
}
dataEv[(j * order) + i] = z;
dataEv[jO + i] = z;
}
}
}
/// <summary>
/// Solves a system of linear equations, <b>AX = B</b>, with A SVD factorized.
/// </summary>
/// <param name="input">The right hand side <see cref="Matrix{T}"/>, <b>B</b>.</param>
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param>
public override void Solve(Matrix<Complex32> input, Matrix<Complex32> result)
public override void Solve(Matrix<Numerics.Complex32> input, Matrix<Numerics.Complex32> result)
{
// Check for proper arguments.
if (input == null)
@ -846,21 +848,21 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
if (IsSymmetric)
{
var order = VectorEv.Count;
var tmp = new Complex32[order];
var tmp = new Numerics.Complex32[order];
for (var k = 0; k < order; k++)
{
for (var j = 0; j < order; j++)
{
Complex32 value = 0.0f;
Numerics.Complex32 value = 0.0f;
if (j < order)
{
for (var i = 0; i < order; i++)
{
value += ((DenseMatrix)MatrixEv).Values[(j * order) + i].Conjugate() * input.At(i, k);
value += ((DenseMatrix) MatrixEv).Values[(j*order) + i].Conjugate()*input.At(i, k);
}
value /= (float)VectorEv[j].Real;
value /= (float) VectorEv[j].Real;
}
tmp[j] = value;
@ -868,10 +870,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
for (var j = 0; j < order; j++)
{
Complex32 value = 0.0f;
Numerics.Complex32 value = 0.0f;
for (var i = 0; i < order; i++)
{
value += ((DenseMatrix)MatrixEv).Values[(i * order) + j] * tmp[i];
value += ((DenseMatrix) MatrixEv).Values[(i*order) + j]*tmp[i];
}
result.At(j, k, value);
@ -880,7 +882,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
}
else
{
throw new ArgumentException(Resources.ArgumentMatrixSymmetric);
throw new ArgumentException(Resources.ArgumentMatrixSymmetric);
}
}
@ -889,7 +891,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// </summary>
/// <param name="input">The right hand side vector, <b>b</b>.</param>
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param>
public override void Solve(Vector<Complex32> input, Vector<Complex32> result)
public override void Solve(Vector<Numerics.Complex32> input, Vector<Numerics.Complex32> result)
{
if (input == null)
{
@ -918,8 +920,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
{
// Symmetric case -> x = V * inv(λ) * VH * b;
var order = VectorEv.Count;
var tmp = new Complex32[order];
Complex32 value;
var tmp = new Numerics.Complex32[order];
Numerics.Complex32 value;
for (var j = 0; j < order; j++)
{
@ -928,10 +930,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
{
for (var i = 0; i < order; i++)
{
value += ((DenseMatrix)MatrixEv).Values[(j * order) + i].Conjugate() * input[i];
value += ((DenseMatrix) MatrixEv).Values[(j*order) + i].Conjugate()*input[i];
}
value /= (float)VectorEv[j].Real;
value /= (float) VectorEv[j].Real;
}
tmp[j] = value;
@ -940,9 +942,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
for (var j = 0; j < order; j++)
{
value = 0;
for (int i = 0; i < order; i++)
for (var i = 0; i < order; i++)
{
value += ((DenseMatrix)MatrixEv).Values[(i * order) + j] * tmp[i];
value += ((DenseMatrix) MatrixEv).Values[(i*order) + j]*tmp[i];
}
result[j] = value;
@ -954,4 +956,4 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
}
}
}
}
}

4
src/Numerics/LinearAlgebra/Complex32/Factorization/UserEvd.cs

@ -80,9 +80,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
IsSymmetric = true;
for (var i = 0; i < order & IsSymmetric; i++)
for (var i = 0; IsSymmetric && i < order; i++)
{
for (var j = 0; j < order & IsSymmetric; j++)
for (var j = 0; IsSymmetric && j < order; j++)
{
IsSymmetric &= matrix.At(i, j) == matrix.At(j, i).Conjugate();
}

579
src/Numerics/LinearAlgebra/Double/Factorization/DenseEvd.cs

File diff suppressed because it is too large

4
src/Numerics/LinearAlgebra/Double/Factorization/UserEvd.cs

@ -79,9 +79,9 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
IsSymmetric = true;
for (var i = 0; i < order & IsSymmetric; i++)
for (var i = 0; IsSymmetric && i < order; i++)
{
for (var j = 0; j < order & IsSymmetric; j++)
for (var j = 0; IsSymmetric && j < order; j++)
{
IsSymmetric &= matrix.At(i, j) == matrix.At(j, i);
}

600
src/Numerics/LinearAlgebra/Single/Factorization/DenseEvd.cs

File diff suppressed because it is too large

4
src/Numerics/LinearAlgebra/Single/Factorization/UserEvd.cs

@ -80,9 +80,9 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
IsSymmetric = true;
for (var i = 0; i < order & IsSymmetric; i++)
for (var i = 0; IsSymmetric && i < order; i++)
{
for (var j = 0; j < order & IsSymmetric; j++)
for (var j = 0; IsSymmetric && j < order; j++)
{
IsSymmetric &= matrix.At(i, j) == matrix.At(j, i);
}

2
src/UnitTests/LinearAlgebraProviderTests/Complex32/LinearAlgebraProviderTests.cs

@ -248,7 +248,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraProviderTests.Complex32
var matrix = _matrices["Square3x3"];
var work = new float[18];
var norm = Control.LinearAlgebraProvider.MatrixNorm(Norm.FrobeniusNorm, matrix.RowCount, matrix.ColumnCount, matrix.Values, work);
AssertHelpers.AlmostEqual(10.777754868246f, norm, 8);
AssertHelpers.AlmostEqual(10.777754868246f, norm, 6);
}
/// <summary>

1
src/UnitTests/LinearAlgebraTests/Complex/Factorization/EvdTests.cs

@ -30,7 +30,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Factorization
using System.Numerics;
using LinearAlgebra.Complex;
using LinearAlgebra.Complex.Factorization;
using LinearAlgebra.Generic.Factorization;
using NUnit.Framework;
/// <summary>

12
src/UnitTests/LinearAlgebraTests/Complex32/Factorization/EvdTests.cs

@ -30,7 +30,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Factorization
using System.Numerics;
using LinearAlgebra.Complex32;
using LinearAlgebra.Complex32.Factorization;
using LinearAlgebra.Generic.Factorization;
using NUnit.Framework;
using Complex32 = Numerics.Complex32;
@ -115,8 +114,8 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Factorization
/// <summary>
/// Can factorize a symmetric random square matrix.
/// </summary> <param name="order">Matrix order.</param>
[Test, Ignore]
public void CanFactorizeRandomSymmetricMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
[Test]
public void CanFactorizeRandomSymmetricMatrix([Values(1, 2, 5, 10)] int order)
{
var matrixA = MatrixLoader.GenerateRandomPositiveDefiniteHermitianDenseMatrix(order);
MatrixHelpers.ForceConjugateSymmetric(matrixA);
@ -201,13 +200,12 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Factorization
/// Can solve a system of linear equations for a random vector and symmetric matrix (Ax=b).
/// </summary>
/// <param name="order">Matrix order.</param>
[Test, Ignore]
[Test]
[TestCase(1)]
[TestCase(2)]
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomVectorAndSymmetricMatrix(int order)
{
var matrixA = MatrixLoader.GenerateRandomPositiveDefiniteHermitianDenseMatrix(order);
@ -249,7 +247,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Factorization
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomMatrixAndSymmetricMatrix(int order)
{
var matrixA = MatrixLoader.GenerateRandomPositiveDefiniteHermitianDenseMatrix(order);
@ -292,13 +289,12 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Factorization
/// Can solve a system of linear equations for a random vector and symmetric matrix (Ax=b) into a result vector.
/// </summary>
/// <param name="order">Matrix order.</param>
[Test, Ignore]
[Test]
[TestCase(1)]
[TestCase(2)]
[TestCase(5)]
[TestCase(10)]
[TestCase(50)]
[TestCase(100)]
public void CanSolveForRandomVectorAndSymmetricMatrixWhenResultVectorGiven(int order)
{
var matrixA = MatrixLoader.GenerateRandomPositiveDefiniteHermitianDenseMatrix(order);

4
src/UnitTests/LinearAlgebraTests/Double/Factorization/EvdTests.cs

@ -24,8 +24,6 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using MathNet.Numerics.LinearAlgebra.Generic;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Factorization
{
using System;
@ -128,7 +126,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Factorization
var factorEvd = matrixA.Evd();
var eigenVectors = factorEvd.EigenVectors();
var d = factorEvd.D();
Assert.AreEqual(order, eigenVectors.RowCount);
Assert.AreEqual(order, eigenVectors.ColumnCount);

7
src/UnitTests/LinearAlgebraTests/Single/Factorization/EvdTests.cs

@ -77,7 +77,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Factorization
/// Can factorize a random square matrix.
/// </summary>
/// <param name="order">Matrix order.</param>
[Test, Ignore]
[Test]
public void CanFactorizeRandomMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
{
var matrixA = MatrixLoader.GenerateRandomDenseMatrix(order, order);
@ -108,8 +108,8 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Factorization
/// Can factorize a symmetric random square matrix.
/// </summary>
/// <param name="order">Matrix order.</param>
[Test, Ignore]
public void CanFactorizeRandomSymmetricMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
[Test]
public void CanFactorizeRandomSymmetricMatrix([Values(1, 2, 5, 10, 50)] int order)
{
var matrixA = MatrixLoader.GenerateRandomPositiveDefiniteDenseMatrix(order);
MatrixHelpers.ForceSymmetric(matrixA);
@ -169,7 +169,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Factorization
matrixA[i - 1, i] = 1;
matrixA[i + 1, i] = 1;
}
var factorEvd = matrixA.Evd();
Assert.AreEqual(factorEvd.Determinant, 0);

Loading…
Cancel
Save