.. _program_listing_file_src_util_matrix.cpp: Program Listing for File matrix.cpp =================================== |exhale_lsh| :ref:`Return to documentation for file ` (``src_util/matrix.cpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #include #include "matrix.hpp" using namespace std; /* NOTE : The general convention of this code is to use "Column Major Matrices", stored in linear arrays, such that if A is a r x c matrix, then A[i][j] ---> A[i+r*j] Eigen also uses column-major storage by default, so Eigen::Map wraps the v.data() buffer directly with zero copy. */ template<> void matrix::inverse() { QCM_ASSERT(r==c); if(r==0) return; if(r==1){v[0] = 1/v[0]; return;} Eigen::Map M(v.data(), r, c); M = M.inverse().eval(); } template<> bool matrix::is_real(double accuracy) { for(size_t i=0; i accuracy) return false; return true; } template<> void matrix::eigensystem(vector &d, matrix &U) const { QCM_ASSERT(r == c); QCM_ASSERT(U.r == r and U.c == c); QCM_ASSERT(d.size() == r); Eigen::Map A(v.data(), r, c); Eigen::SelfAdjointEigenSolver solver(A); if(solver.info() != Eigen::Success) { cout << "dimension : " << r << " x " << c << endl; cout << *this << endl; throw std::runtime_error("SelfAdjointEigenSolver failed (eigensystem)"); } Eigen::Map(d.data(), r) = solver.eigenvalues(); Eigen::Map(U.v.data(), r, c) = solver.eigenvectors(); } template<> void matrix::eigenvalues(vector &d) { QCM_ASSERT(r == c); Eigen::Map A(v.data(), r, c); Eigen::SelfAdjointEigenSolver solver(A, Eigen::EigenvaluesOnly); QCM_ASSERT(solver.info() == Eigen::Success); Eigen::Map(d.data(), r) = solver.eigenvalues(); } template<> void matrix::inverse() { QCM_ASSERT(r==c); if(r==0) return; Eigen::Map M(v.data(), r, c); M = M.inverse().eval(); } template<> Complex matrix::determinant() { if(r==0) return Complex(0); Eigen::Map M(v.data(), r, c); return M.determinant(); } template<> void matrix::eigensystem(vector &d, matrix &U) const { QCM_ASSERT(r == c); Eigen::Map A(v.data(), r, c); Eigen::SelfAdjointEigenSolver solver(A); if(solver.info() != Eigen::Success) { cout << "dimension : " << r << " x " << c << endl; cout << *this << endl; throw std::runtime_error("SelfAdjointEigenSolver failed (eigensystem)"); } Eigen::Map(d.data(), r) = solver.eigenvalues(); Eigen::Map(U.v.data(), r, c) = solver.eigenvectors(); } template<> void matrix::eigenvalues(vector &d) { QCM_ASSERT(r == c); Eigen::Map A(v.data(), r, c); Eigen::SelfAdjointEigenSolver solver(A, Eigen::EigenvaluesOnly); QCM_ASSERT(solver.info() == Eigen::Success); Eigen::Map(d.data(), r) = solver.eigenvalues(); } template<> double matrix::norm() { Eigen::Map M(v.data(), r, c); return M.norm(); } template<> double matrix::norm() { Eigen::Map M(v.data(), r, c); return M.norm(); } template<> double matrix::norm2() { Eigen::Map M(v.data(), r, c); return M.squaredNorm(); } template<> double matrix::norm2() { Eigen::Map M(v.data(), r, c); return M.squaredNorm(); } template<> bool matrix::is_orthogonal(double accuracy) { if(r!=c) return false; Eigen::Map M(v.data(), r, c); Eigen::MatrixXd diff = M.transpose() * M - Eigen::MatrixXd::Identity(r, r); return diff.cwiseAbs().maxCoeff() <= accuracy; } template<> bool matrix::cholesky(matrix &A) { Eigen::Map Ma(A.v.data(), A.r, A.c); Eigen::LLT llt(Ma); if(llt.info() != Eigen::Success) return false; set_size(A.r); Eigen::Map(v.data(), r, c) = llt.matrixL(); return true; } template<> bool matrix::triangular_inverse() { Eigen::Map M(v.data(), r, c); Eigen::MatrixXd Linv = M.triangularView().solve( Eigen::MatrixXd::Identity(r, r)); M = Linv; return true; } /* transforms a real matrix into a complex one **/ matrix to_complex_matrix(const matrix &x) { matrix xc(x.r, x.c); for (size_t i = 0; i < x.v.size(); i++) xc.v[i] = x.v[i]; return xc; } /* Builds a hermitian complex matrix from a real vector **/ matrix hermitian_matrix_from_real_vector(size_t d, const vector &x){ matrix M(d); size_t k = 0; for(int i = 0; i &M, double *x){ size_t k = 0; for(int i = 0; i