/** * @file uselapack_test.cc * * Tests for LAPACK integration. */ #include "base/test.h" #include "uselapack.h" #include "la.h" TEST_SUITE_BEGIN(uselapack); /** * Creates a matrix locally. * The matrix cotents are column-major. */ #define MAKE_MATRIX_TRANS(name, n_rows, n_cols, contents ...) \ double name ## _values [] = { contents }; \ DEBUG_ASSERT(sizeof(name ## _values) / sizeof(double) == n_rows * n_cols); \ Matrix name; \ name.Alias(name ## _values, (n_rows), (n_cols)); /** * Creates a vector locally. * The matrix cotents are column-major. */ #define MAKE_VECTOR(name, length, contents ...) \ double name ## _values [] = { contents }; \ DEBUG_ASSERT(sizeof(name ## _values) / sizeof(double) == (length)); \ Vector name; \ name.Alias(name ## _values, (length)); bool VectorApproxEqual(const Vector& a, const Vector& b, double eps) { if (a.length() != b.length()) { fprintf(stderr, "XXX Size mismatch.\n"); return false; } int wrong = 0; double max_diff = 0; for (index_t i = 0; i < a.length(); i++) { double diff = fabs(a.get(i) - b.get(i)); max_diff = std::max(max_diff, diff); if (!(diff <= eps)) { wrong++; if (wrong <= 3) { fprintf(stderr, "XXX Mismatch (index %d) zero-based (%e)\n", i, diff); } } } if (wrong) { fprintf(stderr, "XXX Total %d mismatches, max diff %e.\n", wrong, max_diff); } return wrong == 0; } void AssertApproxVector(const Vector& a, const Vector& b, double eps) { if (!VectorApproxEqual(a, b, eps)) { a.PrintDebug("a"); b.PrintDebug("b"); abort(); } //fprintf(stderr, "... Correct vector!\n"); } bool MatrixApproxEqual(const Matrix& a, const Matrix& b, double eps) { if (a.n_rows() != b.n_rows() || a.n_cols() != b.n_cols()) { fprintf(stderr, "XXX Size mismatch.\n"); return false; } int wrong = 0; double max_diff = 0; for (index_t c = 0; c < a.n_cols(); c++) { for (index_t r = 0; r < a.n_rows(); r++) { double diff = fabs(a.get(r, c) - b.get(r, c)); max_diff = std::max(max_diff, diff); if (!(diff <= eps)) { wrong++; if (wrong <= 3) { fprintf(stderr, "XXX Mismatch (%d, %d) zero-based (%e)\n", r, c, diff); } } } } if (wrong) { fprintf(stderr, "XXX Total %d mismatches, max diff %e.\n", wrong, max_diff); } return wrong == 0; } void AssertApproxMatrix(const Matrix& a, const Matrix& b, double eps) { if (!MatrixApproxEqual(a, b, eps)) { a.PrintDebug("a"); b.PrintDebug("b"); abort(); } //fprintf(stderr, "... Correct matrix!\n"); } void AssertExactMatrix(const Matrix& a, const Matrix& b) { AssertApproxMatrix(a, b, 0); } void AssertApproxTransMatrix(const Matrix& a, const Matrix& b, double eps) { Matrix a_trans; la::TransposeInit(a, &a_trans); if (!MatrixApproxEqual(a_trans, b, eps)) { a_trans.PrintDebug("a_trans"); b.PrintDebug("b"); abort(); } } void TestVectorDot() { MAKE_VECTOR(a, 4, 2, 1, 4, 5); MAKE_VECTOR(b, 4, 3, 0, 2, -1); //TEST_DOUBLE_EXACT(F77_FUNC(ddot)(4, a.ptr(), 1, a.ptr(), 1), 4+1+16+25); TEST_DOUBLE_EXACT(la::Dot(a, a), 4+1+16+25); TEST_DOUBLE_EXACT(la::Dot(a, b), 6+0+8-5); TEST_DOUBLE_APPROX(la::LengthEuclidean(b), sqrt(9+0+4+1), 1.0e-8); TEST_DOUBLE_APPROX(la::LengthEuclidean(a), sqrt(4+1+16+25), 1.0e-8); } // ---- INCLUDED FROM ORIGINAL LA TEST ----- // ---- // ---- // ---- (Except distance tests are omitted) void MakeCountMatrix(index_t n_rows, index_t n_cols, Matrix *m) { m->Init(n_rows, n_cols); for (index_t c = 0; c < n_cols; c++) { for (index_t r = 0; r < n_rows; r++) { m->set(r, c, r + c); } } } void MakeConstantMatrix(index_t n_rows, index_t n_cols, double v, Matrix *m) { m->Init(n_rows, n_cols); for (index_t c = 0; c < n_cols; c++) { for (index_t r = 0; r < n_rows; r++) { m->set(r, c, v); } } } /** Tests level 1 BLAS-ish stuff. */ void TestMatrixSimpleMath() { Matrix m1; Matrix m2; Matrix m3; Matrix m4; Matrix m5; MakeCountMatrix(3, 4, &m1); MakeCountMatrix(3, 4, &m2); la::AddTo(m2, &m1); la::AddInit(m1, m2, &m3); TEST_ASSERT(m3.get(0, 0) == 0); TEST_ASSERT(m3.get(2, 3) == (2+3)*3); la::AddExpert(-1.0, m2, &m1); TEST_ASSERT(m1.get(0, 0) == 0); TEST_ASSERT(m1.get(2, 3) == (2+3)); la::Scale(4.0, &m1); TEST_ASSERT(m1.get(2, 3) == (2+3)*4); MakeConstantMatrix(3, 4, 7.0, &m4); la::AddInit(m1, m4, &m5); TEST_ASSERT(m5.get(2, 3) == (2+3)*4 + 7.0); TEST_ASSERT(m5.get(1, 3) == (1+3)*4 + 7.0); TEST_ASSERT(m5.get(1, 0) == (1+0)*4 + 7.0); } void MakeCountVector(index_t n, Vector *v) { v->Init(n); for (index_t c = 0; c < n; c++) { (*v)[c] = c; } } void MakeConstantVector(index_t n, double d, Vector *v) { v->Init(n); for (index_t c = 0; c < n; c++) { (*v)[c] = d; } } /** Tests level 1 BLAS-ish stuff. */ void TestVectorSimpleMath() { Vector v1; Vector v2; Vector v3; Vector v4; Vector v5; MakeCountVector(6, &v1); MakeCountVector(6, &v2); la::AddTo(v2, &v1); la::AddInit(v1, v2, &v3); TEST_ASSERT(v3[0] == 0); TEST_ASSERT(v3[5] == (5)*3); la::AddExpert(-1.0, v2, &v1); TEST_ASSERT(v1[0] == 0); TEST_ASSERT(v1[5] == (5)); la::Scale(4.0, &v1); TEST_ASSERT(v1[5] == (5)*4); MakeConstantVector(6, 7.0, &v4); la::AddInit(v1, v4, &v5); TEST_ASSERT(v5[5] == (5)*4 + 7.0); TEST_ASSERT(v5[4] == (4)*4 + 7.0); TEST_ASSERT(v5[1] == (1)*4 + 7.0); } /** Tests aliases and copies */ void TestVector() { Vector v1; const Vector *v_const; Vector v2; Vector v3; Vector v4; Vector v6; Vector v7; Vector v8; Vector v9; MakeCountVector(10, &v1); TEST_ASSERT(v1.length() == 10); TEST_ASSERT(v1.ptr()[3] == v1[3]); v_const = &v1; TEST_ASSERT(v_const->ptr()[3] == (*v_const)[3]); v2.Alias(v1); TEST_ASSERT(v2[9] == 9); TEST_ASSERT(v1.ptr() == v2.ptr()); v2.MakeSubvector(2, 5, &v3); TEST_ASSERT(v3.length() == 5); TEST_ASSERT(v3[4] == 6); TEST_ASSERT(v3.ptr() != v2.ptr()); v4.Copy(v3); TEST_ASSERT(v4.length() == 5); TEST_ASSERT(v4[4] == 6); SmallVector<21> v5; v5.SetZero(); TEST_ASSERT(v5[20] == 0.0); v6.Alias(v1.ptr(), v1.length()); TEST_ASSERT(v6[9] == 9); TEST_ASSERT(v6[3] == 3); v7.Own(&v1); TEST_ASSERT(v7[9] == 9); TEST_ASSERT(v7[3] == 3); v8.WeakCopy(v1); TEST_ASSERT(v8[9] == 9); TEST_ASSERT(v8[3] == 3); MakeConstantVector(10, 3.5, &v9); TEST_ASSERT(v9[0] == 3.5); TEST_ASSERT(v1[0] == 0.0); v9.SwapValues(&v1); TEST_DOUBLE_EXACT(v1[0], 3.5); TEST_ASSERT(v9[0] == 0.0); TEST_ASSERT(v2[0] == 3.5); TEST_ASSERT(v3[0] == 3.5); TEST_ASSERT(v4[0] != 3.5); TEST_ASSERT(v6[0] == 3.5); TEST_ASSERT(v7[0] == 3.5); TEST_ASSERT(v8[0] == 3.5); v8.SetZero(); TEST_ASSERT(v1[0] == 0.0); } void TestMatrix() { Matrix m1; const Matrix *m_const; Matrix m2; Matrix m3; Matrix m4; Matrix m6; Matrix m7; Matrix m8; Matrix m9; MakeCountMatrix(13, 10, &m1); TEST_ASSERT(m1.n_cols() == 10); TEST_ASSERT(m1.n_rows() == 13); TEST_ASSERT(m1.ptr()[3] == m1.get(3, 0)); m_const = &m1; TEST_ASSERT(m_const->ptr()[3] == (*m_const).get(3, 0)); Vector v1, v2; m1.MakeColumnVector(0, &v1); m1.MakeColumnVector(1, &v2); TEST_ASSERT(v1[12] == 12); TEST_ASSERT(v2[12] == 13); m2.Alias(m1); TEST_ASSERT(m2.get(9, 0) == 9); TEST_ASSERT(m1.ptr() == m2.ptr()); m2.MakeColumnSlice(2, 5, &m3); TEST_ASSERT(m3.n_cols() == 5); TEST_ASSERT(m3.get(4, 0) == 6); TEST_ASSERT(m3.ptr() != m2.ptr()); m4.Copy(m3); TEST_ASSERT(m4.n_cols() == 5); TEST_ASSERT(m4.get(4, 0) == 6); SmallMatrix<21, 21> m5; m5.SetZero(); TEST_ASSERT(m5.get(20, 0) == 0.0); m6.Alias(m1.ptr(), m1.n_rows(), m1.n_cols()); TEST_ASSERT(m6.get(9, 0) == 9); TEST_ASSERT(m6.get(3, 0) == 3); m7.Own(&m1); TEST_ASSERT(m7.get(9, 0) == 9); TEST_ASSERT(m7.get(3, 0) == 3); m8.WeakCopy(m1); TEST_ASSERT(m8.get(9, 0) == 9); TEST_ASSERT(m8.get(3, 0) == 3); MakeConstantMatrix(13, 10, 3.5, &m9); TEST_ASSERT(m9.get(0, 0) == 3.5); m9.SwapValues(&m1); TEST_ASSERT(m9.get(0, 0) == 0.0); TEST_ASSERT(m1.get(0, 0) == 3.5); TEST_ASSERT(m2.get(0, 0) == 3.5); TEST_ASSERT(m3.get(0, 0) == 3.5); TEST_ASSERT(m4.get(0, 0) != 3.5); TEST_ASSERT(m6.get(0, 0) == 3.5); TEST_ASSERT(m7.get(0, 0) == 3.5); TEST_ASSERT(m8.get(0, 0) == 3.5); m8.SetZero(); TEST_ASSERT(m1.get(0, 0) == 0.0); m8.ref(3, 4) = 21.75; TEST_ASSERT(m8.get(3, 4) == 21.75); } // ---- -------- ---- // ---- -------- ---- // ---- -------- ---- // ---- NEW TESTS ---- // ---- -------- ---- // ---- -------- ---- // ---- -------- ---- void TestMultiply() { MAKE_MATRIX_TRANS(a, 3, 3, 3, 1, 4, 1, 5, 9, 2, 6, 5); MAKE_MATRIX_TRANS(b, 3, 4, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6); MAKE_MATRIX_TRANS(product_expect, 3, 4, 30, 76, 97, 52, 98, 144, 17, 31, 45, 40, 64, 98); Matrix product_actual; // product_actual is uninitialized la::MulInit(a, b, &product_actual); AssertExactMatrix(product_expect, product_actual); product_actual.SetZero(); la::MulOverwrite(a, b, &product_actual); AssertExactMatrix(product_expect, product_actual); MAKE_MATRIX_TRANS(product_expect_transa, 3, 4, 46, 100, 76, 70, 125, 105, 23, 40, 33, 52, 82, 70); Matrix product_actual_transa; la::MulTransAInit(a, b, &product_actual_transa); AssertExactMatrix(product_expect_transa, product_actual_transa); Matrix a_t, b_t; la::TransposeInit(a, &a_t); la::TransposeInit(b, &b_t); product_actual_transa.Destruct(); la::MulTransBInit(a_t, b_t, &product_actual_transa); AssertExactMatrix(product_expect_transa, product_actual_transa); product_actual.SetZero(); la::MulTransAOverwrite(a, b, &product_actual_transa); AssertExactMatrix(product_expect_transa, product_actual_transa); // test matrix-vector multiplication MAKE_VECTOR(v1, 3, 9, 1, 2); MAKE_VECTOR(a_v1, 3, 32, 26, 55); MAKE_VECTOR(v1_a, 3, 36, 32, 34); MAKE_VECTOR(v2, 3, 2, 3, 4); MAKE_VECTOR(a_v2, 3, 17, 41, 55); MAKE_VECTOR(v2_a, 3, 25, 53, 42); Vector a_v1_actual; la::MulInit(a, v1, &a_v1_actual); AssertApproxVector(a_v1, a_v1_actual, 0); Vector a_v2_actual; a_v2_actual.Init(3); la::MulOverwrite(a, v2, &a_v2_actual); AssertApproxVector(a_v2, a_v2_actual, 0); Vector v1_a_actual; la::MulInit(v1, a, &v1_a_actual); AssertApproxVector(v1_a, v1_a_actual, 0); Vector v2_a_actual; v2_a_actual.Init(3); la::MulOverwrite(v2, a, &v2_a_actual); AssertApproxVector(v2_a, v2_a_actual, 0); // Test non-square matrices (we had some bad debug checks) MAKE_VECTOR(v3, 4, 1, 2, 3, 4); MAKE_VECTOR(b_v3, 3, 62, 41, 59); MAKE_VECTOR(v1_b, 4, 48, 106, 35, 88); SmallVector<3> b_v3_actual; la::MulOverwrite(b, v3, &b_v3_actual); AssertApproxVector(b_v3, b_v3_actual, 0); Vector v1_b_actual; la::MulInit(v1, b, &v1_b_actual); AssertApproxVector(v1_b, v1_b_actual, 0); } void TestInverse() { MAKE_MATRIX_TRANS(a, 3, 3, .5, 0, 0, 0, 1, 0, 0, 0, 2); MAKE_MATRIX_TRANS(a_inv_expect, 3, 3, 2, 0, 0, 0, 1, 0, 0, 0, .5); MAKE_MATRIX_TRANS(b, 3, 3, 3, 1, 4, 1, 5, 9, 2, 6, 5); MAKE_MATRIX_TRANS(b_inv_expect, 3, 3, 0.3222222, -0.2111111, 0.1222222, -0.1444444, -0.0777778, 0.2555556, 0.0444444, 0.1777778, -0.1555556); MAKE_MATRIX_TRANS(c, 3, 3, 1, 0, 0, 0, 1, 0, 0, 0, 0); Matrix a_inv_actual; TEST_ASSERT(PASSED(la::InverseInit(a, &a_inv_actual))); AssertExactMatrix(a_inv_expect, a_inv_actual); Matrix b_inv_actual; b_inv_actual.Init(3, 3); TEST_ASSERT(PASSED(la::InverseOverwrite(b, &b_inv_actual))); AssertApproxMatrix(b_inv_expect, b_inv_actual, 1.0e-5); Matrix c_inv_actual; // Try inverting a 3x3 rank-3 matrix TEST_ASSERT(!PASSED(la::InverseInit(c, &c_inv_actual))); // Try inverting a 3x3 rank-3 matrix TEST_ASSERT(PASSED(la::Inverse(&b))); AssertApproxMatrix(b, b_inv_actual, 1.0e-5); } void TestDeterminant() { MAKE_MATRIX_TRANS(a, 3, 3, 3, 1, 4, 1, 5, 9, 2, 6, 5); MAKE_MATRIX_TRANS(b, 3, 3, -3, 5, -8, 9, -7, 9, 2, 6, 5); MAKE_MATRIX_TRANS(c, 3, 3, -3, -5, -8, 9, -7, 9, -2, 6, 5); MAKE_MATRIX_TRANS(d, 3, 3, 31, 41, 59, 26, 53, 58, 97, 93, 23); int sign; TEST_DOUBLE_APPROX(-90.0, la::Determinant(a), 1.0e-7); TEST_DOUBLE_APPROX(log(90.0), la::DeterminantLog(a, &sign), 1.0e-7); DEBUG_ASSERT_MSG(sign == -1, "%d", sign); TEST_DOUBLE_APPROX(-412.0, la::Determinant(b), 1.0e-7); TEST_DOUBLE_APPROX(262.0, la::Determinant(c), 1.0e-7); TEST_DOUBLE_APPROX(log(262.0), la::DeterminantLog(c, &sign), 1.0e-7); DEBUG_ASSERT_MSG(sign == 1, "%d", sign); TEST_DOUBLE_APPROX(-8.3934e4, la::Determinant(d), 1.0e-7); } void TestQR() { MAKE_MATRIX_TRANS(a, 3, 3, 3, 1, 4, 1, 5, 9, 2, 6, 5); MAKE_MATRIX_TRANS(a_q_expect, 3, 3, -0.58835, -0.19612, -0.78446, 0.71472, -0.57986, -0.39107, -0.37819, -0.79076, 0.48133); MAKE_MATRIX_TRANS(a_r_expect, 3, 3, -5.09902, 0.00000, 0.00000, -8.62911, -5.70425, 0.00000, -6.27572, -4.00511, -3.09426); MAKE_MATRIX_TRANS(b, 3, 4, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6); MAKE_MATRIX_TRANS(b_q_expect, 3, 3, -0.303046, -0.505076, -0.808122, 0.929360, 0.030979, -0.367872, 0.210838, -0.862519, 0.460010); MAKE_MATRIX_TRANS(b_r_expect, 3, 4, -9.89949, 0.00000, 0.00000, -13.53604, 5.27025, 0.00000, -4.34366, 1.74642, 0.28751, -9.29340, 5.35157, 0.99669); MAKE_MATRIX_TRANS(c, 4, 3, 3, 9, 3, 8, 5, 7, 2, 4, 8, 9, 3, 6); MAKE_MATRIX_TRANS(c_q_expect, 4, 3, -0.234978, -0.704934, -0.234978, -0.626608, 0.846774, 0.175882, -0.039891, -0.500449, -0.464365, 0.686138, -0.180138, -0.530217); //0.110115, 0.036705, -0.954329, 0.275287 MAKE_MATRIX_TRANS(c_r_expect, 3, 3, -12.76715, 0.00000, 0.00000, -9.08582, 3.38347, 0.00000, -12.68882, 5.23476, -1.26139); Matrix a_q_actual; Matrix a_r_actual; TEST_ASSERT(PASSED(la::QRInit(a, &a_q_actual, &a_r_actual))); AssertApproxMatrix(a_q_expect, a_q_actual, 1.0e-5); AssertApproxMatrix(a_r_expect, a_r_actual, 1.0e-5); Matrix b_q_actual; Matrix b_r_actual; TEST_ASSERT(PASSED(la::QRInit(b, &b_q_actual, &b_r_actual))); AssertApproxMatrix(b_q_expect, b_q_actual, 1.0e-5); AssertApproxMatrix(b_r_expect, b_r_actual, 1.0e-5); Matrix c_q_actual; Matrix c_r_actual; TEST_ASSERT(PASSED(la::QRInit(c, &c_q_actual, &c_r_actual))); AssertApproxMatrix(c_q_expect, c_q_actual, 1.0e-5); AssertApproxMatrix(c_r_expect, c_r_actual, 1.0e-5); } void TestEigen() { MAKE_MATRIX_TRANS(a, 3, 3, 3, 1, 4, 1, 5, 9, 2, 6, 5); MAKE_MATRIX_TRANS(a_eigenvectors_expect, 3, 3, -0.212480, -0.912445, -0.172947, -0.599107, 0.408996, -0.592976, -0.771960, -0.012887, 0.786428); MAKE_VECTOR(a_eigenvalues_real_expect, 3, 13.08576, 2.58001, -2.66577); MAKE_VECTOR(a_eigenvalues_imag_expect, 3, 0, 0, 0); MAKE_MATRIX_TRANS(b, 2, 2, 3, 4, -2, -1); MAKE_MATRIX_TRANS(b_eigenvectors_real_expect, 2, 2, 0.40825, 0.81650, 0.40825, 0.81650); MAKE_MATRIX_TRANS(b_eigenvectors_imag_expect, 2, 2, 0.40825, 0.0, -0.40825, 0.0); MAKE_VECTOR(b_eigenvalues_real_expect, 2, 1.0, 1.0); MAKE_VECTOR(b_eigenvalues_imag_expect, 2, 2.0, -2.0); Matrix a_eigenvectors_actual; Vector a_eigenvalues_actual; TEST_ASSERT(PASSED(la::EigenvectorsInit( a, &a_eigenvalues_actual, &a_eigenvectors_actual))); AssertApproxVector(a_eigenvalues_real_expect, a_eigenvalues_actual, 1.0e-5); AssertApproxTransMatrix(a_eigenvectors_expect, a_eigenvectors_actual, 1.0e-5); Vector a_eigenvalues_real_actual; Vector a_eigenvalues_imag_actual; TEST_ASSERT(PASSED(la::EigenvaluesInit( a, &a_eigenvalues_real_actual, &a_eigenvalues_imag_actual))); AssertApproxVector(a_eigenvalues_real_expect, a_eigenvalues_real_actual, 1.0e-5); AssertApproxVector(a_eigenvalues_imag_expect, a_eigenvalues_imag_actual, 0.0); Vector a_eigenvalues_actual_2; TEST_ASSERT(PASSED(la::EigenvaluesInit( a, &a_eigenvalues_actual_2))); AssertApproxVector(a_eigenvalues_real_expect, a_eigenvalues_actual_2, 1.0e-5); // complex eigenvalues /* * This function no longer fails on imaginary, but sets them to NaN */ //Matrix b_eigenvectors_actual; //Vector b_eigenvalues_actual; //TEST_ASSERT(!PASSED(la::EigenvectorsInit( // b, &b_eigenvalues_actual, &b_eigenvectors_actual))); Matrix b_eigenvectors_real_actual; Matrix b_eigenvectors_imag_actual; Vector b_eigenvalues_real_actual; Vector b_eigenvalues_imag_actual; TEST_ASSERT(PASSED(la::EigenvectorsInit( b, &b_eigenvalues_real_actual, &b_eigenvalues_imag_actual, &b_eigenvectors_real_actual, &b_eigenvectors_imag_actual))); AssertApproxVector(b_eigenvalues_real_expect, b_eigenvalues_real_actual, 1.0e-5); AssertApproxMatrix(b_eigenvectors_real_expect, b_eigenvectors_real_actual, 1.0e-5); AssertApproxVector(b_eigenvalues_imag_expect, b_eigenvalues_imag_actual, 1.0e-5); AssertApproxMatrix(b_eigenvectors_imag_expect, b_eigenvectors_imag_actual, 1.0e-5); } void TrySchur(const Matrix &orig) { Matrix z; Matrix t; Vector eigen_real; Vector eigen_imag; la::SchurInit(orig, &eigen_real, &eigen_imag, &t, &z); Matrix z_trans; la::TransposeInit(z, &z_trans); Matrix tmp; la::MulInit(t, z_trans, &tmp); Matrix result; la::MulInit(z, tmp, &result); AssertApproxMatrix(orig, result, 1.0e-8); /* * This test now fails because Schur finds real components while * Eigenvectors on 3 args only finds true real eigenvalues */ //Vector eigen_real_2; //Matrix eigenvectors_2; //la::EigenvectorsInit(orig, &eigen_real_2, &eigenvectors_2); //AssertApproxVector(eigen_real_2, eigen_real, 1.0e-8); } void TestSchur() { MAKE_MATRIX_TRANS(a, 3, 3, 3, 1, 4, 1, 5, 9, 2, 6, 5); MAKE_MATRIX_TRANS(b, 5, 5, 3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4, 3); TrySchur(a); TrySchur(b); } void AssertProperSVD(const Matrix& orig, const Vector &s, const Matrix& u, const Matrix& vt) { Matrix s_matrix; s_matrix.Init(s.length(), s.length()); s_matrix.SetDiagonal(s); Matrix tmp; la::MulInit(u, s_matrix, &tmp); Matrix result; la::MulInit(tmp, vt, &result); AssertApproxMatrix(result, orig, 1.0e-8); } void TrySVD(const Matrix& orig) { Vector s; Matrix u; Matrix vt; la::SVDInit(orig, &s, &u, &vt); AssertProperSVD(orig, s, u, vt); } void TestSVD() { MAKE_MATRIX_TRANS(a, 3, 3, 3, 1, 4, 1, 5, 9, 2, 6, 5); MAKE_MATRIX_TRANS(a_u_expect, 3, 3, -0.21141, -0.55393, -0.80528, 0.46332, -0.78225, 0.41645, -0.86060, -0.28506, 0.42202); MAKE_VECTOR(a_s_expect, 3, 13.58236, 2.84548, 2.32869); MAKE_MATRIX_TRANS(a_vt_expect, 3, 3, -0.32463, 0.79898, -0.50620, -0.75307, 0.10547, 0.64943, -0.57227, -0.59203, -0.56746); MAKE_MATRIX_TRANS(b, 3, 10, 3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4, 3, 3, 8, 3, 2, 7); MAKE_MATRIX_TRANS(c, 9, 3, 3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4, 3, 3, 8); MAKE_MATRIX_TRANS(d, 3, 3, 0, 1, 0, -1, 0, 0, 0, 0, 1); Matrix a_u_actual; Vector a_s_actual; Matrix a_vt_actual; la::SVDInit(a, &a_s_actual, &a_u_actual, &a_vt_actual); AssertProperSVD(a, a_s_actual, a_u_actual, a_vt_actual); AssertApproxVector(a_s_expect, a_s_actual, 1.0e-5); AssertApproxMatrix(a_u_expect, a_u_actual, 1.0e-5); AssertApproxMatrix(a_vt_expect, a_vt_actual, 1.0e-5); Vector a_s_actual_2; la::SVDInit(a, &a_s_actual_2); AssertApproxVector(a_s_expect, a_s_actual_2, 1.0e-5); TrySVD(b); TrySVD(c); TrySVD(d); // let's try a big, but asymmetric, one Matrix e; e.Init(3000, 10); for (index_t j = 0; j < e.n_cols(); j++) { for (index_t i = 0; i < e.n_rows(); i++) { e.set(i, j, rand() * 1.0 / RAND_MAX); } } TrySVD(e); } void TryCholesky(const Matrix &orig) { Matrix u; TEST_ASSERT(PASSED(la::CholeskyInit(orig, &u))); Matrix result; la::MulTransAInit(u, u, &result); AssertApproxMatrix(orig, result, 1.0e-8); } void TestCholesky() { MAKE_MATRIX_TRANS(a, 3, 3, 1, 0, 0, 0, 2, 0, 0, 0, 3); MAKE_MATRIX_TRANS(b, 4, 4, 9.00, 0.60, -0.30, 1.50, 0.60, 16.04, 1.18, -1.50, -0.30, 1.18, 4.10, -0.57, 1.50, -1.50, -0.57, 25.45); TryCholesky(a); TryCholesky(b); } void TrySolveMatrix(const Matrix& a, const Matrix& b) { Matrix x; TEST_ASSERT(PASSED(la::SolveInit(a, b, &x))); Matrix result; la::MulInit(a, x, &result); AssertApproxMatrix(b, result, 1.0e-8); } void TrySolveVector(const Matrix& a, const Vector& b) { Vector x; la::SolveInit(a, b, &x); Vector result; la::MulInit(a, x, &result); AssertApproxVector(b, result, 1.0e-8); } void TestSolve() { MAKE_MATRIX_TRANS(a, 3, 3, 3, 1, 4, 1, 5, 9, 2, 6, 5); MAKE_MATRIX_TRANS(a_vectors, 3, 5, 1, 2, 3, 4, 5, 2, 1, 6, 3, 2, 1, 8, 4, 2, 6); MAKE_VECTOR(a_vector_1, 3, 3, 1, 2); MAKE_VECTOR(a_vector_2, 3, 2, 4, 6); MAKE_VECTOR(a_vector_3, 3, 2, 4, 6); MAKE_VECTOR(a_vector_4, 3, 5, 7, 8); MAKE_MATRIX_TRANS(b, 5, 5, 3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4, 3); TrySolveMatrix(a, a_vectors); TrySolveVector(a, a_vector_1); TrySolveVector(a, a_vector_2); TrySolveVector(a, a_vector_3); TrySolveVector(a, a_vector_4); } /** * Writen by Nick to Test LeastSquareFit */ void TestLeastSquareFit() { Matrix x; Matrix y; Matrix a; x.Init(3,2); x.set(0, 0, 1.0); x.set(0, 1, -1.0); x.set(1, 0, 0.33); x.set(1, 1, 0.44); x.set(2, 0, 1.5); x.set(2, 1, -0.2); y.Init(3, 2); y.set(0, 0, 1.5); y.set(0, 1, -2.0); y.set(1, 0, -0.3); y.set(1, 1, 4.0); y.set(2, 0, 0.2); y.set(2, 1, -0.4); la::LeastSquareFit(y, x, &a); Matrix true_a; true_a.Init(2, 2); true_a.set(0, 0, 0.0596); true_a.set(0, 1, 1.0162); true_a.set(1, 0, -1.299); true_a.set(1, 1, 4.064); for (index_t i=0; i<2; i++) { for(index_t j=0; j<2; j++) { TEST_DOUBLE_APPROX(true_a.get(i,j), a.get(i, j), 0.001); } } } TEST_SUITE_END(uselapack, TestVector, TestMatrix, TestVectorDot, TestVectorSimpleMath, TestMatrixSimpleMath, TestMultiply, TestInverse, TestDeterminant, TestQR, TestEigen, TestSchur, TestSVD, TestCholesky, TestSolve, TestLeastSquareFit );