void TestMatrix::runSubTest8(double& res, double& expected, std::string& subTestName) { expected = 1; subTestName = "simple_invert"; #ifdef COSMO_LAPACK Math::Matrix<double> mat(2, 2); mat(0, 0) = 1; mat(0, 1) = 2; mat(1, 0) = 3; mat(1, 1) = 4; mat.writeIntoTextFile("test_files/matrix_test_8_original.txt"); Math::Matrix<double> invMat; mat.getInverse(&invMat); invMat.writeIntoTextFile("test_files/matrix_test_8_inverse.txt"); Math::Matrix<double> prod = invMat * mat; prod.writeIntoTextFile("test_files/matrix_test_8_product.txt"); res = 1; for(int i = 0; i < prod.rows(); ++i) { for(int j = 0; j < prod.cols(); ++j) { if(i == j) { if(!Math::areEqual(prod(i, j), 1.0, 1e-5)) { output_screen("FAIL! Diagonal element " << i << " must be 1 but it is " << prod(i, j) << std::endl); res = 0; } } else { if(!Math::areEqual(prod(i, j), 0.0, 1e-5)) { output_screen("FAIL! Non-diagonal element " << i << " " << j << " must be 0 but it is " << prod(i, j) << std::endl); res = 0; } } } } #else output_screen_clean("This test (below) is skipped because Cosmo++ has not been linked to lapack" << std::endl); res = 1; #endif }
void TestMatrix::runSubTestEigen(double& res, double& expected, std::string& subTestName, bool pd) { subTestName = "simple_symmetric_eigen"; if(pd) subTestName = "simple_symmetric_positive_eigen"; #ifdef COSMO_LAPACK Math::SymmetricMatrix<double> mat(3, 3); mat(0, 0) = 3; mat(1, 1) = 10; mat(2, 2) = 4; mat(0, 2) = 2; std::vector<double> eigenvals; Math::Matrix<double> eigenvecs; const int info = mat.getEigen(&eigenvals, &eigenvecs, pd); if(info) { output_screen_clean("FAIL! Eigenvalue/eigenvector decomposition failed. Info = " << info << std::endl); res = 0; return; } //output_screen_clean("Eigenvalues: " << eigenvals[0] << ", " << eigenvals[1] << ", " << eigenvals[2] << std::endl); if(pd) eigenvecs.writeIntoTextFile("test_files/matrix_test_eigenvecs.txt"); else eigenvecs.writeIntoTextFile("test_files/matrix_test_eigenvecs_pos.txt"); res = 1; expected = 1; Math::Matrix<double> m = mat; for(int i = 0; i < 3; ++i) { Math::Matrix<double> v = eigenvecs.getCol(i); Math::Matrix<double> prod = m * v; for(int j = 0; j < 3; ++j) { if(!Math::areEqual(prod(j, 0), eigenvals[i] * v(j, 0), 1e-5)) { output_screen_clean("FAIL! The eigenvalue " << i << " times the eigenvector doesn't match the matrix times the eigenvector." << std::endl); output_screen_clean("\tLooking at index " << j << ", expected " << eigenvals[i] * v(j, 0) << " obtained " << prod(j, 0) << std::endl); res = 0; } } } Math::Matrix<double> diag = eigenvecs.getTranspose() * mat * eigenvecs; for(int i = 0; i < 3; ++i) { for(int j = 0; j < 3; ++j) { if(i == j) { if(!Math::areEqual(diag(i, i), eigenvals[i], 1e-5)) { output_screen_clean("FAIL! The diagonalized matrix has " << diag(i, i) << " on the diagonal at index " << i << " but the corresponding eigenvalue is " << eigenvals[i] << std::endl); res = 0; } } else { if(!Math::areEqual(diag(i, j), 0.0, 1e-5)) { output_screen_clean("FAIL! The diagonalized matrix has " << diag(i, j) << " as the off-diagonal element (" << i << ", " << j << "). Must be 0." << std::endl); res = 0; } } } } #else output_screen_clean("This test (below) is skipped because Cosmo++ has not been linked to lapack" << std::endl); res = 1; expected = 1; #endif }