/*!
\file diagonalize.h
\brief Inferface function to boost/lapack syev function
\author Martin Peters
$Date: 2010/03/29 20:33:22 $
$Revision: 1.7 $
----------------------------------------------------------------------------
MTK++ - C++ package of modeling libraries.
Copyright (C) 2005-2006 (see AUTHORS file for a list of contributors)
This file is part of MTK++.
MTK++ is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
MTK++ is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lessser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see .
----------------------------------------------------------------------------
*/
#ifndef DIAGONALIZE_H
#define DIAGONALIZE_H
#include
#include
#include
#include "boost/numeric/bindings/lapack/syev.hpp"
#include "boost/numeric/bindings/lapack/gesvd.hpp"
#include "boost/numeric/bindings/lapack/gesdd.hpp"
#include "boost/numeric/bindings/traits/ublas_matrix.hpp"
#include "boost/numeric/bindings/traits/ublas_vector.hpp"
namespace ublas = boost::numeric::ublas;
namespace lapack = boost::numeric::bindings::lapack;
namespace MTKpp
{
/*!
\brief Diagonalize a matrix
Diag(S):
Diagonalizing S involves finding U such that:
transpose(U) * S * U = D
where D is the diagonal matrix containig the eigenvalues,
and U is the eigenvector matrix.
\param eigenvectors Matrix to be diagonalized, it is destroyed, returned containing the eigenvectors
\param eigenvalues Vector of resulting eigenvalues
\return success
*/
inline int diagonalize(ublas::matrix& eigenvectors,
ublas::vector& eigenvalues) {
int r = lapack::syev( 'V', 'U', eigenvectors, eigenvalues, lapack::minimal_workspace() );
return r;
}
/*!
\brief Singular Value Decomposition (SVD)
From boost documentation
gesvd --> simple driver
gesdd --> divide and conquer driver
gesvd/gesdd computes the singular value decomposition (SVD) of
M-by-N matrix A, optionally computing the left and/or right
singular vectors. The SVD is written
A = U * S * V^T or A = U * S * V^H
where S is an M-by-N matrix which is zero except for its min(m,n)
diagonal elements, U is an M-by-M orthogonal/unitary matrix, and V
is an N-by-N orthogonal/unitary matrix. The diagonal elements of S
are the singular values of A; they are real and non-negative, and
are returned in descending order. The first min(m,n) columns of
U and V are the left and right singular vectors of A. (Note that
the routine returns V^T or V^H, not V.
A_nxp = U_nxn S_nxp V^T_pxp
Other links
http://en.wikipedia.org/wiki/Singular_value_decomposition
http://www.netlib.org/lapack/lug/node32.html
\return success
*/
inline int svd(ublas::matrix& H,
ublas::vector& s,
ublas::matrix& U,
ublas::matrix& VT) {
//int r = lapack::gesvd('A', 'A', H, s, U, VT);
int r = lapack::gesdd(H, s, U, VT);
return r;
}
/*!
\brief Sorts eigenvalues and applies this ordering on the eigenvector matrix
\param eigenvectors Eigenvector matrix
\param eigenvalues Eigenvalue matrix
\param order Ascending = 0, Desending = 1
*/
inline void eigenValueSort(ublas::matrix& eigenvectors,
ublas::vector& eigenvalues, int order) {
int k;
double p;
int size = eigenvectors.size1();
// Ascending
if (!order) {
for (int i = 0; i < size-1 ; ++i) {
k = i;
p = eigenvalues(i);
for (int j = i+1; j < size; ++j) {
if (eigenvalues(j) < p) {
k = j;
p = eigenvalues(j);
}
}
if ( k != i ) {
eigenvalues(k) = eigenvalues(i);
eigenvalues(i) = p;
for (int m = 0; m < size; ++m) {
p = eigenvectors(m,i);
eigenvectors(m,i) = eigenvectors(m,k);
eigenvectors(m,k) = p;
}
}
}
}
// Descending
else {
for (int i = 0; i < size-1 ; ++i) {
k = i;
p = eigenvalues(i);
for (int j = i+1; j < size; ++j) {
if (eigenvalues(j) > p) {
k = j;
p = eigenvalues(j);
}
}
if ( k != i ) {
eigenvalues(k) = eigenvalues(i);
eigenvalues(i) = p;
for (int m = 0; m < size; ++m) {
p = eigenvectors(m,i);
eigenvectors(m,i) = eigenvectors(m,k);
eigenvectors(m,k) = p;
}
}
}
}
}
} // MTKpp namespace
#endif // DIAGONALIZE_H