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
v2
Christoph Ruegg 14 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 "blas.h"
#include <algorithm>
extern "C" {
#include "clapack.h" #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[]){ template<typename T, typename K>
int info = clapack_spotrf(CblasColMajor, CblasLower, n, a, n); inline int lu_inverse(int n, T a[],
for (int i = 0; i < n; ++i) int (*getrf) (CBLAS_ORDER, const int, const int, K*, const int, int*),
{ int (*getri) (CBLAS_ORDER, const int, K*, const int, const int*))
int index = i * n; {
for (int j = 0; j < n && i > j; ++j) int* ipiv = new int[n];
{ int info = getrf(CblasColMajor, n, n, a, n, ipiv);
a[index + j] = 0;
} if (info != 0){
} delete[] ipiv;
return info; return info;
} }
DLLEXPORT int d_cholesky_factor(int n, double* a){ info = getri(CblasColMajor, n, a, n, ipiv);
int info = clapack_dpotrf(CblasColMajor, CblasLower, n, a, n); delete[] ipiv;
for (int i = 0; i < n; ++i) 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; a[index + j] = zero;
for (int j = 0; j < n && i > j; ++j)
{
a[index + j] = 0;
}
} }
}
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; return info;
} }
DLLEXPORT int c_cholesky_factor(int n, Complex8 a[]){ info = potrs(CblasColMajor, CblasLower, n, nrhs, clone, n, b, n);
int info = clapack_cpotrf(CblasColMajor, CblasLower, n, a, n); delete[] clone;
Complex8 zero; return info;
zero.real = 0.0; }
zero.real = 0.0;
for (int i = 0; i < n; ++i) 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; if (i > j)
for (int j = 0; j < n && i > j; ++j)
{ {
a[index + j] = zero; q[j * m + i] = r[j * m + i];
} }
} }
return info;
} }
DLLEXPORT int z_cholesky_factor(int n, Complex16 a[]){ //compute the q elements explicitly
int info = clapack_zpotrf(CblasColMajor, CblasLower, n, a, n); if (m <= n)
Complex16 zero; {
zero.real = 0.0; info = orgqr(m, m, m, q, m, tau);
zero.real = 0.0; }
for (int i = 0; i < n; ++i) 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; if( i <= j) {
for (int j = 0; j < n && i > j; ++j) r[j * n + i] = q[j * m + i];
{
a[index + j] = zero;
} }
} }
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> 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]; T* clone = new T[m*n];
memcpy(clone, a, m*n*sizeof(T)); memcpy(clone, a, m*n*sizeof(T));
return clone; return clone;

8
src/NativeWrappers/Common/resource.rc

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

9
src/NativeWrappers/Linux/build.sh

