diff --git a/.travis.yml b/.travis.yml index 04d60c4..29a28d6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,7 +20,14 @@ matrix: - ./test_jacobi 4 1000 3.0 - ./test_jacobi 5 1000 3.0 - ./test_jacobi 10 100 3.0 - - ./test_jacobi 50 20 3.0 + - ./test_jacobi 30 20 3.0 + #- now test with degenerate eigenvalues + - ./test_jacobi 2 1000 3.0 2 + - ./test_jacobi 3 1000 3.0 2 + - ./test_jacobi 4 1000 3.0 2 + - ./test_jacobi 5 1000 3.0 3 + - ./test_jacobi 10 100 3.0 5 + - ./test_jacobi 30 20 3.0 20 - cd ../ - language: cpp @@ -38,6 +45,13 @@ matrix: - ./test_jacobi 4 1000 3.0 - ./test_jacobi 5 1000 3.0 - ./test_jacobi 10 100 3.0 - - ./test_jacobi 50 20 3.0 + - ./test_jacobi 30 20 3.0 + #- now test with degenerate eigenvalues + - ./test_jacobi 2 1000 3.0 2 + - ./test_jacobi 3 1000 3.0 2 + - ./test_jacobi 4 1000 3.0 2 + - ./test_jacobi 5 1000 3.0 3 + - ./test_jacobi 10 100 3.0 5 + - ./test_jacobi 30 20 3.0 20 - cd ../ diff --git a/README.md b/README.md index 1d0d18b..4dbe8a1 100644 --- a/README.md +++ b/README.md @@ -78,13 +78,11 @@ This is a header-only library. # Development Status: *alpha* -As of 2020-1-23, basic functionality appears to be working. +As of 2020-1-29, basic functionality appears to be working. More testing is needed including tests for copy constructors, memory leaks and profiling. The API might change slightly, but existing code built using it should still work. -(Later I might add "const" to the first argument of Jacobi::Diagonalize().) - ## License diff --git a/include/jacobi.hpp b/include/jacobi.hpp index 707c972..b01d909 100644 --- a/include/jacobi.hpp +++ b/include/jacobi.hpp @@ -27,7 +27,7 @@ class Jacobi { int n; //!< the size of the matrix Scalar **M; //!< local copy of the matrix being analyzed - // Precomputed cosine, sin, and tangent of the most recent rotation angle: + // Precomputed cosine, sine, and tangent of the most recent rotation angle: Scalar c; //!< = cos(θ) Scalar s; //!< = sin(θ) Scalar t; //!< = tan(θ), (note |t|<=1) @@ -222,12 +222,12 @@ CalcRot(Matrix M, // matrix } -/// brief Perform a similarity transform by multiplying matrix M on both -/// sides by a rotation matrix (transposing one of them). +/// brief Perform a similarity transformation by multiplying matrix M on both +/// sides by a rotation matrix (and its transpose). /// This rotation matrix performs a rotation in the i,j plane by -/// angle θ. Also updates the max_idx_row[] array. Assumes i < j. -/// details This function assumes that iv) are not computed. /// @code diff --git a/include/matrix_alloc.hpp b/include/matrix_alloc.hpp index 5f9f52b..e661680 100644 --- a/include/matrix_alloc.hpp +++ b/include/matrix_alloc.hpp @@ -65,8 +65,6 @@ void Alloc2D(int nrows, //!< size of the array (outer) template void Dealloc2D(Entry ***paaX) //!< pointer to 2-D multidimensional array { - //*paaX = new Entry* [size[0]]; - //(*paaX)[0] = new Entry [size[0] * size[1]]; if (paaX && *paaX) { delete [] (*paaX)[0]; delete [] (*paaX); diff --git a/tests/test.cpp b/tests/test.cpp index f501c41..f6f5799 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "matrix_alloc.hpp" #include "jacobi.hpp" @@ -17,7 +18,9 @@ using namespace jacobi_public_domain; // @brief Are two numbers "similar"? template inline static bool Similar(T a, T b, T eps=1.0e-06) { - return std::abs(a - b) <= std::abs(eps)*std::sqrt(std::abs(a)*std::abs(b)); + return ((std::abs(a-b) <= std::abs(eps)) + || + (std::abs(a-b) <= std::abs(eps)*std::sqrt(std::abs(a)*std::abs(b)))); } /// @brief Are two vectors (containing n numbers) similar? @@ -186,11 +189,6 @@ void GenRandSymm(Matrix M, //(evects, n, generator); + // Does the user want us to force some of the eigenvalues to be the same? + if (n_degeneracy > 1) { + unsigned *permutation = new unsigned[n]; //a random permutation from 0...n-1 + for (int i = 0; i < n; i++) + permutation[i] = i; + std::shuffle(permutation, permutation+n, generator); + for (int i = 1; i < n_degeneracy; i++) //set the first n_degeneracy to same + evals[permutation[i]] = evals[permutation[0]]; + delete [] permutation; + } + + // D is a diagonal matrix whose diagonal elements are the eigenvalues + for (int i = 0; i < n; i++) + for (int j = 0; j < n; j++) + D[i][j] = ((i == j) ? evals[i] : 0.0); + + // Now randomly generate the (transpose of) the "evects" matrix + GenRandOrth(evects, n, generator); //(will transpose it later) // Construct the test matrix, M, where M = Rt * D * R mmult(evects, D, tmp, n); //tmp = Rt * D @@ -301,7 +314,8 @@ void TestJacobi(int n, // 4) n_tests = std::stoi(argv[4]); + if (argc > 5) + n_degeneracy = std::stoi(argv[5]); if (argc > 6) - n_degeneracy = std::stoi(argv[6]); - if (argc > 7) - seed = std::stoi(argv[7]); + seed = std::stoi(argv[6]); TestJacobi(n_size, n_matr, erange, n_tests, n_degeneracy, seed);