00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifndef MTL_MATRIX_EIGENVALUE_INCLUDE
00015 #define MTL_MATRIX_EIGENVALUE_INCLUDE
00016
00017 #include <cmath>
00018 #include <boost/utility.hpp>
00019 #include <boost/numeric/linear_algebra/identity.hpp>
00020 #include <boost/numeric/mtl/utility/exception.hpp>
00021 #include <boost/numeric/mtl/utility/irange.hpp>
00022 #include <boost/numeric/mtl/concept/collection.hpp>
00023 #include <boost/numeric/mtl/concept/magnitude.hpp>
00024 #include <boost/numeric/mtl/operation/conj.hpp>
00025 #include <boost/numeric/mtl/operation/householder.hpp>
00026 #include <boost/numeric/mtl/operation/diagonal.hpp>
00027 #include <boost/numeric/mtl/operation/rank_one_update.hpp>
00028 #include <boost/numeric/mtl/operation/trans.hpp>
00029 #include <boost/numeric/mtl/operation/givens.hpp>
00030 #include <boost/numeric/mtl/vector/dense_vector.hpp>
00031
00032
00033 namespace mtl { namespace matrix {
00034
00035
00037
00038 template <typename Matrix>
00039 dense_vector<typename Collection<Matrix>::value_type>
00040 inline qr_sym_imp(const Matrix& A)
00041 {
00042 using std::abs; using mtl::signum; using mtl::real;
00043 typedef typename Collection<Matrix>::value_type value_type;
00044 typedef typename Magnitude<value_type>::type magnitude_type;
00045 typedef typename Collection<Matrix>::size_type size_type;
00046 size_type ncols = num_cols(A), nrows = num_rows(A), N;
00047 value_type zero= math::zero(A[0][0]), h00, h10, h11, beta, mu, a, b, tol;
00048 const magnitude_type two(2);
00049 Matrix Q(nrows,ncols), H(nrows,ncols), G(2,2);
00050
00051 tol= 1.0e-8;
00052
00053 MTL_THROW_IF(ncols != nrows , matrix_not_square());
00054
00055
00056 H= hessenberg(A);
00057 N= nrows;
00058
00059
00060 while (1) {
00061 h00= H[N-2][N-2];
00062 h10= H[N-1][N-2];
00063 h11= H[N-1][N-1];
00064
00065
00066 if(abs(h10) < tol * abs(h11 + h00))
00067 N--;
00068 if (N < 2)
00069 break;
00070
00071
00072 beta= (h00 - h11) / two;
00073 mu = h11 + (beta != zero ? beta - signum(beta) * sqrt(beta * beta + h10 * h10) : -h10);
00074 a= H[0][0] - mu, b= H[1][0];
00075
00076
00077 for (size_type k = 0; k < N - 1; k++) {
00078 givens<Matrix>(H, a, b).trafo(k);
00079 if (k < N - 2)
00080 a= H[k+1][k], b= H[k+2][k];
00081 }
00082 }
00083 return diagonal(H);
00084 }
00085
00086
00088
00089 template <typename Matrix>
00090 dense_vector<typename Collection<Matrix>::value_type>
00091 inline qr_algo(const Matrix& A, typename Collection<Matrix>::size_type itMax)
00092 {
00093 typedef typename Collection<Matrix>::size_type size_type;
00094 size_type ncols = num_cols(A), nrows = num_rows(A);
00095 Matrix Q(nrows, ncols), H(nrows, ncols), R(nrows, ncols);
00096
00097 MTL_THROW_IF(ncols != nrows , matrix_not_square());
00098
00099 H= hessenberg(A);
00100 for (size_type i = 0; i < itMax; i++) {
00101 boost::tie(Q, R)= qr_factors(H);
00102 H= R * Q;
00103 }
00104 return diagonal(H);
00105 }
00106
00108 template <typename Matrix>
00109 dense_vector<typename Collection<Matrix>::value_type>
00110 inline eigenvalue_symmetric(const Matrix& A,
00111 typename Collection<Matrix>::size_type itMax= 0)
00112 {
00113 # ifdef MTL_SYMMETRIC_EIGENVALUE_WITH_QR
00114 return qr_algo(A, itMax == 0 ? num_rows(A) : itMax);
00115 # else
00116 return qr_sym_imp(A);
00117 # endif
00118 }
00119
00120 }}
00121
00122
00123 #endif // MTL_MATRIX_EIGENVALUE_INCLUDE
00124