// Copyright (C) 2010 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #include "tester.h" #include <dlib/matrix.h> #include <dlib/rand.h> #include <vector> #include <sstream> namespace { using namespace test; using namespace dlib; using namespace std; dlib::logger dlog("test.symmetric_matrix_cache"); class test_symmetric_matrix_cache : public tester { /*! WHAT THIS OBJECT REPRESENTS This object represents a unit test. When it is constructed it adds itself into the testing framework. !*/ public: test_symmetric_matrix_cache ( ) : tester ( "test_symmetric_matrix_cache", // the command line argument name for this test "Run tests on the symmetric_matrix_cache function.", // the command line argument description 0 // the number of command line arguments for this test ) { } dlib::rand rnd; // ----------------------------------- template <typename EXP1, typename EXP2> void test_colm_exp ( const matrix_exp<EXP1>& m1, const matrix_exp<EXP2>& m2 ) { for (long i = 0; i < m1.nc(); ++i) { typename colm_exp<EXP1>::type c1 = colm(m1,i); typename colm_exp<EXP2>::type c2 = colm(m2,i); DLIB_TEST(equal(c1 , c2)); DLIB_TEST(equal(colm(m1,i) , c2)); DLIB_TEST(equal(c1 , colm(m2,i))); DLIB_TEST(equal(colm(m1,i) , colm(m2,i))); } // Get a bunch of columns at once to test out the reference // counting and automatic cache expansion built into the symmetric_matrix_cache. // This test verifies that, for example, getting column 3 doesn't stomp on // any of the previous columns. typename colm_exp<EXP1>::type c1_0 = colm(m1,0); typename colm_exp<EXP1>::type c1_1 = colm(m1,1); typename colm_exp<EXP1>::type c1_2 = colm(m1,2); typename colm_exp<EXP1>::type c1_3 = colm(m1,3); typename colm_exp<EXP1>::type c1_4 = colm(m1,4); typename colm_exp<EXP1>::type c1_5 = colm(m1,5); typename colm_exp<EXP2>::type c2_0 = colm(m2,0); typename colm_exp<EXP2>::type c2_1 = colm(m2,1); typename colm_exp<EXP2>::type c2_2 = colm(m2,2); typename colm_exp<EXP2>::type c2_3 = colm(m2,3); typename colm_exp<EXP2>::type c2_4 = colm(m2,4); typename colm_exp<EXP2>::type c2_5 = colm(m2,5); DLIB_TEST(equal(c1_0, c2_0)); DLIB_TEST(equal(c1_1, c2_1)); DLIB_TEST(equal(c1_2, c2_2)); DLIB_TEST(equal(c1_3, c2_3)); DLIB_TEST(equal(c1_4, c2_4)); DLIB_TEST(equal(c1_5, c2_5)); } // ----------------------------------- template <typename EXP1, typename EXP2> void test_rowm_exp ( const matrix_exp<EXP1>& m1, const matrix_exp<EXP2>& m2 ) { for (long i = 0; i < m1.nc(); ++i) { typename rowm_exp<EXP1>::type r1 = rowm(m1,i); typename rowm_exp<EXP2>::type r2 = rowm(m2,i); DLIB_TEST(equal(r1 , r2)); DLIB_TEST(equal(rowm(m1,i) , r2)); DLIB_TEST(equal(r1 , rowm(m2,i))); DLIB_TEST(equal(rowm(m1,i) , rowm(m2,i))); } // Get a bunch of rows at once to test out the reference // counting and automatic cache expansion built into the symmetric_matrix_cache. // This test verifies that, for example, getting row 3 doesn't stomp on // any of the previous rows. typename rowm_exp<EXP1>::type r1_0 = rowm(m1,0); typename rowm_exp<EXP1>::type r1_1 = rowm(m1,1); typename rowm_exp<EXP1>::type r1_2 = rowm(m1,2); typename rowm_exp<EXP1>::type r1_3 = rowm(m1,3); typename rowm_exp<EXP1>::type r1_4 = rowm(m1,4); typename rowm_exp<EXP1>::type r1_5 = rowm(m1,5); typename rowm_exp<EXP2>::type r2_0 = rowm(m2,0); typename rowm_exp<EXP2>::type r2_1 = rowm(m2,1); typename rowm_exp<EXP2>::type r2_2 = rowm(m2,2); typename rowm_exp<EXP2>::type r2_3 = rowm(m2,3); typename rowm_exp<EXP2>::type r2_4 = rowm(m2,4); typename rowm_exp<EXP2>::type r2_5 = rowm(m2,5); DLIB_TEST(equal(r1_0, r2_0)); DLIB_TEST(equal(r1_1, r2_1)); DLIB_TEST(equal(r1_2, r2_2)); DLIB_TEST(equal(r1_3, r2_3)); DLIB_TEST(equal(r1_4, r2_4)); DLIB_TEST(equal(r1_5, r2_5)); } // ----------------------------------- template <typename EXP1, typename EXP2> void test_diag_exp ( const matrix_exp<EXP1>& m1, const matrix_exp<EXP2>& m2 ) { typename diag_exp<EXP1>::type c1 = diag(m1); typename diag_exp<EXP2>::type c2 = diag(m2); DLIB_TEST(equal(c1 , c2)); DLIB_TEST(equal(diag(m1) , c2)); DLIB_TEST(equal(c1 , diag(m2))); DLIB_TEST(equal(diag(m1) , diag(m2))); } // ----------------------------------- void test_stuff ( long csize ) { print_spinner(); dlog << LINFO << "csize: "<< csize; matrix<double> m = randm(10,10,rnd); m = make_symmetric(m); DLIB_TEST(equal(symmetric_matrix_cache<float>(m, csize), matrix_cast<float>(m))); DLIB_TEST(equal(symmetric_matrix_cache<double>(m, csize), matrix_cast<double>(m))); dlog << LINFO << "test colm/rowm"; for (long i = 0; i < m.nr(); ++i) { DLIB_TEST(equal(colm(symmetric_matrix_cache<float>(m, csize),i), colm(matrix_cast<float>(m),i))); DLIB_TEST(equal(rowm(symmetric_matrix_cache<float>(m, csize),i), rowm(matrix_cast<float>(m),i))); // things are supposed to be symmetric DLIB_TEST(equal(colm(symmetric_matrix_cache<float>(m, csize),i), trans(rowm(matrix_cast<float>(m),i)))); DLIB_TEST(equal(rowm(symmetric_matrix_cache<float>(m, csize),i), trans(colm(matrix_cast<float>(m),i)))); } dlog << LINFO << "test diag"; DLIB_TEST(equal(diag(symmetric_matrix_cache<float>(m,csize)), diag(matrix_cast<float>(m)))); test_colm_exp(symmetric_matrix_cache<float>(m,csize), matrix_cast<float>(m)); test_rowm_exp(symmetric_matrix_cache<float>(m,csize), matrix_cast<float>(m)); test_diag_exp(symmetric_matrix_cache<float>(m,csize), matrix_cast<float>(m)); test_colm_exp(tmp(symmetric_matrix_cache<float>(m,csize)), tmp(matrix_cast<float>(m))); test_rowm_exp(symmetric_matrix_cache<float>(m,csize), tmp(matrix_cast<float>(m))); test_diag_exp(tmp(symmetric_matrix_cache<float>(m,csize)), tmp(matrix_cast<float>(m))); } void perform_test ( ) { for (int itr = 0; itr < 5; ++itr) { test_stuff(0); test_stuff(1); test_stuff(2); } } }; // Create an instance of this object. Doing this causes this test // to be automatically inserted into the testing framework whenever this cpp file // is linked into the project. Note that since we are inside an unnamed-namespace // we won't get any linker errors about the symbol a being defined multiple times. test_symmetric_matrix_cache a; }