rivet is hosted by Hepforge, IPPP Durham
MatrixDiag.hh
Go to the documentation of this file.
00001 #ifndef RIVET_MATH_MATRIXDIAG
00002 #define RIVET_MATH_MATRIXDIAG
00003 
00004 #include "Rivet/Math/MathHeader.hh"
00005 #include "Rivet/Math/MatrixN.hh"
00006 
00007 #include "gsl/gsl_vector.h"
00008 #include "gsl/gsl_matrix.h"
00009 #include "gsl/gsl_eigen.h"
00010 
00011 namespace Rivet {
00012 
00013 
00014 template <size_t N>
00015 class EigenSystem;
00016 template <size_t N>
00017 EigenSystem<N> diagonalize(const Matrix<N>& m);
00018 
00019 
00020 /// Handy object containing results of a diagonalization.
00021 template <size_t N>
00022 class EigenSystem {
00023   template <size_t M>
00024   friend EigenSystem<M> diagonalize(const Matrix<M>&);
00025 
00026 public:
00027 
00028   typedef pair<double, Vector<N> > EigenPair;
00029   typedef vector<EigenPair> EigenPairs;
00030 
00031   Vector<N> getDiagVector() const {
00032     assert(_eigenPairs.size() == N);
00033     Vector<N> ret;
00034     for (size_t i = 0; i < N; ++i) {
00035       ret.set(i, _eigenPairs[i].first);
00036     }
00037     return ret;
00038   }
00039 
00040   Matrix<N> getDiagMatrix() const {
00041     return Matrix<N>::mkDiag(getDiagVector());
00042   }
00043 
00044   EigenPairs getEigenPairs() const {
00045     return _eigenPairs;
00046   }
00047 
00048   vector<double> getEigenValues() const {
00049     assert(_eigenPairs.size() == N);
00050     vector<double> ret;
00051     for (size_t i = 0; i < N; ++i) {
00052       ret.push_back(_eigenPairs[i].first);
00053     }
00054     return ret;
00055   }
00056 
00057   vector<Vector<N> > getEigenVectors() const {
00058     assert(_eigenPairs.size() == N);
00059     vector<Vector<N> > ret;
00060     for (size_t i = 0; i < N; ++i) {
00061       ret.push_back(_eigenPairs[i].second);
00062     }
00063     return ret;
00064   }
00065 
00066 private:
00067 
00068   EigenPairs _eigenPairs;
00069 
00070 };
00071 
00072 
00073 /// Comparison functor for "eigen-pairs".
00074 template <size_t N>
00075 struct EigenPairCmp :
00076   public std::binary_function<const typename EigenSystem<N>::EigenPair&,
00077                               const typename EigenSystem<N>::EigenPair&, bool> {
00078   bool operator()(const typename EigenSystem<N>::EigenPair& a,
00079                   const typename EigenSystem<N>::EigenPair& b) {
00080     return a.first < b.first;
00081   }
00082 };
00083 
00084 
00085 /// Diagonalize an NxN matrix, returning a collection of pairs of
00086 /// eigenvalues and eigenvectors, ordered decreasing in eigenvalue.
00087 template <size_t N>
00088 EigenSystem<N> diagonalize(const Matrix<N>& m) {
00089   EigenSystem<N> esys;
00090 
00091   // Make a GSL matrix.
00092   gsl_matrix* A = gsl_matrix_alloc(N, N);
00093   for (size_t i = 0; i < N; ++i) {
00094     for (size_t j = 0; j < N; ++j) {
00095       gsl_matrix_set(A, i, j, m.get(i, j));
00096     }
00097   }
00098 
00099   // Use GSL diagonalization.
00100   gsl_matrix* vecs = gsl_matrix_alloc(N, N);
00101   gsl_vector* vals = gsl_vector_alloc(N);
00102   gsl_eigen_symmv_workspace* workspace = gsl_eigen_symmv_alloc(N);
00103   gsl_eigen_symmv(A, vals, vecs, workspace);
00104   gsl_eigen_symmv_sort(vals, vecs, GSL_EIGEN_SORT_VAL_DESC);
00105 
00106   // Build the vector of "eigen-pairs".
00107   typename EigenSystem<N>::EigenPairs eigensolns;
00108   for (size_t i = 0; i < N; ++i) {
00109     typename EigenSystem<N>::EigenPair ep;
00110     ep.first = gsl_vector_get(vals, i);
00111     Vector<N> ev;
00112     for (size_t j = 0; j < N; ++j) {
00113       ev.set(j, gsl_matrix_get(vecs, j, i));
00114     }
00115     ep.second = ev;
00116     eigensolns.push_back(ep);
00117   }
00118 
00119   // Free GSL memory.
00120   gsl_eigen_symmv_free(workspace);
00121   gsl_matrix_free(A);
00122   gsl_matrix_free(vecs);
00123   gsl_vector_free(vals);
00124 
00125   // Populate the returned object.
00126   esys._eigenPairs = eigensolns;
00127   return esys;
00128 }
00129 
00130 
00131 template <size_t N>
00132 inline const string toString(const typename EigenSystem<N>::EigenPair& e) {
00133   ostringstream ss;
00134   //for (typename EigenSystem<N>::EigenPairs::const_iterator i = e.begin(); i != e.end(); ++i) {
00135   ss << e->first << " -> " << e->second;
00136   //  if (i+1 != e.end()) ss << endl;
00137   //}
00138   return ss.str();
00139 }
00140 
00141 template <size_t N>
00142 inline ostream& operator<<(std::ostream& out, const typename EigenSystem<N>::EigenPair& e) {
00143   out << toString(e);
00144   return out;
00145 }
00146 
00147 
00148 }
00149 
00150 #endif