@ -1,6 +1,11 @@
export INTEL=/opt/intel export INTEL=/opt/intel
export MKL=$INTEL/mkl 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 "mkl_cblas.h"
#include "wrapper_common.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[]){ DLLEXPORT void s_axpy(const MKL_INT n, const float alpha, const float x[], float y[]){
cblas_saxpy(n, alpha, x, 1, y, 1); 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); 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 "mkl_vml.h"
#include "wrapper_common.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[] ){ DLLEXPORT void s_vector_add( const int n, const float x[], const float y[], float result[] ){
vsAdd( n, x, y, 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[] ){ DLLEXPORT void z_vector_divide( const int n, const MKL_Complex16 x[], const MKL_Complex16 y[], MKL_Complex16 result[] ){
vzDiv( n, x, y, 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> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<AdditionalOptions>/Qvec-report:1 %(AdditionalOptions)</AdditionalOptions>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>libiomp5md.lib;mkl_intel_c.lib;mkl_intel_thread.lib;mkl_core.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>libiomp5md.lib;mkl_intel_c.lib;mkl_intel_thread.lib;mkl_core.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -271,6 +272,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<AdditionalOptions>/Qvec-report:1 %(AdditionalOptions)</AdditionalOptions>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>libiomp5md.lib;mkl_intel_lp64.lib;mkl_intel_thread.lib;mkl_core.lib;%(AdditionalDependencies)</AdditionalDependencies> <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\lapack.cpp" />
<ClCompile Include="..\..\MKL\vector_functions.c" /> <ClCompile Include="..\..\MKL\vector_functions.c" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\Common\wrapper_common.h" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="..\..\Common\resource.rc" /> <ResourceCompile Include="..\..\Common\resource.rc" />
</ItemGroup> </ItemGroup>

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

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

18
src/NativeWrappers/Windows/NativeWrappers.sln

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

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

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // 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. /// The requested <see cref="Norm"/> of the matrix.
/// </returns> /// </returns>
Complex MatrixNorm(Norm norm, int rows, int columns, Complex[] matrix, double[] work); 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://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without // files (the "Software"), to deal in the Software without
@ -24,14 +24,15 @@
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
// </copyright> // </copyright>
using System.Numerics;
using MathNet.Numerics.LinearAlgebra.Generic.Factorization;
namespace MathNet.Numerics.Algorithms.LinearAlgebra namespace MathNet.Numerics.Algorithms.LinearAlgebra
{ {
using System; using System;
using Properties; using Properties;
using Threading; using Threading;
using System.Numerics;
using Numerics.LinearAlgebra.Complex32.Factorization;
using Numerics.LinearAlgebra.Generic.Factorization;
using Numerics.LinearAlgebra.Complex32;
/// <summary> /// <summary>
/// The managed linear algebra provider. /// 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://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without // files (the "Software"), to deal in the Software without
@ -24,11 +24,11 @@
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
// </copyright> // </copyright>
using MathNet.Numerics.LinearAlgebra.Generic.Factorization;
namespace MathNet.Numerics.Algorithms.LinearAlgebra namespace MathNet.Numerics.Algorithms.LinearAlgebra
{ {
using System; using System;
using System.Numerics;
using Numerics.LinearAlgebra.Generic.Factorization;
using Properties; using Properties;
using Threading; 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://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without // files (the "Software"), to deal in the Software without
@ -24,11 +24,11 @@
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
// </copyright> // </copyright>
using MathNet.Numerics.LinearAlgebra.Generic.Factorization;
namespace MathNet.Numerics.Algorithms.LinearAlgebra namespace MathNet.Numerics.Algorithms.LinearAlgebra
{ {
using System; using System;
using System.Numerics;
using Numerics.LinearAlgebra.Generic.Factorization;
using Properties; using Properties;
using Threading; 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://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // 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://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -28,14 +28,13 @@
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
// </copyright> // </copyright>
using MathNet.Numerics.LinearAlgebra.Generic.Factorization;
namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{ {
using System; using System;
using System.Security; using System.Security;
using Numerics.LinearAlgebra.Generic.Factorization;
using Properties; using Properties;
/// <summary> /// <summary>
/// Intel's Math Kernel Library (MKL) linear algebra provider. /// Intel's Math Kernel Library (MKL) linear algebra provider.
/// </summary> /// </summary>
@ -68,7 +67,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
return SafeNativeMethods.c_dot_product(x.Length, x, y); return SafeNativeMethods.c_dot_product(x.Length, x, y);
} }
/// <summary> /// <summary>
/// Adds a scaled vector to another: <c>result = y + alpha*x</c>. /// Adds a scaled vector to another: <c>result = y + alpha*x</c>.
/// </summary> /// </summary>
@ -121,8 +120,8 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
if (x == null) if (x == null)
{ {
throw new ArgumentNullException("x"); throw new ArgumentNullException("x");
} }
if (!ReferenceEquals(x, result)) if (!ReferenceEquals(x, result))
{ {
Array.Copy(x, 0, result, 0, x.Length); 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 k = transposeA == Transpose.DontTranspose ? columnsA : rowsA;
var l = transposeB == Transpose.DontTranspose ? rowsB : columnsB; 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) if (k != l)
@ -225,7 +224,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("ipiv"); throw new ArgumentNullException("ipiv");
} }
if (data.Length != order * order) if (data.Length != order*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "data"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "data");
} }
@ -234,7 +233,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
} }
SafeNativeMethods.c_lu_factor(order, data, ipiv); SafeNativeMethods.c_lu_factor(order, data, ipiv);
} }
@ -252,13 +251,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("a"); throw new ArgumentNullException("a");
} }
if (a.Length != order * order) if (a.Length != order*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
} }
var work = new Complex32[order]; var work = new Complex32[order];
SafeNativeMethods.c_lu_inverse(order, a, work, work.Length); SafeNativeMethods.c_lu_inverse(order, a, work, work.Length);
} }
/// <summary> /// <summary>
@ -281,7 +280,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("ipiv"); throw new ArgumentNullException("ipiv");
} }
if (a.Length != order * order) if (a.Length != order*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
} }
@ -292,7 +291,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
} }
var work = new Complex32[order]; 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> /// <summary>
@ -312,7 +311,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("a"); throw new ArgumentNullException("a");
} }
if (a.Length != order * order) if (a.Length != order*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
} }
@ -327,7 +326,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.WorkArrayTooSmall, "work"); 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> /// <summary>
@ -353,7 +352,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("ipiv"); throw new ArgumentNullException("ipiv");
} }
if (a.Length != order * order) if (a.Length != order*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
} }
@ -373,7 +372,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.WorkArrayTooSmall, "work"); 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> /// <summary>
@ -392,22 +391,22 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("a"); throw new ArgumentNullException("a");
} }
if (a.Length != order * order) if (a.Length != order*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
} }
if (b.Length != columnsOfB * order) if (b.Length != columnsOfB*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
} }
if (ReferenceEquals(a, b)) if (ReferenceEquals(a, b))
{ {
throw new ArgumentException(Resources.ArgumentReferenceDifferent); throw new ArgumentException(Resources.ArgumentReferenceDifferent);
} }
SafeNativeMethods.c_lu_solve(order, columnsOfB, a, b); SafeNativeMethods.c_lu_solve(order, columnsOfB, a, b);
} }
/// <summary> /// <summary>
@ -432,7 +431,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("ipiv"); throw new ArgumentNullException("ipiv");
} }
if (a.Length != order * order) if (a.Length != order*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
} }
@ -442,7 +441,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
} }
if (b.Length != columnsOfB * order) if (b.Length != columnsOfB*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
} }
@ -452,7 +451,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent); 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> /// <summary>
@ -475,7 +474,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentMustBePositive, "order"); throw new ArgumentException(Resources.ArgumentMustBePositive, "order");
} }
if (a.Length != order * order) if (a.Length != order*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
} }
@ -510,7 +509,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("b"); throw new ArgumentNullException("b");
} }
if (b.Length != orderA * columnsB) if (b.Length != orderA*columnsB)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
} }
@ -520,7 +519,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent); throw new ArgumentException(Resources.ArgumentReferenceDifferent);
} }
SafeNativeMethods.c_cholesky_solve(orderA, columnsB, a, b); SafeNativeMethods.c_cholesky_solve(orderA, columnsB, a, b);
} }
/// <summary> /// <summary>
@ -544,7 +543,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("b"); throw new ArgumentNullException("b");
} }
if (b.Length != orderA * columnsB) if (b.Length != orderA*columnsB)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
} }
@ -554,7 +553,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent); throw new ArgumentException(Resources.ArgumentReferenceDifferent);
} }
SafeNativeMethods.c_cholesky_solve_factored(orderA, columnsB, a, b); SafeNativeMethods.c_cholesky_solve_factored(orderA, columnsB, a, b);
} }
/// <summary> /// <summary>
@ -582,7 +581,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("q"); throw new ArgumentNullException("q");
} }
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");
} }
@ -592,12 +591,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau"); 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"); 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); 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"); throw new ArgumentNullException("work");
} }
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");
} }
@ -644,14 +643,14 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau"); 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"); 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"); throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
} }
@ -672,7 +671,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
[SecuritySafeCritical] [SecuritySafeCritical]
public override void QRSolve(Complex32[] a, int rows, int columns, Complex32[] b, int columnsB, Complex32[] x, QRMethod method = QRMethod.Full) 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); QRSolve(a, rows, columns, b, columnsB, x, work, method);
} }
@ -713,17 +712,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("work"); throw new ArgumentNullException("work");
} }
if (a.Length != rows * columns) if (a.Length != rows*columns)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
} }
if (b.Length != rows * columnsB) if (b.Length != rows*columnsB)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
} }
if (x.Length != columns * columnsB) if (x.Length != columns*columnsB)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "x"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "x");
} }
@ -735,7 +734,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
if (work.Length < 1) if (work.Length < 1)
{ {
work[0] = rows * Control.BlockSize; work[0] = rows*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work"); throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
} }
@ -759,7 +758,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
[SecuritySafeCritical] [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) 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); 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; 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) if (work.Length < 1)
{ {
work[0] = rowsA * Control.BlockSize; work[0] = rowsA*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work"); throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
} }
@ -895,12 +894,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("vt"); throw new ArgumentNullException("vt");
} }
if (u.Length != rowsA * rowsA) if (u.Length != rowsA*rowsA)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
} }
if (vt.Length != columnsA * columnsA) if (vt.Length != columnsA*columnsA)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
} }
@ -910,7 +909,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s"); 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); SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, work);
} }
@ -940,20 +939,20 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("x"); throw new ArgumentNullException("x");
} }
if (b.Length != rowsA * columnsB) if (b.Length != rowsA*columnsB)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
} }
if (x.Length != columnsA * columnsB) if (x.Length != columnsA*columnsB)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b"); 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 s = new Complex32[Math.Min(rowsA, columnsA)];
var u = new Complex32[rowsA * rowsA]; var u = new Complex32[rowsA*rowsA];
var vt = new Complex32[columnsA * columnsA]; var vt = new Complex32[columnsA*columnsA];
var clone = new Complex32[a.Length]; var clone = new Complex32[a.Length];
a.Copy(clone); a.Copy(clone);
@ -1005,12 +1004,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("work"); throw new ArgumentNullException("work");
} }
if (u.Length != rowsA * rowsA) if (u.Length != rowsA*rowsA)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
} }
if (vt.Length != columnsA * columnsA) if (vt.Length != columnsA*columnsA)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
} }
@ -1025,9 +1024,9 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentSingleDimensionArray, "work"); 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"); throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
} }
@ -1060,7 +1059,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength); throw new ArgumentException(Resources.ArgumentArraysSameLength);
} }
if (x.Length != result.Length) if (x.Length != result.Length)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength); throw new ArgumentException(Resources.ArgumentArraysSameLength);
@ -1095,12 +1094,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength); throw new ArgumentException(Resources.ArgumentArraysSameLength);
} }
if (x.Length != result.Length) if (x.Length != result.Length)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength); throw new ArgumentException(Resources.ArgumentArraysSameLength);
} }
SafeNativeMethods.c_vector_subtract(x.Length, x, y, result); SafeNativeMethods.c_vector_subtract(x.Length, x, y, result);
} }
@ -1130,12 +1129,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength); throw new ArgumentException(Resources.ArgumentArraysSameLength);
} }
if (x.Length != result.Length) if (x.Length != result.Length)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength); throw new ArgumentException(Resources.ArgumentArraysSameLength);
} }
SafeNativeMethods.c_vector_multiply(x.Length, x, y, result); SafeNativeMethods.c_vector_multiply(x.Length, x, y, result);
} }
@ -1165,12 +1164,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength); throw new ArgumentException(Resources.ArgumentArraysSameLength);
} }
if (x.Length != result.Length) if (x.Length != result.Length)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength); throw new ArgumentException(Resources.ArgumentArraysSameLength);
} }
SafeNativeMethods.c_vector_divide(x.Length, x, y, result); 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://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -28,14 +28,14 @@
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
// </copyright> // </copyright>
using MathNet.Numerics.LinearAlgebra.Generic.Factorization;
namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{ {
using System; using System;
using System.Numerics;
using System.Security; using System.Security;
using Numerics.LinearAlgebra.Generic.Factorization;
using Properties; using Properties;
/// <summary> /// <summary>
/// Intel's Math Kernel Library (MKL) linear algebra provider. /// Intel's Math Kernel Library (MKL) linear algebra provider.
/// </summary> /// </summary>
@ -121,8 +121,8 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
if (x == null) if (x == null)
{ {
throw new ArgumentNullException("x"); throw new ArgumentNullException("x");
} }
if (!ReferenceEquals(x, result)) if (!ReferenceEquals(x, result))
{ {
Array.Copy(x, 0, result, 0, x.Length); 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 k = transposeA == Transpose.DontTranspose ? columnsA : rowsA;
var l = transposeB == Transpose.DontTranspose ? rowsB : columnsB; 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) if (k != l)
@ -225,7 +225,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("ipiv"); throw new ArgumentNullException("ipiv");
} }
if (data.Length != order * order) if (data.Length != order*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "data"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "data");
} }
@ -234,7 +234,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
} }
SafeNativeMethods.d_lu_factor(order, data, ipiv); SafeNativeMethods.d_lu_factor(order, data, ipiv);
} }
@ -252,13 +252,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("a"); throw new ArgumentNullException("a");
} }
if (a.Length != order * order) if (a.Length != order*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
} }
var work = new double[order]; var work = new double[order];
SafeNativeMethods.d_lu_inverse(order, a, work, work.Length); SafeNativeMethods.d_lu_inverse(order, a, work, work.Length);
} }
/// <summary> /// <summary>
@ -281,7 +281,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("ipiv"); throw new ArgumentNullException("ipiv");
} }
if (a.Length != order * order) if (a.Length != order*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
} }
@ -292,7 +292,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
} }
var work = new double[order]; 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> /// <summary>
@ -312,7 +312,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("a"); throw new ArgumentNullException("a");
} }
if (a.Length != order * order) if (a.Length != order*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
} }
@ -327,7 +327,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.WorkArrayTooSmall, "work"); 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> /// <summary>
@ -353,7 +353,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("ipiv"); throw new ArgumentNullException("ipiv");
} }
if (a.Length != order * order) if (a.Length != order*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
} }
@ -373,7 +373,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.WorkArrayTooSmall, "work"); 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> /// <summary>
@ -392,22 +392,22 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("a"); throw new ArgumentNullException("a");
} }
if (a.Length != order * order) if (a.Length != order*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
} }
if (b.Length != columnsOfB * order) if (b.Length != columnsOfB*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
} }
if (ReferenceEquals(a, b)) if (ReferenceEquals(a, b))
{ {
throw new ArgumentException(Resources.ArgumentReferenceDifferent); throw new ArgumentException(Resources.ArgumentReferenceDifferent);
} }
SafeNativeMethods.d_lu_solve(order, columnsOfB, a, b); SafeNativeMethods.d_lu_solve(order, columnsOfB, a, b);
} }
/// <summary> /// <summary>
@ -432,7 +432,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("ipiv"); throw new ArgumentNullException("ipiv");
} }
if (a.Length != order * order) if (a.Length != order*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
} }
@ -442,7 +442,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
} }
if (b.Length != columnsOfB * order) if (b.Length != columnsOfB*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
} }
@ -452,7 +452,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent); 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> /// <summary>
@ -475,7 +475,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentMustBePositive, "order"); throw new ArgumentException(Resources.ArgumentMustBePositive, "order");
} }
if (a.Length != order * order) if (a.Length != order*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
} }
@ -510,7 +510,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("b"); throw new ArgumentNullException("b");
} }
if (b.Length != orderA * columnsB) if (b.Length != orderA*columnsB)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
} }
@ -520,7 +520,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent); throw new ArgumentException(Resources.ArgumentReferenceDifferent);
} }
SafeNativeMethods.d_cholesky_solve(orderA, columnsB, a, b); SafeNativeMethods.d_cholesky_solve(orderA, columnsB, a, b);
} }
/// <summary> /// <summary>
@ -544,7 +544,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("b"); throw new ArgumentNullException("b");
} }
if (b.Length != orderA * columnsB) if (b.Length != orderA*columnsB)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
} }
@ -554,7 +554,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent); throw new ArgumentException(Resources.ArgumentReferenceDifferent);
} }
SafeNativeMethods.d_cholesky_solve_factored(orderA, columnsB, a, b); SafeNativeMethods.d_cholesky_solve_factored(orderA, columnsB, a, b);
} }
/// <summary> /// <summary>
@ -582,7 +582,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("q"); throw new ArgumentNullException("q");
} }
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");
} }
@ -592,12 +592,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau"); 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"); 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); 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"); throw new ArgumentNullException("work");
} }
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");
} }
@ -644,14 +644,14 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau"); 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"); 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"); throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
} }
@ -683,7 +683,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("q"); throw new ArgumentNullException("q");
} }
if (q.Length != rowsA * columnsA) if (q.Length != rowsA*columnsA)
{ {
throw new ArgumentException(string.Format(Resources.ArgumentArrayWrongLength, "rowsR * columnsR"), "q"); 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"); 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); SafeNativeMethods.d_qr_thin_factor(rowsA, columnsA, q, tau, r, work, work.Length);
} }
@ -776,7 +775,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
[SecuritySafeCritical] [SecuritySafeCritical]
public override void QRSolve(double[] a, int rows, int columns, double[] b, int columnsB, double[] x, QRMethod method = QRMethod.Full) 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); QRSolve(a, rows, columns, b, columnsB, x, work, method);
} }
@ -817,17 +816,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("work"); throw new ArgumentNullException("work");
} }
if (a.Length != rows * columns) if (a.Length != rows*columns)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
} }
if (b.Length != rows * columnsB) if (b.Length != rows*columnsB)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
} }
if (x.Length != columns * columnsB) if (x.Length != columns*columnsB)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "x"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "x");
} }
@ -839,7 +838,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
if (work.Length < 1) if (work.Length < 1)
{ {
work[0] = rows * Control.BlockSize; work[0] = rows*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work"); throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
} }
@ -863,7 +862,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
[SecuritySafeCritical] [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) 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); 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; int rowsQ, columnsQ, rowsR, columnsR;
if( method == QRMethod.Full) if (method == QRMethod.Full)
{ {
rowsQ = columnsQ = rowsR = rowsA; rowsQ = columnsQ = rowsR = rowsA;
columnsR = columnsA; columnsR = columnsA;
@ -925,29 +924,29 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
columnsQ = rowsR = columnsR = columnsA; 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) if (work.Length < 1)
{ {
work[0] = rowsA * Control.BlockSize; work[0] = rowsA*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work"); throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
} }
@ -999,12 +998,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("vt"); throw new ArgumentNullException("vt");
} }
if (u.Length != rowsA * rowsA) if (u.Length != rowsA*rowsA)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
} }
if (vt.Length != columnsA * columnsA) if (vt.Length != columnsA*columnsA)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
} }
@ -1014,7 +1013,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s"); 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); SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, work);
} }
@ -1044,20 +1043,20 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("x"); throw new ArgumentNullException("x");
} }
if (b.Length != rowsA * columnsB) if (b.Length != rowsA*columnsB)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
} }
if (x.Length != columnsA * columnsB) if (x.Length != columnsA*columnsB)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b"); 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 s = new double[Math.Min(rowsA, columnsA)];
var u = new double[rowsA * rowsA]; var u = new double[rowsA*rowsA];
var vt = new double[columnsA * columnsA]; var vt = new double[columnsA*columnsA];
var clone = new double[a.Length]; var clone = new double[a.Length];
a.Copy(clone); a.Copy(clone);
@ -1109,12 +1108,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("work"); throw new ArgumentNullException("work");
} }
if (u.Length != rowsA * rowsA) if (u.Length != rowsA*rowsA)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
} }
if (vt.Length != columnsA * columnsA) if (vt.Length != columnsA*columnsA)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
} }
@ -1129,9 +1128,9 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentSingleDimensionArray, "work"); 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"); throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
} }
@ -1164,7 +1163,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength); throw new ArgumentException(Resources.ArgumentArraysSameLength);
} }
if (x.Length != result.Length) if (x.Length != result.Length)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength); throw new ArgumentException(Resources.ArgumentArraysSameLength);
@ -1199,12 +1198,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength); throw new ArgumentException(Resources.ArgumentArraysSameLength);
} }
if (x.Length != result.Length) if (x.Length != result.Length)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength); throw new ArgumentException(Resources.ArgumentArraysSameLength);
} }
SafeNativeMethods.d_vector_subtract(x.Length, x, y, result); SafeNativeMethods.d_vector_subtract(x.Length, x, y, result);
} }
@ -1234,12 +1233,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength); throw new ArgumentException(Resources.ArgumentArraysSameLength);
} }
if (x.Length != result.Length) if (x.Length != result.Length)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength); throw new ArgumentException(Resources.ArgumentArraysSameLength);
} }
SafeNativeMethods.d_vector_multiply(x.Length, x, y, result); SafeNativeMethods.d_vector_multiply(x.Length, x, y, result);
} }
@ -1269,13 +1268,67 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength); throw new ArgumentException(Resources.ArgumentArraysSameLength);
} }
if (x.Length != result.Length) if (x.Length != result.Length)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength); throw new ArgumentException(Resources.ArgumentArraysSameLength);
} }
SafeNativeMethods.d_vector_divide(x.Length, x, y, result); 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://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -28,18 +28,14 @@
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
// </copyright> // </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 namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{ {
using System; using System;
using System.Numerics;
using System.Security; using System.Security;
using Numerics.LinearAlgebra.Generic.Factorization;
using Properties; using Properties;
/// <summary> /// <summary>
/// Intel's Math Kernel Library (MKL) linear algebra provider. /// Intel's Math Kernel Library (MKL) linear algebra provider.
/// </summary> /// </summary>
@ -72,7 +68,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
return SafeNativeMethods.s_dot_product(x.Length, x, y); return SafeNativeMethods.s_dot_product(x.Length, x, y);
} }
/// <summary> /// <summary>
/// Adds a scaled vector to another: <c>result = y + alpha*x</c>. /// Adds a scaled vector to another: <c>result = y + alpha*x</c>.
/// </summary> /// </summary>
@ -125,8 +121,8 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
if (x == null) if (x == null)
{ {
throw new ArgumentNullException("x"); throw new ArgumentNullException("x");
} }
if (!ReferenceEquals(x, result)) if (!ReferenceEquals(x, result))
{ {
Array.Copy(x, 0, result, 0, x.Length); 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 k = transposeA == Transpose.DontTranspose ? columnsA : rowsA;
var l = transposeB == Transpose.DontTranspose ? rowsB : columnsB; 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) if (k != l)
@ -229,7 +225,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("ipiv"); throw new ArgumentNullException("ipiv");
} }
if (data.Length != order * order) if (data.Length != order*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "data"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "data");
} }
@ -238,7 +234,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
} }
SafeNativeMethods.s_lu_factor(order, data, ipiv); SafeNativeMethods.s_lu_factor(order, data, ipiv);
} }
@ -256,13 +252,13 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("a"); throw new ArgumentNullException("a");
} }
if (a.Length != order * order) if (a.Length != order*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
} }
var work = new float[order]; var work = new float[order];
SafeNativeMethods.s_lu_inverse(order, a, work, work.Length); SafeNativeMethods.s_lu_inverse(order, a, work, work.Length);
} }
/// <summary> /// <summary>
@ -285,7 +281,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("ipiv"); throw new ArgumentNullException("ipiv");
} }
if (a.Length != order * order) if (a.Length != order*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
} }
@ -316,7 +312,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("a"); throw new ArgumentNullException("a");
} }
if (a.Length != order * order) if (a.Length != order*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
} }
@ -331,7 +327,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.WorkArrayTooSmall, "work"); 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> /// <summary>
@ -357,7 +353,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("ipiv"); throw new ArgumentNullException("ipiv");
} }
if (a.Length != order * order) if (a.Length != order*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
} }
@ -396,22 +392,22 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("a"); throw new ArgumentNullException("a");
} }
if (a.Length != order * order) if (a.Length != order*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
} }
if (b.Length != columnsOfB * order) if (b.Length != columnsOfB*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
} }
if (ReferenceEquals(a, b)) if (ReferenceEquals(a, b))
{ {
throw new ArgumentException(Resources.ArgumentReferenceDifferent); throw new ArgumentException(Resources.ArgumentReferenceDifferent);
} }
SafeNativeMethods.s_lu_solve(order, columnsOfB, a, b); SafeNativeMethods.s_lu_solve(order, columnsOfB, a, b);
} }
/// <summary> /// <summary>
@ -436,7 +432,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("ipiv"); throw new ArgumentNullException("ipiv");
} }
if (a.Length != order * order) if (a.Length != order*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
} }
@ -446,7 +442,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "ipiv");
} }
if (b.Length != columnsOfB * order) if (b.Length != columnsOfB*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
} }
@ -456,7 +452,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent); 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> /// <summary>
@ -479,7 +475,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentMustBePositive, "order"); throw new ArgumentException(Resources.ArgumentMustBePositive, "order");
} }
if (a.Length != order * order) if (a.Length != order*order)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
} }
@ -514,7 +510,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("b"); throw new ArgumentNullException("b");
} }
if (b.Length != orderA * columnsB) if (b.Length != orderA*columnsB)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
} }
@ -524,7 +520,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent); throw new ArgumentException(Resources.ArgumentReferenceDifferent);
} }
SafeNativeMethods.s_cholesky_solve(orderA, columnsB, a, b); SafeNativeMethods.s_cholesky_solve(orderA, columnsB, a, b);
} }
/// <summary> /// <summary>
@ -548,7 +544,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("b"); throw new ArgumentNullException("b");
} }
if (b.Length != orderA * columnsB) if (b.Length != orderA*columnsB)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
} }
@ -558,7 +554,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentReferenceDifferent); throw new ArgumentException(Resources.ArgumentReferenceDifferent);
} }
SafeNativeMethods.s_cholesky_solve_factored(orderA, columnsB, a, b); SafeNativeMethods.s_cholesky_solve_factored(orderA, columnsB, a, b);
} }
/// <summary> /// <summary>
@ -586,7 +582,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("q"); throw new ArgumentNullException("q");
} }
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");
} }
@ -596,12 +592,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau"); 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"); 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); 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"); throw new ArgumentNullException("work");
} }
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");
} }
@ -648,14 +644,14 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(string.Format(Resources.ArrayTooSmall, "min(m,n)"), "tau"); 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"); 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"); throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
} }
@ -676,7 +672,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
[SecuritySafeCritical] [SecuritySafeCritical]
public override void QRSolve(float[] a, int rows, int columns, float[] b, int columnsB, float[] x, QRMethod method = QRMethod.Full) 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); QRSolve(a, rows, columns, b, columnsB, x, work, method);
} }
@ -717,17 +713,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("work"); throw new ArgumentNullException("work");
} }
if (a.Length != rows * columns) if (a.Length != rows*columns)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "a"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "a");
} }
if (b.Length != rows * columnsB) if (b.Length != rows*columnsB)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
} }
if (x.Length != columns * columnsB) if (x.Length != columns*columnsB)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "x"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "x");
} }
@ -739,7 +735,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
if (work.Length < 1) if (work.Length < 1)
{ {
work[0] = rows * Control.BlockSize; work[0] = rows*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work"); throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
} }
@ -763,7 +759,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
[SecuritySafeCritical] [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) 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); 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; 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) if (work.Length < 1)
{ {
work[0] = rowsA * Control.BlockSize; work[0] = rowsA*Control.BlockSize;
throw new ArgumentException(Resources.WorkArrayTooSmall, "work"); throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
} }
@ -899,12 +895,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("vt"); throw new ArgumentNullException("vt");
} }
if (u.Length != rowsA * rowsA) if (u.Length != rowsA*rowsA)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
} }
if (vt.Length != columnsA * columnsA) if (vt.Length != columnsA*columnsA)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
} }
@ -914,7 +910,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentArraysSameLength, "s"); 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); SingularValueDecomposition(computeVectors, a, rowsA, columnsA, s, u, vt, work);
} }
@ -944,20 +940,20 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("x"); throw new ArgumentNullException("x");
} }
if (b.Length != rowsA * columnsB) if (b.Length != rowsA*columnsB)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "b");
} }
if (x.Length != columnsA * columnsB) if (x.Length != columnsA*columnsB)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "b"); 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 s = new float[Math.Min(rowsA, columnsA)];
var u = new float[rowsA * rowsA]; var u = new float[rowsA*rowsA];
var vt = new float[columnsA * columnsA]; var vt = new float[columnsA*columnsA];
var clone = new float[a.Length]; var clone = new float[a.Length];
a.Copy(clone); a.Copy(clone);
@ -1009,12 +1005,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentNullException("work"); throw new ArgumentNullException("work");
} }
if (u.Length != rowsA * rowsA) if (u.Length != rowsA*rowsA)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "u"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "u");
} }
if (vt.Length != columnsA * columnsA) if (vt.Length != columnsA*columnsA)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt"); throw new ArgumentException(Resources.ArgumentArraysSameLength, "vt");
} }
@ -1029,9 +1025,9 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
throw new ArgumentException(Resources.ArgumentSingleDimensionArray, "work"); 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"); throw new ArgumentException(Resources.WorkArrayTooSmall, "work");
} }
@ -1064,7 +1060,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength); throw new ArgumentException(Resources.ArgumentArraysSameLength);
} }
if (x.Length != result.Length) if (x.Length != result.Length)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength); throw new ArgumentException(Resources.ArgumentArraysSameLength);
@ -1099,12 +1095,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength); throw new ArgumentException(Resources.ArgumentArraysSameLength);
} }
if (x.Length != result.Length) if (x.Length != result.Length)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength); throw new ArgumentException(Resources.ArgumentArraysSameLength);
} }
SafeNativeMethods.s_vector_subtract(x.Length, x, y, result); SafeNativeMethods.s_vector_subtract(x.Length, x, y, result);
} }
@ -1134,12 +1130,12 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength); throw new ArgumentException(Resources.ArgumentArraysSameLength);
} }
if (x.Length != result.Length) if (x.Length != result.Length)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength); throw new ArgumentException(Resources.ArgumentArraysSameLength);
} }
SafeNativeMethods.s_vector_multiply(x.Length, x, y, result); SafeNativeMethods.s_vector_multiply(x.Length, x, y, result);
} }
@ -1169,13 +1165,67 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength); throw new ArgumentException(Resources.ArgumentArraysSameLength);
} }
if (x.Length != result.Length) if (x.Length != result.Length)
{ {
throw new ArgumentException(Resources.ArgumentArraysSameLength); throw new ArgumentException(Resources.ArgumentArraysSameLength);
} }
SafeNativeMethods.s_vector_divide(x.Length, x, y, result); 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 // Math.NET Numerics, part of the Math.NET Project
// http://mathnet.opensourcedotnet.info // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // 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)] [DllImport(DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
internal static extern int z_svd_factor(bool computeVectors, int m, int n, [In, Out] Complex[] a, [In, Out] Complex[] s, [In, Out] Complex[] u, [In, Out] Complex[] v, [In, Out] Complex[] work, int len); internal static extern int z_svd_factor(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 #endregion LAPACK
#region Vector Functions #region Vector Functions

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

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // 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 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
// </copyright> // </copyright>
namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
{ {
using System; using System;
using System.Numerics;
using Generic; using Generic;
using Properties; using Properties;
/// <summary> /// <summary>
/// Eigenvalues and eigenvectors of a complex matrix. /// Eigenvalues and eigenvectors of a complex matrix.
/// </summary> /// </summary>
@ -72,45 +72,23 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
var order = matrix.RowCount; var order = matrix.RowCount;
// Initialize matricies for eigenvalues and eigenvectors // Initialize matrices for eigenvalues and eigenvectors
MatrixEv = DenseMatrix.Identity(order); MatrixEv = DenseMatrix.Identity(order);
MatrixD = matrix.CreateMatrix(order, order); MatrixD = matrix.CreateMatrix(order, order);
VectorEv = new DenseVector(order); VectorEv = new DenseVector(order);
IsSymmetric = true; 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(); IsSymmetric &= matrix.At(i, j) == matrix.At(j, i).Conjugate();
} }
} }
if (IsSymmetric) Control.LinearAlgebraProvider.EigenDecomp(IsSymmetric, order, matrix.Values, ((DenseMatrix) MatrixEv).Values,
{ ((DenseVector) VectorEv).Values, ((DenseMatrix) MatrixD).Values);
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);
} }
/// <summary> /// <summary>
@ -125,14 +103,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// Smith, Boyle, Dongarra, Garbow, Ikebe, Klema, Moler, and Wilkinson, Handbook for /// Smith, Boyle, Dongarra, Garbow, Ikebe, Klema, Moler, and Wilkinson, Handbook for
/// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding /// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
/// Fortran subroutine in EISPACK.</remarks> /// 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; double hh;
tau[order - 1] = Complex.One; tau[order - 1] = System.Numerics.Complex.One;
for (var i = 0; i < order; i++) 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. // Householder reduction to tridiagonal form.
@ -144,95 +122,96 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
for (var k = 0; k < i; k++) 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) if (scale == 0.0)
{ {
tau[i - 1] = Complex.One; tau[i - 1] = System.Numerics.Complex.One;
e[i] = 0.0; e[i] = 0.0;
} }
else else
{ {
for (var k = 0; k < i; k++) for (var k = 0; k < i; k++)
{ {
matrixA[i, k] /= scale; matrixA[k*order + i] /= scale;
h += matrixA[i, k].MagnitudeSquared(); h += matrixA[k*order + i].MagnitudeSquared();
} }
Complex g = Math.Sqrt(h); System.Numerics.Complex g = Math.Sqrt(h);
e[i] = scale * g.Real; e[i] = scale*g.Real;
Complex temp; System.Numerics.Complex temp;
var f = matrixA[i, i - 1]; var im1Oi = (i - 1)*order + i;
var f = matrixA[im1Oi];
if (f.Magnitude != 0) if (f.Magnitude != 0)
{ {
temp = -(matrixA[i, i - 1].Conjugate() * tau[i].Conjugate()) / f.Magnitude; temp = -(matrixA[im1Oi].Conjugate()*tau[i].Conjugate())/f.Magnitude;
h += f.Magnitude * g.Real; h += f.Magnitude*g.Real;
g = 1.0 + (g / f.Magnitude); g = 1.0 + (g/f.Magnitude);
matrixA[i, i - 1] *= g; matrixA[im1Oi] *= g;
} }
else else
{ {
temp = -tau[i].Conjugate(); temp = -tau[i].Conjugate();
matrixA[i, i - 1] = g; matrixA[im1Oi] = g;
} }
if ((f.Magnitude == 0) || (i != 1)) if ((f.Magnitude == 0) || (i != 1))
{ {
f = Complex.Zero; f = System.Numerics.Complex.Zero;
for (var j = 0; j < i; j++) 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. // Form element of A*U.
for (var k = 0; k <= j; k++) 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++) 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 // Form element of P
tau[j] = tmp / h; tau[j] = tmp/h;
f += (tmp / h) * matrixA[i, j]; f += (tmp/h)*matrixA[jO + i];
} }
hh = f.Real / (h + h); hh = f.Real/(h + h);
// Form the reduced A. // Form the reduced A.
for (var j = 0; j < i; j++) for (var j = 0; j < i; j++)
{ {
f = matrixA[i, j].Conjugate(); f = matrixA[j*order + i].Conjugate();
g = tau[j] - (hh * f); g = tau[j] - (hh*f);
tau[j] = g.Conjugate(); tau[j] = g.Conjugate();
for (var k = 0; k <= j; k++) 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++) for (var k = 0; k < i; k++)
{ {
matrixA[i, k] *= scale; matrixA[k*order + i] *= scale;
} }
tau[i - 1] = temp.Conjugate(); tau[i - 1] = temp.Conjugate();
} }
hh = d[i]; hh = d[i];
d[i] = matrixA[i, i].Real; d[i] = matrixA[i*order + i].Real;
matrixA[i, i] = new Complex(hh, scale * Math.Sqrt(h)); matrixA[i*order + i] = new System.Numerics.Complex(hh, scale*Math.Sqrt(h));
} }
hh = d[0]; hh = d[0];
d[0] = matrixA[0, 0].Real; d[0] = matrixA[0].Real;
matrixA[0, 0] = hh; matrixA[0] = hh;
e[0] = 0.0; e[0] = 0.0;
} }
@ -247,7 +226,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// Bowdler, Martin, Reinsch, and Wilkinson, Handbook for /// Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
/// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding /// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
/// Fortran subroutine in EISPACK.</remarks> /// 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; const int Maxiter = 1000;
@ -268,7 +247,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
var m = l; var m = l;
while (m < order) while (m < order)
{ {
if (Math.Abs(e[m]) <= eps * tst1) if (Math.Abs(e[m]) <= eps*tst1)
{ {
break; break;
} }
@ -287,15 +266,15 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
// Compute implicit shift // Compute implicit shift
var g = d[l]; 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); var r = SpecialFunctions.Hypotenuse(p, 1.0);
if (p < 0) if (p < 0)
{ {
r = -r; r = -r;
} }
d[l] = e[l] / (p + r); d[l] = e[l]/(p + r);
d[l + 1] = e[l] * (p + r); d[l + 1] = e[l]*(p + r);
var dl1 = d[l + 1]; var dl1 = d[l + 1];
var h = g - d[l]; var h = g - d[l];
@ -319,27 +298,27 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
c3 = c2; c3 = c2;
c2 = c; c2 = c;
s2 = s; s2 = s;
g = c * e[i]; g = c*e[i];
h = c * p; h = c*p;
r = SpecialFunctions.Hypotenuse(p, e[i]); r = SpecialFunctions.Hypotenuse(p, e[i]);
e[i + 1] = s * r; e[i + 1] = s*r;
s = e[i] / r; s = e[i]/r;
c = p / r; c = p/r;
p = (c * d[i]) - (s * g); p = (c*d[i]) - (s*g);
d[i + 1] = h + (s * ((c * g) + (s * d[i]))); d[i + 1] = h + (s*((c*g) + (s*d[i])));
// Accumulate transformation. // Accumulate transformation.
for (var k = 0; k < order; k++) for (var k = 0; k < order; k++)
{ {
h = dataEv[((i + 1) * order) + k].Real; h = dataEv[((i + 1)*order) + k].Real;
dataEv[((i + 1) * order) + k] = (s * dataEv[(i * order) + k].Real) + (c * h); 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); dataEv[(i*order) + k] = (c*dataEv[(i*order) + k].Real) - (s*h);
} }
} }
p = (-s) * s2 * c3 * el1 * e[l] / dl1; p = (-s)*s2*c3*el1*e[l]/dl1;
e[l] = s * p; e[l] = s*p;
d[l] = c * p; d[l] = c*p;
// Check for convergence. If too many iterations have been performed, // Check for convergence. If too many iterations have been performed,
// throw exception that Convergence Failed // throw exception that Convergence Failed
@ -347,8 +326,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
{ {
throw new ArgumentException(Resources.ConvergenceFailed); throw new ArgumentException(Resources.ConvergenceFailed);
} }
} } while (Math.Abs(e[l]) > eps*tst1);
while (Math.Abs(e[l]) > eps * tst1);
} }
d[l] = d[l] + f; d[l] = d[l] + f;
@ -375,9 +353,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
d[i] = p; d[i] = p;
for (var j = 0; j < order; j++) for (var j = 0; j < order; j++)
{ {
p = dataEv[(i * order) + j].Real; p = dataEv[(i*order) + j].Real;
dataEv[(i * order) + j] = dataEv[(k * order) + j]; dataEv[(i*order) + j] = dataEv[(k*order) + j];
dataEv[(k * order) + j] = p; 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 /// by Smith, Boyle, Dongarra, Garbow, Ikebe, Klema, Moler, and Wilkinson, Handbook for
/// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding /// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
/// Fortran subroutine in EISPACK.</remarks> /// 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 i = 0; i < order; i++)
{ {
for (var j = 0; j < order; j++) 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. // Recover and apply the Householder matrices.
for (var i = 1; i < order; i++) for (var i = 1; i < order; i++)
{ {
var h = matrixA[i, i].Imaginary; var h = matrixA[i*order + i].Imaginary;
if (h != 0) if (h != 0)
{ {
for (var j = 0; j < order; j++) for (var j = 0; j < order; j++)
{ {
var s = Complex.Zero; var s = System.Numerics.Complex.Zero;
for (var k = 0; k < i; k++) 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++) 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., /// by Martin and Wilkinson, Handbook for Auto. Comp.,
/// Vol.ii-Linear Algebra, and the corresponding /// Vol.ii-Linear Algebra, and the corresponding
/// Fortran subroutines in EISPACK.</remarks> /// 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++) for (var m = 1; m < order - 1; m++)
{ {
// Scale column. // Scale column.
var scale = 0.0; var scale = 0.0;
var mm1O = (m - 1)*order;
for (var i = m; i < order; i++) 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) if (scale != 0.0)
@ -458,57 +437,58 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
var h = 0.0; var h = 0.0;
for (var i = order - 1; i >= m; i--) 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(); h += ort[i].MagnitudeSquared();
} }
var g = Math.Sqrt(h); var g = Math.Sqrt(h);
if (ort[m].Magnitude != 0) if (ort[m].Magnitude != 0)
{ {
h = h + (ort[m].Magnitude * g); h = h + (ort[m].Magnitude*g);
g /= ort[m].Magnitude; g /= ort[m].Magnitude;
ort[m] = (1.0 + g) * ort[m]; ort[m] = (1.0 + g)*ort[m];
} }
else else
{ {
ort[m] = g; ort[m] = g;
matrixH[m, m - 1] = scale; matrixH[mm1O + m] = scale;
} }
// Apply Householder similarity transformation // Apply Householder similarity transformation
// H = (I-u*u'/h)*H*(I-u*u')/h) // H = (I-u*u'/h)*H*(I-u*u')/h)
for (var j = m; j < order; j++) 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--) 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++) 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++) 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--) 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++) 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]; ort[m] = scale*ort[m];
matrixH[m, m - 1] *= -g; matrixH[mm1O + m] *= -g;
} }
} }
@ -517,59 +497,65 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
{ {
for (var j = 0; j < order; j++) 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--) 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++) 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++) for (var j = m; j < order; j++)
{ {
var g = Complex.Zero; var g = System.Numerics.Complex.Zero;
for (var i = m; i < order; i++) 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 // Double division avoids possible underflow
g /= norm; g /= norm;
for (var i = m; i < order; i++) 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. // Create real subdiagonal elements.
for (var i = 1; i < order; i++) 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; var y = matrixH[im1Oi]/matrixH[im1Oi].Magnitude;
matrixH[i, i - 1] = matrixH[i, i - 1].Magnitude; matrixH[im1Oi] = matrixH[im1Oi].Magnitude;
for (var j = i; j < order; j++) 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++) 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++) 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., /// by Martin and Wilkinson, Handbook for Auto. Comp.,
/// Vol.ii-Linear Algebra, and the corresponding /// Vol.ii-Linear Algebra, and the corresponding
/// Fortran subroutine in EISPACK.</remarks> /// 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 // Initialize
var n = order - 1; var n = order - 1;
var eps = Precision.DoubleMachinePrecision; var eps = Precision.DoubleMachinePrecision;
double norm; 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 // Outer loop over eigenvalue index
var iter = 0; var iter = 0;
@ -603,8 +589,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
var l = n; var l = n;
while (l > 0) 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); var lm1 = l - 1;
if (Math.Abs(matrixH[l, l - 1].Real) < eps * tst1) 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; break;
} }
@ -612,46 +601,50 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
l--; l--;
} }
var nm1 = n - 1;
var nm1O = nm1*order;
var nO = n*order;
var nOn = nO + n;
// Check for convergence // Check for convergence
// One root found // One root found
if (l == n) if (l == n)
{ {
matrixH[n, n] += exshift; matrixH[nOn] += exshift;
vectorV[n] = matrixH[n, n]; vectorV[n] = matrixH[nOn];
n--; n--;
iter = 0; iter = 0;
} }
else else
{ {
// Form shift // Form shift
Complex s; System.Numerics.Complex s;
if (iter != 10 && iter != 20) if (iter != 10 && iter != 20)
{ {
s = matrixH[n, n]; s = matrixH[nOn];
x = matrixH[n - 1, n] * matrixH[n, n - 1].Real; x = matrixH[nO + nm1]*matrixH[nm1O + n].Real;
if (x.Real != 0.0 || x.Imaginary != 0.0) if (x.Real != 0.0 || x.Imaginary != 0.0)
{ {
y = (matrixH[n - 1, n - 1] - s) / 2.0; y = (matrixH[nm1O + nm1] - s)/2.0;
z = ((y * y) + x).SquareRoot(); z = ((y*y) + x).SquareRoot();
if ((y.Real * z.Real) + (y.Imaginary * z.Imaginary) < 0.0) if ((y.Real*z.Real) + (y.Imaginary*z.Imaginary) < 0.0)
{ {
z *= -1.0; z *= -1.0;
} }
x /= y + z; x /= y + z;
s = s - x; s = s - x;
} }
} }
else else
{ {
// Form exceptional shift // 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++) for (var i = 0; i <= n; i++)
{ {
matrixH[i, i] -= s; matrixH[i*order + i] -= s;
} }
exshift += s; exshift += s;
@ -660,31 +653,35 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
// Reduce to triangle (rows) // Reduce to triangle (rows)
for (var i = l + 1; i <= n; i++) for (var i = l + 1; i <= n; i++)
{ {
s = matrixH[i, i - 1].Real; var im1 = i - 1;
norm = SpecialFunctions.Hypotenuse(matrixH[i - 1, i - 1].Magnitude, s.Real); var im1O = im1*order;
x = matrixH[i - 1, i - 1] / norm; 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; vectorV[i - 1] = x;
matrixH[i - 1, i - 1] = norm; matrixH[im1Oim1] = norm;
matrixH[i, i - 1] = new Complex(0.0, s.Real / norm); matrixH[im1O + i] = new System.Numerics.Complex(0.0, s.Real/norm);
for (var j = i; j < order; j++) for (var j = i; j < order; j++)
{ {
y = matrixH[i - 1, j]; var jO = j*order;
z = matrixH[i, j]; y = matrixH[jO + im1];
matrixH[i - 1, j] = (x.Conjugate() * y) + (matrixH[i, i - 1].Imaginary * z); z = matrixH[jO + i];
matrixH[i, j] = (x * z) - (matrixH[i, i - 1].Imaginary * y); 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) if (s.Imaginary != 0.0)
{ {
s /= matrixH[n, n].Magnitude; s /= matrixH[nOn].Magnitude;
matrixH[n, n] = matrixH[n, n].Magnitude; matrixH[nOn] = matrixH[nOn].Magnitude;
for (var j = n + 1; j < order; j++) 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++) for (var j = l + 1; j <= n; j++)
{ {
x = 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++) for (var i = 0; i <= j; i++)
{ {
z = matrixH[i, j]; var jm1Oi = jm1O + i;
z = matrixH[jO + i];
if (i != j) if (i != j)
{ {
y = matrixH[i, j - 1]; y = matrixH[jm1Oi];
matrixH[i, j - 1] = (x * y) + (matrixH[j, j - 1].Imaginary * z); matrixH[jm1Oi] = (x*y) + (matrixH[jm1O + j].Imaginary*z);
} }
else else
{ {
y = matrixH[i, j - 1].Real; y = matrixH[jm1Oi].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); 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++) for (var i = 0; i < order; i++)
{ {
y = dataEv[((j - 1) * order) + i]; y = dataEv[((j - 1)*order) + i];
z = dataEv[(j * order) + i]; z = dataEv[(j*order) + i];
dataEv[((j - 1) * order) + i] = (x * y) + (matrixH[j, j - 1].Imaginary * z); dataEv[jm1O + i] = (x*y) + (matrixH[jm1Oj].Imaginary*z);
dataEv[(j * order) + i] = (x.Conjugate() * z) - (matrixH[j, j - 1].Imaginary * y); 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++) for (var i = 0; i <= n; i++)
{ {
matrixH[i, n] *= s; matrixH[nO + i] *= s;
} }
for (var i = 0; i < order; i++) 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++) 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--) for (n = order - 1; n > 0; n--)
{ {
var nO = n*order;
var nOn = nO + n;
x = vectorV[n]; x = vectorV[n];
matrixH[n, n] = 1.0; matrixH[nOn] = 1.0;
for (var i = n - 1; i >= 0; i--) for (var i = n - 1; i >= 0; i--)
{ {
z = 0.0; z = 0.0;
for (var j = i + 1; j <= n; j++) 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]; y = x - vectorV[i];
if (y.Real == 0.0 && y.Imaginary == 0.0) 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 // Overflow control
var tr = Math.Abs(matrixH[i, n].Real) + Math.Abs(matrixH[i, n].Imaginary); var tr = Math.Abs(matrixH[nO + i].Real) + Math.Abs(matrixH[nO + i].Imaginary);
if ((eps * tr) * tr > 1) if ((eps*tr)*tr > 1)
{ {
for (var j = i; j <= n; j++) 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 // Back transformation to get eigenvectors of original matrix
for (var j = order - 1; j > 0; j--) for (var j = order - 1; j > 0; j--)
{ {
var jO = j*order;
for (var i = 0; i < order; i++) for (var i = 0; i < order; i++)
{ {
z = Complex.Zero; z = System.Numerics.Complex.Zero;
for (var k = 0; k <= j; k++) 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> /// <summary>
/// Solves a system of linear equations, <b>AX = B</b>, with A SVD factorized. /// Solves a system of linear equations, <b>AX = B</b>, with A SVD factorized.
/// </summary> /// </summary>
/// <param name="input">The right hand side <see cref="Matrix{T}"/>, <b>B</b>.</param> /// <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> /// <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. // Check for proper arguments.
if (input == null) if (input == null)
@ -842,18 +847,18 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
if (IsSymmetric) if (IsSymmetric)
{ {
var order = VectorEv.Count; 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 k = 0; k < order; k++)
{ {
for (var j = 0; j < order; j++) for (var j = 0; j < order; j++)
{ {
Complex value = 0.0; System.Numerics.Complex value = 0.0;
if (j < order) if (j < order)
{ {
for (var i = 0; i < order; i++) 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; value /= VectorEv[j].Real;
@ -864,10 +869,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
for (var j = 0; j < order; j++) for (var j = 0; j < order; j++)
{ {
Complex value = 0.0; System.Numerics.Complex value = 0.0;
for (var 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.At(j, k, value); result.At(j, k, value);
@ -876,7 +881,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
} }
else else
{ {
throw new ArgumentException(Resources.ArgumentMatrixSymmetric); throw new ArgumentException(Resources.ArgumentMatrixSymmetric);
} }
} }
@ -885,7 +890,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// </summary> /// </summary>
/// <param name="input">The right hand side vector, <b>b</b>.</param> /// <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> /// <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) if (input == null)
{ {
@ -914,8 +919,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
{ {
// Symmetric case -> x = V * inv(λ) * VH * b; // Symmetric case -> x = V * inv(λ) * VH * b;
var order = VectorEv.Count; var order = VectorEv.Count;
var tmp = new Complex[order]; var tmp = new System.Numerics.Complex[order];
Complex value; System.Numerics.Complex value;
for (var j = 0; j < order; j++) for (var j = 0; j < order; j++)
{ {
@ -924,7 +929,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
{ {
for (var i = 0; i < order; i++) 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; value /= VectorEv[j].Real;
@ -936,9 +941,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
for (var j = 0; j < order; j++) for (var j = 0; j < order; j++)
{ {
value = 0; 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; 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; 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(); 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://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // 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 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
// </copyright> // </copyright>
namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
{ {
using System; using System;
using System.Numerics;
using Generic; using Generic;
using Numerics;
using Properties; using Properties;
/// <summary> /// <summary>
@ -73,48 +73,23 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
var order = matrix.RowCount; var order = matrix.RowCount;
// Initialize matricies for eigenvalues and eigenvectors // Initialize matrices for eigenvalues and eigenvectors
MatrixEv = DenseMatrix.Identity(order); MatrixEv = DenseMatrix.Identity(order);
MatrixD = matrix.CreateMatrix(order, order); MatrixD = matrix.CreateMatrix(order, order);
VectorEv = new LinearAlgebra.Complex.DenseVector(order); VectorEv = new Complex.DenseVector(order);
IsSymmetric = true; 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(); IsSymmetric &= matrix.At(i, j) == matrix.At(j, i).Conjugate();
} }
} }
if (IsSymmetric) Control.LinearAlgebraProvider.EigenDecomp(IsSymmetric, order, matrix.Values, ((DenseMatrix) MatrixEv).Values,
{ ((Complex.DenseVector) VectorEv).Values, ((DenseMatrix) MatrixD).Values);
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]);
}
} }
/// <summary> /// <summary>
@ -129,14 +104,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// Smith, Boyle, Dongarra, Garbow, Ikebe, Klema, Moler, and Wilkinson, Handbook for /// Smith, Boyle, Dongarra, Garbow, Ikebe, Klema, Moler, and Wilkinson, Handbook for
/// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding /// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
/// Fortran subroutine in EISPACK.</remarks> /// 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; float hh;
tau[order - 1] = Complex32.One; tau[order - 1] = Numerics.Complex32.One;
for (var i = 0; i < order; i++) 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. // Householder reduction to tridiagonal form.
@ -148,95 +123,96 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
for (var k = 0; k < i; k++) 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) if (scale == 0.0f)
{ {
tau[i - 1] = Complex32.One; tau[i - 1] = Numerics.Complex32.One;
e[i] = 0.0f; e[i] = 0.0f;
} }
else else
{ {
for (var k = 0; k < i; k++) for (var k = 0; k < i; k++)
{ {
matrixA[i, k] /= scale; matrixA[k*order + i] /= scale;
h += matrixA[i, k].MagnitudeSquared; h += matrixA[k*order + i].MagnitudeSquared;
} }
Complex32 g = (float)Math.Sqrt(h); Numerics.Complex32 g = (float) Math.Sqrt(h);
e[i] = scale * g.Real; e[i] = scale*g.Real;
Complex32 temp; Numerics.Complex32 temp;
var f = matrixA[i, i - 1]; var im1Oi = (i - 1)*order + i;
if (f.Magnitude != 0) var f = matrixA[im1Oi];
if (f.Magnitude != 0.0f)
{ {
temp = -(matrixA[i, i - 1].Conjugate() * tau[i].Conjugate()) / f.Magnitude; temp = -(matrixA[im1Oi].Conjugate()*tau[i].Conjugate())/f.Magnitude;
h += f.Magnitude * g.Real; h += f.Magnitude*g.Real;
g = 1.0f + (g / f.Magnitude); g = 1.0f + (g/f.Magnitude);
matrixA[i, i - 1] *= g; matrixA[im1Oi] *= g;
} }
else else
{ {
temp = -tau[i].Conjugate(); 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++) 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. // Form element of A*U.
for (var k = 0; k <= j; k++) 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++) 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 // Form element of P
tau[j] = tmp / h; tau[j] = tmp/h;
f += (tmp / h) * matrixA[i, j]; f += (tmp/h)*matrixA[jO + i];
} }
hh = f.Real / (h + h); hh = f.Real/(h + h);
// Form the reduced A. // Form the reduced A.
for (var j = 0; j < i; j++) for (var j = 0; j < i; j++)
{ {
f = matrixA[i, j].Conjugate(); f = matrixA[j*order + i].Conjugate();
g = tau[j] - (hh * f); g = tau[j] - (hh*f);
tau[j] = g.Conjugate(); tau[j] = g.Conjugate();
for (var k = 0; k <= j; k++) 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++) for (var k = 0; k < i; k++)
{ {
matrixA[i, k] *= scale; matrixA[k*order + i] *= scale;
} }
tau[i - 1] = temp.Conjugate(); tau[i - 1] = temp.Conjugate();
} }
hh = d[i]; hh = d[i];
d[i] = matrixA[i, i].Real; d[i] = matrixA[i*order + i].Real;
matrixA[i, i] = new Complex32(hh, scale * (float)Math.Sqrt(h)); matrixA[i*order + i] = new Numerics.Complex32(hh, scale*(float) Math.Sqrt(h));
} }
hh = d[0]; hh = d[0];
d[0] = matrixA[0, 0].Real; d[0] = matrixA[0].Real;
matrixA[0, 0] = hh; matrixA[0] = hh;
e[0] = 0.0f; e[0] = 0.0f;
} }
@ -251,7 +227,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// Bowdler, Martin, Reinsch, and Wilkinson, Handbook for /// Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
/// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding /// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
/// Fortran subroutine in EISPACK.</remarks> /// 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; const int Maxiter = 1000;
@ -272,7 +248,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
var m = l; var m = l;
while (m < order) while (m < order)
{ {
if (Math.Abs(e[m]) <= eps * tst1) if (Math.Abs(e[m]) <= eps*tst1)
{ {
break; break;
} }
@ -291,15 +267,15 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
// Compute implicit shift // Compute implicit shift
var g = d[l]; 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); var r = SpecialFunctions.Hypotenuse(p, 1.0f);
if (p < 0) if (p < 0)
{ {
r = -r; r = -r;
} }
d[l] = e[l] / (p + r); d[l] = e[l]/(p + r);
d[l + 1] = e[l] * (p + r); d[l + 1] = e[l]*(p + r);
var dl1 = d[l + 1]; var dl1 = d[l + 1];
var h = g - d[l]; var h = g - d[l];
@ -323,27 +299,27 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
c3 = c2; c3 = c2;
c2 = c; c2 = c;
s2 = s; s2 = s;
g = c * e[i]; g = c*e[i];
h = c * p; h = c*p;
r = SpecialFunctions.Hypotenuse(p, e[i]); r = SpecialFunctions.Hypotenuse(p, e[i]);
e[i + 1] = s * r; e[i + 1] = s*r;
s = e[i] / r; s = e[i]/r;
c = p / r; c = p/r;
p = (c * d[i]) - (s * g); p = (c*d[i]) - (s*g);
d[i + 1] = h + (s * ((c * g) + (s * d[i]))); d[i + 1] = h + (s*((c*g) + (s*d[i])));
// Accumulate transformation. // Accumulate transformation.
for (var k = 0; k < order; k++) for (var k = 0; k < order; k++)
{ {
h = dataEv[((i + 1) * order) + k].Real; h = dataEv[((i + 1)*order) + k].Real;
dataEv[((i + 1) * order) + k] = (s * dataEv[(i * order) + k].Real) + (c * h); 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); dataEv[(i*order) + k] = (c*dataEv[(i*order) + k].Real) - (s*h);
} }
} }
p = (-s) * s2 * c3 * el1 * e[l] / dl1; p = (-s)*s2*c3*el1*e[l]/dl1;
e[l] = s * p; e[l] = s*p;
d[l] = c * p; d[l] = c*p;
// Check for convergence. If too many iterations have been performed, // Check for convergence. If too many iterations have been performed,
// throw exception that Convergence Failed // throw exception that Convergence Failed
@ -351,8 +327,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
{ {
throw new ArgumentException(Resources.ConvergenceFailed); throw new ArgumentException(Resources.ConvergenceFailed);
} }
} } while (Math.Abs(e[l]) > eps*tst1);
while (Math.Abs(e[l]) > eps * tst1);
} }
d[l] = d[l] + f; d[l] = d[l] + f;
@ -379,9 +354,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
d[i] = p; d[i] = p;
for (var j = 0; j < order; j++) for (var j = 0; j < order; j++)
{ {
p = dataEv[(i * order) + j].Real; p = dataEv[(i*order) + j].Real;
dataEv[(i * order) + j] = dataEv[(k * order) + j]; dataEv[(i*order) + j] = dataEv[(k*order) + j];
dataEv[(k * order) + j] = p; 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 /// by Smith, Boyle, Dongarra, Garbow, Ikebe, Klema, Moler, and Wilkinson, Handbook for
/// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding /// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
/// Fortran subroutine in EISPACK.</remarks> /// 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 i = 0; i < order; i++)
{ {
for (var j = 0; j < order; j++) 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. // Recover and apply the Householder matrices.
for (var i = 1; i < order; i++) for (var i = 1; i < order; i++)
{ {
var h = matrixA[i, i].Imaginary; var h = matrixA[i*order + i].Imaginary;
if (h != 0) if (h != 0)
{ {
for (var j = 0; j < order; j++) for (var j = 0; j < order; j++)
{ {
var s = Complex32.Zero; var s = Numerics.Complex32.Zero;
for (var k = 0; k < i; k++) 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++) 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., /// by Martin and Wilkinson, Handbook for Auto. Comp.,
/// Vol.ii-Linear Algebra, and the corresponding /// Vol.ii-Linear Algebra, and the corresponding
/// Fortran subroutines in EISPACK.</remarks> /// 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++) for (var m = 1; m < order - 1; m++)
{ {
// Scale column. // Scale column.
var scale = 0.0f; var scale = 0.0f;
var mm1O = (m - 1)*order;
for (var i = m; i < order; i++) 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) if (scale != 0.0f)
@ -462,57 +438,58 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
var h = 0.0f; var h = 0.0f;
for (var i = order - 1; i >= m; i--) 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; h += ort[i].MagnitudeSquared;
} }
var g = (float)Math.Sqrt(h); var g = (float) Math.Sqrt(h);
if (ort[m].Magnitude != 0) if (ort[m].Magnitude != 0)
{ {
h = h + (ort[m].Magnitude * g); h = h + (ort[m].Magnitude*g);
g /= ort[m].Magnitude; g /= ort[m].Magnitude;
ort[m] = (1.0f + g) * ort[m]; ort[m] = (1.0f + g)*ort[m];
} }
else else
{ {
ort[m] = g; ort[m] = g;
matrixH[m, m - 1] = scale; matrixH[mm1O + m] = scale;
} }
// Apply Householder similarity transformation // Apply Householder similarity transformation
// H = (I-u*u'/h)*H*(I-u*u')/h) // H = (I-u*u'/h)*H*(I-u*u')/h)
for (var j = m; j < order; j++) 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--) 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++) 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++) for (var i = 0; i < order; i++)
{ {
var f = Complex32.Zero; var f = Numerics.Complex32.Zero;
for (var j = order - 1; j >= m; j--) 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++) 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]; ort[m] = scale*ort[m];
matrixH[m, m - 1] *= -g; matrixH[mm1O + m] *= -g;
} }
} }
@ -521,59 +498,65 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
{ {
for (var j = 0; j < order; j++) 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--) 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++) 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++) for (var j = m; j < order; j++)
{ {
var g = Complex32.Zero; var g = Numerics.Complex32.Zero;
for (var i = m; i < order; i++) 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 // Double division avoids possible underflow
g /= norm; g /= norm;
for (var i = m; i < order; i++) 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. // Create real subdiagonal elements.
for (var i = 1; i < order; i++) 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; var y = matrixH[im1Oi]/matrixH[im1Oi].Magnitude;
matrixH[i, i - 1] = matrixH[i, i - 1].Magnitude; matrixH[im1Oi] = matrixH[im1Oi].Magnitude;
for (var j = i; j < order; j++) 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++) 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++) 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., /// by Martin and Wilkinson, Handbook for Auto. Comp.,
/// Vol.ii-Linear Algebra, and the corresponding /// Vol.ii-Linear Algebra, and the corresponding
/// Fortran subroutine in EISPACK.</remarks> /// 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 // Initialize
var n = order - 1; var n = order - 1;
var eps = (float)Precision.SingleMachinePrecision; var eps = (float) Precision.SingleMachinePrecision;
float norm; float norm;
Complex32 x, y, z, exshift = Complex32.Zero; Numerics.Complex32 x, y, z, exshift = Numerics.Complex32.Zero;
// Outer loop over eigenvalue index // Outer loop over eigenvalue index
var iter = 0; var iter = 0;
@ -607,8 +590,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
var l = n; var l = n;
while (l > 0) 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); var lm1 = l - 1;
if (Math.Abs(matrixH[l, l - 1].Real) < eps * tst1) 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; break;
} }
@ -616,46 +602,50 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
l--; l--;
} }
var nm1 = n - 1;
var nm1O = nm1*order;
var nO = n*order;
var nOn = nO + n;
// Check for convergence // Check for convergence
// One root found // One root found
if (l == n) if (l == n)
{ {
matrixH[n, n] += exshift; matrixH[nOn] += exshift;
vectorV[n] = matrixH[n, n].ToComplex(); vectorV[n] = matrixH[nOn];
n--; n--;
iter = 0; iter = 0;
} }
else else
{ {
// Form shift // Form shift
Complex32 s; Numerics.Complex32 s;
if (iter != 10 && iter != 20) if (iter != 10 && iter != 20)
{ {
s = matrixH[n, n]; s = matrixH[nOn];
x = matrixH[n - 1, n] * matrixH[n, n - 1].Real; x = matrixH[nO + nm1]*matrixH[nm1O + n].Real;
if (x.Real != 0.0f || x.Imaginary != 0.0f) if (x.Real != 0.0f || x.Imaginary != 0.0f)
{ {
y = (matrixH[n - 1, n - 1] - s) / 2.0f; y = (matrixH[nm1O + nm1] - s)/2.0f;
z = ((y * y) + x).SquareRoot(); z = ((y*y) + x).SquareRoot();
if ((y.Real * z.Real) + (y.Imaginary * z.Imaginary) < 0.0f) if ((y.Real*z.Real) + (y.Imaginary*z.Imaginary) < 0.0)
{ {
z *= -1.0f; z *= -1.0f;
} }
x /= y + z; x /= y + z;
s = s - x; s = s - x;
} }
} }
else else
{ {
// Form exceptional shift // 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++) for (var i = 0; i <= n; i++)
{ {
matrixH[i, i] -= s; matrixH[i*order + i] -= s;
} }
exshift += s; exshift += s;
@ -664,61 +654,70 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
// Reduce to triangle (rows) // Reduce to triangle (rows)
for (var i = l + 1; i <= n; i++) for (var i = l + 1; i <= n; i++)
{ {
s = matrixH[i, i - 1].Real; var im1 = i - 1;
norm = SpecialFunctions.Hypotenuse(matrixH[i - 1, i - 1].Magnitude, s.Real); var im1O = im1*order;
x = matrixH[i - 1, i - 1] / norm; var im1Oim1 = im1O + im1;
vectorV[i - 1] = x.ToComplex(); s = matrixH[im1O + i].Real;
matrixH[i - 1, i - 1] = norm; norm = SpecialFunctions.Hypotenuse(matrixH[im1Oim1].Magnitude, s.Real);
matrixH[i, i - 1] = new Complex32(0.0f, s.Real / norm); 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++) for (var j = i; j < order; j++)
{ {
y = matrixH[i - 1, j]; var jO = j*order;
z = matrixH[i, j]; y = matrixH[jO + im1];
matrixH[i - 1, j] = (x.Conjugate() * y) + (matrixH[i, i - 1].Imaginary * z); z = matrixH[jO + i];
matrixH[i, j] = (x * z) - (matrixH[i, i - 1].Imaginary * y); 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) if (s.Imaginary != 0.0f)
{ {
s /= matrixH[n, n].Magnitude; s /= matrixH[nOn].Magnitude;
matrixH[n, n] = matrixH[n, n].Magnitude; matrixH[nOn] = matrixH[nOn].Magnitude;
for (var j = n + 1; j < order; j++) for (var j = n + 1; j < order; j++)
{ {
matrixH[n, j] *= s.Conjugate(); matrixH[j*order + n] *= s.Conjugate();
} }
} }
// Inverse operation (columns). // Inverse operation (columns).
for (var j = l + 1; j <= n; j++) 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++) for (var i = 0; i <= j; i++)
{ {
z = matrixH[i, j]; var jm1Oi = jm1O + i;
z = matrixH[jO + i];
if (i != j) if (i != j)
{ {
y = matrixH[i, j - 1]; y = matrixH[jm1Oi];
matrixH[i, j - 1] = (x * y) + (matrixH[j, j - 1].Imaginary * z); matrixH[jm1Oi] = (x*y) + (matrixH[jm1O + j].Imaginary*z);
} }
else else
{ {
y = matrixH[i, j - 1].Real; y = matrixH[jm1Oi].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); 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++) for (var i = 0; i < order; i++)
{ {
y = dataEv[((j - 1) * order) + i]; y = dataEv[((j - 1)*order) + i];
z = dataEv[(j * order) + i]; z = dataEv[(j*order) + i];
dataEv[((j - 1) * order) + i] = (x * y) + (matrixH[j, j - 1].Imaginary * z); dataEv[jm1O + i] = (x*y) + (matrixH[jm1Oj].Imaginary*z);
dataEv[(j * order) + i] = (x.Conjugate() * z) - (matrixH[j, j - 1].Imaginary * y); 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++) for (var i = 0; i <= n; i++)
{ {
matrixH[i, n] *= s; matrixH[nO + i] *= s;
} }
for (var i = 0; i < order; i++) 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++) 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; return;
} }
if (norm == 0.0f) if (norm == 0.0)
{ {
return; return;
} }
for (n = order - 1; n > 0; n--) for (n = order - 1; n > 0; n--)
{ {
x = (Complex32)vectorV[n]; var nO = n*order;
matrixH[n, n] = 1.0f; var nOn = nO + n;
x = vectorV[n];
matrixH[nOn] = 1.0f;
for (var i = n - 1; i >= 0; i--) for (var i = n - 1; i >= 0; i--)
{ {
z = 0.0f; z = 0.0f;
for (var j = i + 1; j <= n; j++) 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) 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 // Overflow control
var tr = Math.Abs(matrixH[i, n].Real) + Math.Abs(matrixH[i, n].Imaginary); var tr = Math.Abs(matrixH[nO + i].Real) + Math.Abs(matrixH[nO + i].Imaginary);
if ((eps * tr) * tr > 1) if ((eps*tr)*tr > 1)
{ {
for (var j = i; j <= n; j++) 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 // Back transformation to get eigenvectors of original matrix
for (var j = order - 1; j > 0; j--) for (var j = order - 1; j > 0; j--)
{ {
var jO = j*order;
for (var i = 0; i < order; i++) for (var i = 0; i < order; i++)
{ {
z = Complex32.Zero; z = Numerics.Complex32.Zero;
for (var k = 0; k <= j; k++) 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> /// <summary>
/// Solves a system of linear equations, <b>AX = B</b>, with A SVD factorized. /// Solves a system of linear equations, <b>AX = B</b>, with A SVD factorized.
/// </summary> /// </summary>
/// <param name="input">The right hand side <see cref="Matrix{T}"/>, <b>B</b>.</param> /// <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> /// <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. // Check for proper arguments.
if (input == null) if (input == null)
@ -846,21 +848,21 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
if (IsSymmetric) if (IsSymmetric)
{ {
var order = VectorEv.Count; var order = VectorEv.Count;
var tmp = new Complex32[order]; var tmp = new Numerics.Complex32[order];
for (var k = 0; k < order; k++) for (var k = 0; k < order; k++)
{ {
for (var j = 0; j < order; j++) for (var j = 0; j < order; j++)
{ {
Complex32 value = 0.0f; Numerics.Complex32 value = 0.0f;
if (j < order) if (j < order)
{ {
for (var i = 0; i < order; i++) 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; tmp[j] = value;
@ -868,10 +870,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
for (var j = 0; j < order; j++) for (var j = 0; j < order; j++)
{ {
Complex32 value = 0.0f; Numerics.Complex32 value = 0.0f;
for (var 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.At(j, k, value); result.At(j, k, value);
@ -880,7 +882,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
} }
else else
{ {
throw new ArgumentException(Resources.ArgumentMatrixSymmetric); throw new ArgumentException(Resources.ArgumentMatrixSymmetric);
} }
} }
@ -889,7 +891,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// </summary> /// </summary>
/// <param name="input">The right hand side vector, <b>b</b>.</param> /// <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> /// <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) if (input == null)
{ {
@ -918,8 +920,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
{ {
// Symmetric case -> x = V * inv(λ) * VH * b; // Symmetric case -> x = V * inv(λ) * VH * b;
var order = VectorEv.Count; var order = VectorEv.Count;
var tmp = new Complex32[order]; var tmp = new Numerics.Complex32[order];
Complex32 value; Numerics.Complex32 value;
for (var j = 0; j < order; j++) for (var j = 0; j < order; j++)
{ {
@ -928,10 +930,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
{ {
for (var i = 0; i < order; i++) 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; tmp[j] = value;
@ -940,9 +942,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
for (var j = 0; j < order; j++) for (var j = 0; j < order; j++)
{ {
value = 0; 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; 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; 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(); 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; 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); 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; 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); 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 matrix = _matrices["Square3x3"];
var work = new float[18]; var work = new float[18];
var norm = Control.LinearAlgebraProvider.MatrixNorm(Norm.FrobeniusNorm, matrix.RowCount, matrix.ColumnCount, matrix.Values, work); 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> /// <summary>

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

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

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

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

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

@ -24,8 +24,6 @@
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
// </copyright> // </copyright>
using MathNet.Numerics.LinearAlgebra.Generic;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Factorization namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Factorization
{ {
using System; using System;
@ -128,7 +126,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Factorization
var factorEvd = matrixA.Evd(); var factorEvd = matrixA.Evd();
var eigenVectors = factorEvd.EigenVectors(); var eigenVectors = factorEvd.EigenVectors();
var d = factorEvd.D(); var d = factorEvd.D();
Assert.AreEqual(order, eigenVectors.RowCount); Assert.AreEqual(order, eigenVectors.RowCount);
Assert.AreEqual(order, eigenVectors.ColumnCount); 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. /// Can factorize a random square matrix.
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[Test, Ignore] [Test]
public void CanFactorizeRandomMatrix([Values(1, 2, 5, 10, 50, 100)] int order) public void CanFactorizeRandomMatrix([Values(1, 2, 5, 10, 50, 100)] int order)
{ {
var matrixA = MatrixLoader.GenerateRandomDenseMatrix(order, 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. /// Can factorize a symmetric random square matrix.
/// </summary> /// </summary>
/// <param name="order">Matrix order.</param> /// <param name="order">Matrix order.</param>
[Test, Ignore] [Test]
public void CanFactorizeRandomSymmetricMatrix([Values(1, 2, 5, 10, 50, 100)] int order) public void CanFactorizeRandomSymmetricMatrix([Values(1, 2, 5, 10, 50)] int order)
{ {
var matrixA = MatrixLoader.GenerateRandomPositiveDefiniteDenseMatrix(order); var matrixA = MatrixLoader.GenerateRandomPositiveDefiniteDenseMatrix(order);
MatrixHelpers.ForceSymmetric(matrixA); MatrixHelpers.ForceSymmetric(matrixA);
@ -169,7 +169,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Factorization
matrixA[i - 1, i] = 1; matrixA[i - 1, i] = 1;
matrixA[i + 1, i] = 1; matrixA[i + 1, i] = 1;
} }
var factorEvd = matrixA.Evd(); var factorEvd = matrixA.Evd();
Assert.AreEqual(factorEvd.Determinant, 0); Assert.AreEqual(factorEvd.Determinant, 0);

Loading…
Cancel
Save