summaryrefslogtreecommitdiffstats
path: root/ml/dlib/dlib/test/symmetric_matrix_cache.cpp
blob: 6d93a4daa373c7bc84ba082af1d4200dd20aff44 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
// 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;

}