/*---------------------------------------------------------------------------*
* IT++ *
*---------------------------------------------------------------------------*
* Copyright (c) 1995-2004 by Tony Ottosson, Thomas Eriksson, Pål Frenger, *
* Tobias Ringström, and Jonas Samuelsson. *
* *
* Permission to use, copy, modify, and distribute this software and its *
* documentation under the terms of the GNU General Public License is hereby *
* granted. No representations are made about the suitability of this *
* software for any purpose. It is provided "as is" without expressed or *
* implied warranty. See the GNU General Public License for more details. *
*---------------------------------------------------------------------------*/
/*!
\file
\brief Eigenvalue decomposition functions.
\author Tony Ottosson
1.11
2003/06/19 09:03:05
*/
#include "base/eigen.h"
#include "base/matfunc.h"
#include "../src/base/lapack.h"
namespace itpp {
#ifndef NO_LAPACK
bool eig_sym(const mat &A, vec &d, mat &V)
{
it_assert1(A.rows() == A.cols(), "eig_sym: Matrix is not symmetric");
// Test for symmetric?
char jobz='V', uplo='U';
int n, lda, lwork, info;
n = lda = A.rows();
lwork = std::max(1,3*n-1); // This may be choosen better!
d.set_size(n, false);
vec work(lwork);
V = A; // The routine overwrites input matrix with eigenvectors
dsyev_(&jobz, &uplo, &n, V._data(), &lda, d._data(), work._data(), &lwork, &info);
return (info==0);
}
bool eig_sym(const mat &A, vec &d)
{
it_assert1(A.rows() == A.cols(), "eig_sym: Matrix is not symmetric");
// Test for symmetric?
char jobz='N', uplo='U';
int n, lda, lwork, info;
n = lda = A.rows();
lwork = std::max(1,3*n-1); // This may be choosen better!
d.set_size(n, false);
vec work(lwork);
mat B(A); // The routine overwrites input matrix
dsyev_(&jobz, &uplo, &n, B._data(), &lda, d._data(), work._data(), &lwork, &info);
return (info==0);
}
vec eig_sym(const mat &A)
{
vec d;
eig_sym(A, d);
return d;
}
bool eig_sym(const cmat &A, vec &d, cmat &V)
{
it_assert1(A.rows() == A.cols(), "eig_sym: Matrix is not hermitian");
// Test for symmetric?
char jobz='V', uplo='U';
int n, lda, lwork, info;
n = lda = A.rows();
lwork = std::max(1,2*n-1); // This may be choosen better!
d.set_size(n, false);
cvec work(lwork);
vec rwork(std::max(1,3*n-2)); // This may be choosen better!
V = A; // The routine overwrites input matrix with eigenvectors
zheev_(&jobz, &uplo, &n, V._data(), &lda, d._data(), work._data(), &lwork, rwork._data(), &info);
return (info==0);
}
bool eig_sym(const cmat &A, vec &d)
{
it_assert1(A.rows() == A.cols(), "eig_sym: Matrix is not hermitian");
// Test for symmetric?
char jobz='N', uplo='U';
int n, lda, lwork, info;
n = lda = A.rows();
lwork = std::max(1,2*n-1); // This may be choosen better!
d.set_size(n, false);
cvec work(lwork);
vec rwork(std::max(1,3*n-2)); // This may be choosen better!
cmat B(A); // The routine overwrites input matrix
zheev_(&jobz, &uplo, &n, B._data(), &lda, d._data(), work._data(), &lwork, rwork._data(), &info);
return (info==0);
}
vec eig_sym(const cmat &A)
{
vec d;
eig_sym(A, d);
return d;
}
// Non-symmetric matrix
bool eig(const mat &A, cvec &d, cmat &V)
{
it_assert1(A.rows() == A.cols(), "eig: Matrix is not square");
char jobvl='N', jobvr='V';
int n, lda, ldvl, ldvr, lwork, info;
n = lda = A.rows();
ldvl = 1; ldvr = n;
lwork = std::max(1,4*n); // This may be choosen better!
vec work(lwork);
vec rwork(std::max(1,2*n)); // This may be choosen better
vec wr(n), wi(n);
mat vl, vr(n,n);
mat B(A); // The routine overwrites input matrix
dgeev_(&jobvl, &jobvr, &n, B._data(), &lda, wr._data(), wi._data(), vl._data(), &ldvl, vr._data(), &ldvr, work._data(), &lwork, &info);
d = to_cvec(wr, wi);
// Fix V
V.set_size(n, n, false);
for (int j=0; j<n; j++) {
// if d(j) and d(j+1) are complex conjugate pairs, treat special
if( (j<n-1) && d(j) == std::conj(d(j+1))) {
V.set_col(j, to_cvec(vr.get_col(j), vr.get_col(j+1)) );
V.set_col(j+1, to_cvec(vr.get_col(j), -vr.get_col(j+1)) );
j++;
} else {
V.set_col(j, to_cvec(vr.get_col(j)) );
}
}
return (info==0);
}
// Non-symmetric matrix
bool eig(const mat &A, cvec &d)
{
it_assert1(A.rows() == A.cols(), "eig: Matrix is not square");
char jobvl='N', jobvr='N';
int n, lda, ldvl, ldvr, lwork, info;
n = lda = A.rows();
ldvl = 1; ldvr = 1;
lwork = std::max(1,4*n); // This may be choosen better!
vec work(lwork);
vec rwork(std::max(1,2*n)); // This may be choosen better
vec wr(n), wi(n);
mat vl, vr;
mat B(A); // The routine overwrites input matrix
dgeev_(&jobvl, &jobvr, &n, B._data(), &lda, wr._data(), wi._data(), vl._data(), &ldvl, vr._data(), &ldvr, work._data(), &lwork, &info);
d = to_cvec(wr, wi);
return (info==0);
}
cvec eig(const mat &A)
{
cvec d;
eig(A, d);
return d;
}
bool eig(const cmat &A, cvec &d, cmat &V)
{
it_assert1(A.rows() == A.cols(), "eig: Matrix is not square");
char jobvl='N', jobvr='V';
int n, lda, ldvl, ldvr, lwork, info;
n = lda = A.rows();
ldvl = 1; ldvr = n;
lwork = std::max(1,2*n); // This may be choosen better!
d.set_size(n, false);
V.set_size(n, n, false);
cvec work(lwork);
vec rwork(std::max(1,2*n)); // This may be choosen better!
cmat vl;
cmat B(A); // The routine overwrites input matrix
zgeev_(&jobvl, &jobvr, &n, B._data(), &lda, d._data(), vl._data(), &ldvl, V._data(), &ldvr, work._data(), &lwork, rwork._data(), &info);
return (info==0);
}
bool eig(const cmat &A, cvec &d)
{
it_assert1(A.rows() == A.cols(), "eig: Matrix is not square");
char jobvl='N', jobvr='N';
int n, lda, ldvl, ldvr, lwork, info;
n = lda = A.rows();
ldvl = 1; ldvr = 1;
lwork = std::max(1,2*n); // This may be choosen better!
d.set_size(n, false);
cvec work(lwork);
vec rwork(std::max(1,2*n)); // This may be choosen better!
cmat vl, vr;
cmat B(A); // The routine overwrites input matrix
zgeev_(&jobvl, &jobvr, &n, B._data(), &lda, d._data(), vl._data(), &ldvl, vr._data(), &ldvr, work._data(), &lwork, rwork._data(), &info);
return (info==0);
}
cvec eig(const cmat &A)
{
cvec d;
eig(A, d);
return d;
}
#endif // NO_LAPACK
} //namespace itpp
syntax highlighted by Code2HTML, v. 0.9.1