Commit b4ded5bf079bf7b2c29e4bec9ef7deed4e6bc10a

Authored by Jürgen Knödlseder
1 parent a4f1132c

Improve the error messages.

Improve some error messages so that more information is available in the report in case of failures.
test/test_GMatrix.cpp
1 1 /***************************************************************************
2   - * test_GMatrix.cpp - test GMatrix class *
  2 + * test_GMatrix.cpp - Test generic matrix class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2006-2011 by Jurgen Knodlseder *
  4 + * copyright (C) 2006-2012 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -18,778 +18,834 @@
18 18 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19 19 * *
20 20 ***************************************************************************/
  21 +/**
  22 + * @file test_GMatrix.cpp
  23 + * @brief Implementation of unit tests for generic matrices
  24 + * @author Juergen Knoedlseder
  25 + */
21 26  
22 27 /* __ Includes ___________________________________________________________ */
  28 +#ifdef HAVE_CONFIG_H
  29 +#include <config.h>
  30 +#endif
23 31 #include <cmath>
24   -#include <iostream> // std::cout, cerr
25   -#include <stdexcept> // std::exception
26   -#include "GammaLib.hpp"
27 32 #include "test_GMatrix.hpp"
28   -/* __ Namespaces _________________________________________________________ */
29 33  
30 34 /* __ Globals ____________________________________________________________ */
  35 +double g_matrix[] = {1.0, 2.0, 3.0, 4.0,
  36 + 5.0, 6.0, 7.0, 8.0,
  37 + 9.0, 10., 11., 12.};
  38 +double g_vector[] = {1.0, 2.0, 3.0, 4.0};
  39 +int g_rows = 3;
  40 +int g_cols = 4;
31 41  
32   -void TestGMatrix::set(void){
33   - // Test name
34   - name("GMatrix");
35   -
36   - //Initialize m_test
37   - init_matrix();
38   -
39   - //Initialize m_vector
40   - init_vector();
41   -
42   - //Set parameters
43   - m_g_rows = 3;
44   - m_g_cols = 4;
45   -
46   - //add tests
47   - add_test(static_cast<pfunction>(&TestGMatrix::set_matrix),"Set matrix");
48   - add_test(static_cast<pfunction>(&TestGMatrix::set_vector),"Set Vector");
49   - add_test(static_cast<pfunction>(&TestGMatrix::set_bigger),"Set matrix bigger");
50   - add_test(static_cast<pfunction>(&TestGMatrix::test_output),"Output test matrix");
51   - add_test(static_cast<pfunction>(&TestGMatrix::test_conversion),"Matrix conversions");
52   - add_test(static_cast<pfunction>(&TestGMatrix::test_extract),"Vector extraction, insertion and addition");
53   -
54   - add_test(static_cast<pfunction>(&TestGMatrix::test1),"Test 1: Allocate zero matrix");
55   - //add_test(static_cast<pfunction>(&TestGMatrix::test2),"Test 2: Allocate too large matrix");
56   - add_test(static_cast<pfunction>(&TestGMatrix::test3),"Test3: Assign values");
57   - add_test(static_cast<pfunction>(&TestGMatrix::test4),"Test 4: Matrix copy constructor");
58   - add_test(static_cast<pfunction>(&TestGMatrix::test5),"Test 5: Matrix assignment");
59   - add_test(static_cast<pfunction>(&TestGMatrix::test6),"Test 6: Transposition");
60   - add_test(static_cast<pfunction>(&TestGMatrix::test7),"Test 7: Matrix*Vector multiplication");
61   - add_test(static_cast<pfunction>(&TestGMatrix::test8),"Test 8: Matrix*Matrix multiplication");
62   - add_test(static_cast<pfunction>(&TestGMatrix::test9),"Test 9: Assignment and arithmetics");
63   - add_test(static_cast<pfunction>(&TestGMatrix::test10),"Test 10: Matrix functions");
64   - add_test(static_cast<pfunction>(&TestGMatrix::test11),"Test 11: Matrix comparison");
65   -
66   - return;
67   -}
68 42  
69 43 /***************************************************************************
70   -* Initializer m_test *
71   -***************************************************************************/
72   -void TestGMatrix::init_matrix(void)
  44 + * @brief Set test matrix
  45 + ***************************************************************************/
  46 +GMatrix TestGMatrix::set_matrix(void) const
73 47 {
74   - double g_matrix[] = {1.0, 2.0, 3.0, 4.0,
75   - 5.0, 6.0, 7.0, 8.0,
76   - 9.0, 10., 11., 12.};
  48 + // Allocate matrix
  49 + GMatrix matrix(g_rows,g_cols);
77 50  
78   - for(int i=0;i<12;i++){
79   - m_g_matrix[i]=g_matrix[i];
  51 + // Set matrix values
  52 + for (int row = 0; row < g_rows; ++row) {
  53 + for (int col = 0; col < g_cols; ++col) {
  54 + matrix(row,col) = g_matrix[col+row*g_cols];
  55 + }
80 56 }
81 57  
82   - return;
  58 + // Return matrix
  59 + return matrix;
83 60 }
84 61  
85   -/***************************************************************************
86   -* Initializer m_vector *
87   -***************************************************************************/
88   -void TestGMatrix::init_vector(void)
89   -{
90   - double g_vector[] = {1.0, 2.0, 3.0, 4.0};
91   -
92   - for(int i=0;i<4;i++){
93   - m_g_vector[i]=g_vector[i];
94   - }
95   -
96   - return;
97   -}
98 62  
99 63 /***************************************************************************
100   - * Set test matrix *
  64 + * @brief Set test matrix with zero lines
101 65 ***************************************************************************/
102   -void TestGMatrix::set_matrix(void)
  66 +GMatrix TestGMatrix::set_matrix_zero(void) const
103 67 {
104   - GMatrix matrix(m_g_rows,m_g_cols);
105   - for (int row = 0; row < m_g_rows; ++row) {
106   - for (int col = 0; col < m_g_cols; ++col)
107   - matrix(row,col) = m_g_matrix[col+row*m_g_cols];
  68 + // Allocate matrix
  69 + GMatrix matrix(g_rows+1,g_cols+1);
  70 +
  71 + // Set matrix values
  72 + int i = 0;
  73 + for (int row = 0; row < g_rows+1; ++row) {
  74 + if (row == 2) continue;
  75 + int j = 0;
  76 + for (int col = 0; col < g_cols+1; ++col) {
  77 + if (col == 2) continue;
  78 + matrix(row,col) = g_matrix[j+i*g_cols];
  79 + j++;
  80 + }
  81 + i++;
108 82 }
109 83  
110   - m_test = matrix;
111   -
112   - return;
  84 + // Return matrix
  85 + return matrix;
113 86 }
114 87  
115 88  
116 89 /***************************************************************************
117   - * Set test vector *
  90 + * @brief Set test vector
118 91 ***************************************************************************/
119   -void TestGMatrix::set_vector(void)
  92 +GVector TestGMatrix::set_vector(void) const
120 93 {
121   - GVector vector(m_g_cols);
122   - for (int col = 0; col < m_g_cols; ++col){
123   - vector[col] = m_g_vector[col];
124   - }
  94 + // Allocate vector
  95 + GVector vector(g_cols);
125 96  
126   - v_test = vector;
  97 + // Set vector values
  98 + for (int col = 0; col < g_cols; ++col) {
  99 + vector[col] = g_vector[col];
  100 + }
127 101  
128   - return;
  102 + // Return vector
  103 + return vector;
129 104 }
130 105  
131   -void TestGMatrix::set_bigger(void)
132   -{
133   - bigger= GMatrix(m_g_rows+1,m_g_cols+1);
134   -}
  106 +
135 107 /***************************************************************************
136   - * Check test matrix *
  108 + * @brief Check if matrix corresponds to test matrix
  109 + *
  110 + * @param[in] matrix Matrix.
  111 + * @param[in] scale scale factor (default: 1.0).
  112 + * @param[in] offset offset value (default: 0.0).
  113 + *
  114 + * Checks if a matrix corresponds to the test matrix. Optionally, the test
  115 + * matrix can be scaled and an offset can be added.
137 116 ***************************************************************************/
138   -int TestGMatrix::check_matrix(const GMatrix& m, const double scale, const double add)
  117 +bool TestGMatrix::check_matrix(const GMatrix& matrix,
  118 + const double& scale,
  119 + const double& offset) const
139 120 {
140   - int result = 1;
141   -
142   - for (int row = 0; row < m_g_rows; ++row) {
143   - for (int col = 0; col < m_g_cols; ++col) {
144   - double value = m_g_matrix[col+row*m_g_cols] * scale + add;
145   - if (fabs(m(row,col)-value) > 1.0e-15) {
146   - result = 0;
  121 + // Initialise check with true
  122 + bool result = true;
  123 +
  124 + // Compare all matrix elements
  125 + for (int row = 0; row < g_rows; ++row) {
  126 + for (int col = 0; col < g_cols; ++col) {
  127 + double value = g_matrix[col+row*g_cols] * scale + offset;
  128 + if (std::abs(matrix(row,col)-value) > 1.0e-15) {
  129 + result = false;
147 130 break;
148   - }
149   - }
  131 + }
150 132 }
  133 + }
151 134  
  135 + // Return result
152 136 return result;
153 137 }
154 138  
155 139  
156 140 /***************************************************************************
157   - * Check transposed test matrix *
  141 + * @brief Check if transposed matrix corresponds to test matrix
  142 + *
  143 + * @param[in] matrix Trasposed matrix.
  144 + * @param[in] scale scale factor (default: 1.0).
  145 + * @param[in] offset offset value (default: 0.0).
  146 + *
  147 + * Checks if a matrix corresponds to the test matrix. Optionally, the test
  148 + * matrix can be scaled and an offset can be added.
158 149 ***************************************************************************/
159   -int TestGMatrix::check_transpose_matrix(const GMatrix& m, const double scale, const double add)
  150 +bool TestGMatrix::check_matrix_trans(const GMatrix& matrix,
  151 + const double& scale,
  152 + const double& offset) const
160 153 {
161   - int result = 1;
162   -
163   - for (int row = 0; row < m_g_rows; ++row) {
164   - for (int col = 0; col < m_g_cols; ++col) {
165   - double value = m_g_matrix[col+row*m_g_cols] * scale + add;
166   - if (m(col,row) != value) {
167   - result = 0;
  154 + // Initialise check with true
  155 + bool result = true;
  156 +
  157 + // Compare all matrix elements
  158 + for (int row = 0; row < g_rows; ++row) {
  159 + for (int col = 0; col < g_cols; ++col) {
  160 + double value = g_matrix[col+row*g_cols] * scale + offset;
  161 + if (std::abs(matrix(col,row)-value) > 1.0e-15) {
  162 + result = false;
168 163 break;
169   - }
170   - }
  164 + }
171 165 }
  166 + }
172 167  
  168 + // Return result
173 169 return result;
174 170 }
175 171  
176 172  
177 173 /***************************************************************************
178   - * Check full test matrix (lower triangle) *
  174 + * @brief Check lower triangle general matrix
  175 + *
  176 + * @param[in] matrix Matrix.
  177 + * @param[in] ref Reference matrix.
179 178 ***************************************************************************/
180   -int TestGMatrix::check_matrix_lt(const GMatrix& m, const double scale, const double add)
  179 +bool TestGMatrix::check_matrix_lt(const GMatrix& matrix,
  180 + const GMatrix& ref) const
181 181 {
182   - int result = 1;
183   - test_try("Check full test matrix (lower triangle)");
184   - try {
185   - for (int row = 0; row < m_g_rows; ++row) {
186   - for (int col = 0; col < m_g_cols; ++col) {
187   - double value = (col <= row) ? m_g_matrix[col+row*m_g_cols] * scale + add : 0.0;
188   - if (m(row,col) != value) {
189   - result = 0;
190   - break;
191   - }
192   - }
  182 + // Initialise check with true
  183 + bool result = true;
  184 +
  185 + // Compare all matrix elements
  186 + for (int row = 0; row < ref.rows(); ++row) {
  187 + for (int col = 0; col < ref.cols(); ++col) {
  188 + double value = (col <= row) ? ref(row,col) : 0.0;
  189 + if (matrix(row,col) != value) {
  190 + result = false;
  191 + break;
193 192 }
194   - test_try_success();
195   - }
196   - catch (std::exception &e) {
197   - test_try_failure(e);
198   - }
199   - return result;
200   -}
201   -
  193 + }
  194 + }
202 195  
203   -/***************************************************************************
204   - * Check full test matrix (upper triangle) *
205   - ***************************************************************************/
206   -int TestGMatrix::check_matrix_ut(const GMatrix& m, const double scale, const double add)
207   -{
208   - int result = 1;
209   - test_try("Check full test matrix (upper triangle)");
210   - try {
211   - for (int row = 0; row < m_g_rows; ++row) {
212   - for (int col = 0; col < m_g_cols; ++col) {
213   - double value = (col >= row) ? m_g_matrix[col+row*m_g_cols] * scale + add : 0.0;
214   - if (m(row,col) != value) {
215   - result = 0;
216   - break;
217   - }
218   - }
219   - }
220   - test_try_success();
221   - }
222   - catch (std::exception &e) {
223   - test_try_failure(e);
224   - }
  196 + // Return result
225 197 return result;
226 198 }
227 199  
228 200  
229 201 /***************************************************************************
230   - * Check matrix*vector *
  202 + * @brief Check upper triangle general matrix
  203 + *
  204 + * @param[in] matrix Matrix.
  205 + * @param[in] ref Reference matrix.
231 206 ***************************************************************************/
232   -int TestGMatrix::check_matrix_vector(const GVector& v)
  207 +bool TestGMatrix::check_matrix_ut(const GMatrix& matrix,
  208 + const GMatrix& ref) const
233 209 {
234   - int result = 1;
235   - test_try(" Check matrix*vector");
236   - try {
237   - for (int row = 0; row < v.size(); ++row) {
238   - double value = 0.0;
239   - for (int col = 0; col < m_g_cols; ++col)
240   - value += m_g_matrix[col+row*m_g_cols] * m_g_vector[col];
241   - if (v[row] != value) {
242   - result = 0;
  210 + // Initialise check with true
  211 + bool result = true;
  212 +
  213 + // Compare all matrix elements
  214 + for (int row = 0; row < ref.rows(); ++row) {
  215 + for (int col = 0; col < ref.cols(); ++col) {
  216 + double value = (col >= row) ? ref(row,col) : 0.0;
  217 + if (matrix(row,col) != value) {
  218 + result = false;
243 219 break;
244 220 }
245 221 }
246   - test_try_success();
247   - }
248   - catch (std::exception &e) {
249   - test_try_failure(e);
250   - }
251   - return result;
252   -}
253   -
254   -
255   -/***************************************************************************
256   - * Check matrix*matrix *
257   - ***************************************************************************/
258   -int TestGMatrix::check_matrix_matrix(const GMatrix& m)
259   -{
260   - if (m.rows() != m_g_rows || m.cols() != m_g_rows)
261   - return 0;
262   - int result = 1;
263   - test_try("Check matrix*matrix");
264   - try {
265   - for (int row = 0; row < m.rows(); ++row) {
266   - for (int col = 0; col < m.cols(); ++col) {
267   - double value = 0.0;
268   - for (int i = 0; i < m_g_cols; ++i)
269   - value += m_g_matrix[i+row*m_g_cols] * m_g_matrix[i+col*m_g_cols];
270   - if (m(row,col) != value) {
271   - result = 0;
272   - break;
273   - }
274   - }
275 222 }
276   - test_try_success();
277   - }
278   - catch (std::exception &e) {
279   - test_try_failure(e);
280   - }
281   - return result;
282   -}
283   -
284   -
285   -/***************************************************************************
286   - * Check matrix min *
287   - ***************************************************************************/
288   -int TestGMatrix::check_matrix_min(const double min)
289   -{
290   - double value = m_g_matrix[0];
291   - for (int row = 0; row < m_g_rows; ++row) {
292   - for (int col = 0; col < m_g_cols; ++col) {
293   - if (m_g_matrix[col+row*m_g_cols] < value)
294   - value = m_g_matrix[col+row*m_g_cols];
295   - }
296   - }
297   - test_assert(min==value, "Check matrix min");
298   - return (min == value);
299   -}
300 223  
301   -
302   -/***************************************************************************
303   - * Check matrix max *
304   - ***************************************************************************/
305   -int TestGMatrix::check_matrix_max(const double max)
306   -{
307   - double value = m_g_matrix[0];
308   - for (int row = 0; row < m_g_rows; ++row) {
309   - for (int col = 0; col < m_g_cols; ++col) {
310   - if (m_g_matrix[col+row*m_g_cols] > value)
311   - value = m_g_matrix[col+row*m_g_cols];
312   - }
313   - }
314   - test_assert(max==value,"Check matrix max");
315   - return (max == value);
  224 + // Return result
  225 + return result;
316 226 }
317 227  
318 228  
319   -/***************************************************************************
320   - * Check matrix sum *
321   - ***************************************************************************/
322   -int TestGMatrix::check_matrix_sum(const double sum)
  229 +/***********************************************************************//**
  230 + * @brief Set parameters and tests
  231 + **************************************************************************/
  232 +void TestGMatrix::set(void)
323 233 {
324   - double value = 0.0;
325   - for (int row = 0; row < m_g_rows; ++row) {
326   - for (int col = 0; col < m_g_cols; ++col)
327   - value += m_g_matrix[col+row*m_g_cols];
328   - }
329   - test_assert(sum==value,"Check matrix sum");
330   - return (sum == value);
331   -}
  234 + // Set test name
  235 + name("GMatrix");
332 236  
  237 + // Add tests
  238 + append(static_cast<pfunction>(&TestGMatrix::alloc_matrix), "Test matrix allocation");
  239 + append(static_cast<pfunction>(&TestGMatrix::assign_values), "Test value assignment");
  240 + append(static_cast<pfunction>(&TestGMatrix::copy_matrix), "Test matrix copying");
  241 + append(static_cast<pfunction>(&TestGMatrix::matrix_operations), "Test matrix operations");
  242 + append(static_cast<pfunction>(&TestGMatrix::matrix_arithmetics), "Test matrix arithmetics");
  243 + append(static_cast<pfunction>(&TestGMatrix::matrix_functions), "Test matrix functions");
  244 + append(static_cast<pfunction>(&TestGMatrix::matrix_compare), "Test matrix comparisons");
  245 + //append(static_cast<pfunction>(&TestGMatrix::matrix_cholesky), "Test matrix Cholesky decomposition");
  246 + append(static_cast<pfunction>(&TestGMatrix::matrix_print), "Test matrix printing");
  247 +
  248 + // Set members
  249 + m_test = set_matrix();
  250 + v_test = set_vector();
  251 + m_bigger = GMatrix(g_rows+1, g_cols+1);
333 252  
334   -/***************************************************************************
335   - * Test: Output *
336   - ***************************************************************************/
337   -void TestGMatrix::test_output(void)
338   -{
339   - std::cout << "Output test matrix"<<std::endl<< m_test << std::endl;
  253 + // Return
  254 + return;
340 255 }
341 256  
342 257  
343   -/***************************************************************************
344   - * Test: Conversion between matrix types *
  258 +/***********************************************************************//**
  259 + * @brief Test matrix allocation
345 260 ***************************************************************************/
346   -void TestGMatrix::test_conversion(void)
  261 +void TestGMatrix::alloc_matrix(void)
347 262 {
348   - //
349   - // Setup a symmetric matrix
350   - int num = 10;
351   - GMatrix symmetric(num,num);
352   - for (int i = 0; i < num; ++i) {
353   - for (int j = 0; j < num; ++j)
354   - symmetric(i,j) = (i+j+1)/2.0;
355   - }
356   -
357   - //
358   - // Convert symmetric matrix into GSymMatrix object
359   - // GSymMatrix converted = sym_matrix(symmetric);
360   - GSymMatrix converted = GSymMatrix(symmetric);
361   -
362   - //
363   - // Convert GSymMatrix back to full matrix
364   - GMatrix back_convert = matrix(converted);
365   -
366   - //
367   - // Compare back converted matrix to original one. They should be identical
368   - test_assert(symmetric == back_convert,"Compare back converted matrix to original one");
369   - //
370   - // Determine the fill of the matrix. It should be 1.0
371   - double fill = back_convert.fill();
372   - test_assert(fabs(fill-1.0) <= 1.0e-15,"Test the fill of the matrix","Bad fill "+str(fill)+" determined (expected 1.0).");
373   - //
374   - // Extract lower triangle and check values
375   - GMatrix lower = symmetric.extract_lower_triangle();
376   - int ok = 1;
377   - for (int j = 1; j < num; ++j) {
378   - for (int i = 0; i < j; ++i) {
379   - if (lower(i,j) != 0.0)
380   - ok = 0;
381   - }
382   - }
383   - for (int j = 0; j < num; ++j) {
384   - for (int i = j; i < num; ++i) {
385   - if (lower(i,j) != symmetric(i,j))
386   - ok = 0;
387   - }
388   - }
389   - test_assert(ok,"Extract lower triangle");
390   -
391   - //
392   - // Extract upper triangle and check values
393   - GMatrix upper = symmetric.extract_upper_triangle();
394   - ok = 1;
395   - for (int j = 0; j < num; ++j) {
396   - for (int i = j+1; i < num; ++i) {
397   - if (upper(i,j) != 0.0)
398   - ok = 0;
399   - }
400   - }
401   - for (int j = 0; j < num; ++j) {
402   - for (int i = 0; i <= j; ++i) {
403   - if (upper(i,j) != symmetric(i,j))
404   - ok = 0;
405   - }
406   - }
407   -
408   - test_assert(ok,"Extract upper triangle","Corrupt extract_upper_triangle.");
409   -
410   - //
411   - // Now make the matrix unsymmetric
412   - symmetric(0,num-1) = 1000.0;
413   - //
414   - // Try converting now into GSymMatrix object (this should fail)
415   - test_try("Try converting now into GSymMatrix object");
  263 + // Allocate zero matrix. The allocation should fail.
  264 + test_try("Allocate zero matrix");
416 265 try {
417   - converted = sym_matrix(symmetric);
418   - test_try_failure();
  266 + GMatrix test(0,0);
  267 + test_try_failure("Expected GException::empty exception.");
419 268 }
420   - catch (GException::matrix_not_symmetric &e) {
  269 + catch (GException::empty &e) {
421 270 test_try_success();
422 271 }
423 272 catch (std::exception &e) {
424 273 test_try_failure(e);
425 274 }
426   - //
427   - // Now zero some elements to emulate a sparse matrix
428   - symmetric(0,num-1) = 0.0;
429   - for (int i = 5; i < 8; ++i) {
430   - for (int j = i-2; j < i+2; ++j)
431   - symmetric(i,j) = 0.0;
432   - }
433   -
434   - //
435   - // Convert symmetric matrix into GSparseMatrix object
436   - GSparseMatrix sparse = sparse_matrix(symmetric);
437   - //
438   - // Convert GSparseMatrix back to full matrix
439   - back_convert = matrix(sparse);
440   - //
441   - // Compare back converted matrix to original one. They should be identical
442   - test_assert(symmetric == back_convert,
443   - "Compare back converted matrix to original one",
444   - "Unable to convert matrixes (sparse)");
445 275  
446 276 // Return
447 277 return;
448 278 }
449 279  
450 280  
451   -/***************************************************************************
452   - * Test: extraction and insertion *
  281 +/***********************************************************************//**
  282 + * @brief Test value assignment
453 283 ***************************************************************************/
454   -void TestGMatrix::test_extract(void)
  284 +void TestGMatrix::assign_values(void)
455 285 {
456   -
457   - //
458   - // Set-up test matrix
459   - int rows = 10;
460   - int cols = 20;
461   - GMatrix test(rows, cols);
462   -
463   - //
464   - // Add and extract column vectors
465   - test_try("Add and extract column vectors");
466   - try
467   - {
468   - for (int col = 0; col < cols; ++col) {
469   - GVector column(rows);
470   - for (int row = 0; row < rows; ++row)
471   - column[row] = (col+1)*100.0 + (row+1)*1.0;
472   - test.add_col(column, col);
473   - GVector check = test.extract_col(col);
474   - if (check != column) {
475   - throw exception_failure("Unable to add and extract columns.\nAdded column ...: "+column.print()+"\nExtracted column: "+check.print());
476   - }
  286 + // Setup 3x3 matrix
  287 + GMatrix test(3,3);
  288 +
  289 + // Assignment individual values
  290 + for (int i = 0; i < 3; ++i) {
  291 + for (int k = 0; k < 3; ++k) {
  292 + double value = i*2.0 + k*2.0;
  293 + test(i,k) = value;
477 294 }
478   - test_try_success();
479   - }
480   - catch(std::exception& e)
481   - {
482   - test_try_failure(e);
483 295 }
484 296  
485   - //
486   - // Insert and extract column vectors
487   - test_try("Insert and extract column vectors");
488   - try
489   - {
490   - for (int col = 0; col < cols; ++col) {
491   - GVector column(rows);
492   - for (int row = 0; row < rows; ++row)
493   - column[row] = (col+1)*100.0 + (row+1)*1.0;
494   - test.insert_col(column, col);
495   - GVector check = test.extract_col(col);
496   - if (check != column) {
497   - throw exception_failure("Unable to insert and extract columns.\nIserted column ...: "+column.print()+"\nExtracted column: "+check.print());
498   - }
  297 + // Check assignment of individual values
  298 + for (int i = 0; i < 3; ++i) {
  299 + for (int k = 0; k < 3; ++k) {
  300 + double value = i*2.0 + k*2.0;
  301 + test_value(test(i,k), value, 1.0e-10, "Test matrix element assignment");
499 302 }
500   - test_try_success();
501   - }
502   - catch(std::exception& e)
503   - {
504   - test_try_failure(e);
505 303 }
506 304  
507   - //
508   - // Extract rows
509   - test_try("Extract rows");
510   - try
511   - {
512   - for (int row = 0; row < rows; ++row) {
513   - GVector v_row(cols);
514   - for (int col = 0; col < cols; ++col)
515   - v_row[col] = (col+1)*100.0 + (row+1)*1.0;
516   - GVector check = test.extract_row(row);
517   - if (check != v_row) {
518   - throw exception_failure("Unable to extract rows.\nIserted row ...: "+v_row.print()+"\nExtracted row: "+check.print());
519   - }
520   - }
521   -
  305 + // Verify range checking
  306 + #ifdef G_RANGE_CHECK
  307 + test_try("Verify range checking");
  308 + try {
  309 + test(3,3) = 1.0;
  310 + test_try_failure("Expected GException::out_of_range exception.");
  311 + }
  312 + catch (GException::out_of_range &e) {
522 313 test_try_success();
523 314 }
524   - catch(std::exception& e)
525   - {
  315 + catch (std::exception &e) {
526 316 test_try_failure(e);
527 317 }
  318 + #endif
528 319  
529   -}
530   -
531   -// Test 1: Allocate zero matrix
532   -void TestGMatrix::test1(void)
533   -{
534   - GMatrix test1(0,0);
535   -
  320 + // Return
536 321 return;
537 322 }
538 323  
539   -// Test 2: Allocate too large matrix
540   -void TestGMatrix::test2(void)
  324 +
  325 +/***********************************************************************//**
  326 + * @brief Test matrix copy
  327 + ***************************************************************************/
  328 +void TestGMatrix::copy_matrix(void)
541 329 {
542   - //GMatrix test2(100000,100000);
  330 + // Copy matrix
  331 + GMatrix test = m_test;
  332 +
  333 + // Test if original and compied matrices are correct
  334 + test_assert(check_matrix(m_test), "Test source matrix");
  335 + test_assert(check_matrix(test), "Test matrix copy operator",
  336 + "Found:\n"+test.print()+"\nExpected:\n"+m_test.print());
543 337  
  338 + // Return
544 339 return;
545 340 }
546 341  
547   -// Test 3: Assign values
548   -void TestGMatrix::test3(void)
  342 +
  343 +/***********************************************************************//**
  344 + * @brief Test matrix operations
  345 + *
  346 + * Tests matrix*vector and matrix*matrix multiplication operations.
  347 + ***************************************************************************/
  348 +void TestGMatrix::matrix_operations(void)
549 349 {
550   - GMatrix test3(3,3);
551   - test3(1,1) = 1.0;
552   - test_assert(test3(0,0) == 0.0 && test3(1,0) == 0.0 && test3(2,0) == 0.0 &&
553   - test3(0,1) == 0.0 && test3(1,1) == 1.0 && test3(2,1) == 0.0 &&
554   - test3(0,2) == 0.0 && test3(1,2) == 0.0 && test3(2,2) == 0.0,"Assign value");
555   -
556   - #if defined(G_RANGE_CHECK)
557   - test_try("Range check");
558   - try {
559   - GMatrix test3(3,3);
560   - test3(3,3) = 1.0;
561   - test_try_failure();
562   - }
563   - catch (GException::out_of_range &e) {
564   - test_try_success();
  350 + // Perform vector multiplication
  351 + GVector test1 = m_test * v_test;
  352 +
  353 + // Check if the result vector is as expected
  354 + GVector ref1 = test1;
  355 + bool result = true;
  356 + for (int row = 0; row < g_rows; ++row) {
  357 + double value = 0.0;
  358 + for (int col = 0; col < g_cols; ++col) {
  359 + value += g_matrix[col+row*g_cols] * g_vector[col];
565 360 }
566   - catch (std::exception &e) {
567   - test_try_failure(e);
  361 + ref1[row] = value;
  362 + if (test1[row] != value) {
  363 + result = false;
  364 + break;
568 365 }
569   - #endif
  366 + }
570 367  
571   - return;
572   -}
  368 + // Test if original matrix and result vector are correct
  369 + test_assert(check_matrix(m_test), "Test source matrix");
  370 + test_assert(result, "Test matrix*vector multiplication",
  371 + "Found:\n"+test1.print()+"\nExpected:\n"+ref1.print());
573 372  
574   -// Test 4: Matrix copy constructor
575   -void TestGMatrix::test4(void)
576   -{
577   - GMatrix test4 = m_test;
578   - if (!check_matrix(test4, 1.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
579   - throw exception_failure("Corrupt copy constructor");
  373 + // Test incompatible vector multiplication
  374 + test_try("Test incompatible matrix*vector multiplication");
  375 + try {
  376 + GVector test2 = m_bigger * v_test;
  377 + test_try_failure("Expected GException::matrix_vector_mismatch exception.");
  378 + }
  379 + catch (GException::matrix_vector_mismatch &e) {
  380 + test_try_success();
  381 + }
  382 + catch (std::exception &e) {
  383 + test_try_failure(e);
  384 + }
  385 +
  386 + // Test matrix multiplication
  387 + GMatrix test3 = m_test * transpose(m_test);
  388 +
  389 + // Check if the result matrix is as expected
  390 + GMatrix ref3 = test3;
  391 + result = true;
  392 + for (int row = 0; row < test3.rows(); ++row) {
  393 + for (int col = 0; col < test3.cols(); ++col) {
  394 + double value = 0.0;
  395 + for (int i = 0; i < g_cols; ++i) {
  396 + value += g_matrix[i+row*g_cols] * g_matrix[i+col*g_cols];
  397 + }
  398 + ref3(row,col) = value;
  399 + if (test3(row,col) != value) {
  400 + result = false;
  401 + break;
  402 + }
  403 + }
580 404 }
581 405  
582   - return;
583   -}
  406 + // Test if original matrix and result matrix are correct
  407 + test_assert(check_matrix(m_test), "Test source matrix");
  408 + test_assert(result, "Test matrix multiplication",
  409 + "Found:\n"+test3.print()+"\nExpected:\n"+ref3.print());
  410 + test_value(test3.rows(), g_rows, "Test number of rows of result matrix");
  411 + test_value(test3.cols(), g_rows, "Test number of columns of result matrix");
584 412  
585   -// Test 5: Matrix assignment
586   -void TestGMatrix::test5(void)
587   -{
588   - //
589   - // GMatrix = GMatrix
590   - result = m_test;
591   - if (!check_matrix(result, 1.0, 0.0) || !check_matrix(m_test, 1.0, 0.0)) {
592   - throw exception_failure("Corrupt assignment");
  413 + // Test incompatible matrix multiplication
  414 + test_try("Test incompatible matrix multiplication");
  415 + try {
  416 + GMatrix test4 = m_bigger * m_test;
  417 + test_try_failure("Expected GException::matrix_mismatch exception.");
  418 + }
  419 + catch (GException::matrix_mismatch &e) {
  420 + test_try_success();
  421 + }
  422 + catch (std::exception &e) {
  423 + test_try_failure(e);
593 424 }
594   - //
595   - // GMatrix = GMatrix (bigger matrix)
596   - result = bigger;
597 425  
  426 + // Test another incompatible matrix multiplication
  427 + test_try("Test incompatible matrix multiplication");
  428 + try {
  429 + GMatrix test5 = m_bigger * m_test;
  430 + test_try_failure("Expected GException::matrix_mismatch exception.");
  431 + }
  432 + catch (GException::matrix_mismatch &e) {
  433 + test_try_success();
  434 + }
  435 + catch (std::exception &e) {
  436 + test_try_failure(e);
  437 + }
  438 +
  439 + // Return
598 440 return;
599 441 }
600 442  
601   -// Test 6: Transposition
602   -void TestGMatrix::test6(void)
603   -{
604   - //
605   - // transpose(GMatrix)
606   - result = transpose(m_test);
607   - test_assert(check_transpose_matrix(result, 1.0, 0.0) && check_matrix(m_test, 1.0, 0.0),"transpose(GMatrix)","Corrupt transpose(GMatrix) function.");
608   - //
609   - // GMatrix.transpose()
610   - result = m_test;
611   - result.transpose();
612   - test_assert(check_transpose_matrix(result, 1.0, 0.0) && check_matrix(m_test, 1.0, 0.0),"GMatrix.transpose()","Corrupt GMatrix.transpose() function.");
613   -}
614 443  
615   -// Test 7: Matrix*Vector multiplication
616   -void TestGMatrix::test7(void)
  444 +/***********************************************************************//**
  445 + * @brief Test matrix arithmetics
  446 + *
  447 + * Tests matrix arithmetics.
  448 + ***************************************************************************/
  449 +void TestGMatrix::matrix_arithmetics(void)
617 450 {
618   - GVector v_test7 = m_test*v_test;
619   - test_assert(check_matrix_vector(v_test7) && check_matrix(m_test, 1.0, 0.0),"","Corrupt Matrix*Vector multiplication");
620   -
621   - test_try("Bigger*Vector");
  451 + // -GMatrix
  452 + GMatrix test = -m_test;
  453 + test_assert(check_matrix(m_test), "Test source matrix");
  454 + test_assert(check_matrix(test, -1.0, 0.0), "Test -GMatrix",
  455 + "Unexpected result matrix:\n"+test.print());
  456 +
  457 + // GMatrix += GMatrix
  458 + test = m_test;
  459 + test += m_test;
  460 + test_assert(check_matrix(m_test), "Test source matrix");
  461 + test_assert(check_matrix(test, 2.0, 0.0), "Test GMatrix += GMatrix",
  462 + "Unexpected result matrix:\n"+test.print());
  463 +
  464 + // GMatrix -= GMatrix
  465 + test = m_test;
  466 + test -= m_test;
  467 + test_assert(check_matrix(m_test), "Test source matrix");
  468 + test_assert(check_matrix(test, 0.0, 0.0), "Test GMatrix -= GMatrix",
  469 + "Unexpected result matrix:\n"+test.print());
  470 +
  471 + // GMatrix *= 3.0
  472 + test = m_test;
  473 + test *= 3.0;
  474 + test_assert(check_matrix(m_test), "Test source matrix");
  475 + test_assert(check_matrix(test, 3.0, 0.0), "Test GMatrix *= 3.0",
  476 + "Unexpected result matrix:\n"+test.print());
  477 +
  478 + // GMatrix /= 3.0
  479 + test = m_test;
  480 + test /= 3.0;
  481 + test_assert(check_matrix(m_test), "Test source matrix");
  482 + test_assert(check_matrix(test, 1.0/3.0, 0.0), "Test GMatrix /= 3.0",
  483 + "Unexpected result matrix:\n"+test.print());
  484 +
  485 + // GMatrix + GMatrix
  486 + test = m_test + m_test;
  487 + test_assert(check_matrix(m_test), "Test source matrix");
  488 + test_assert(check_matrix(test, 2.0, 0.0), "Test GMatrix + GMatrix",
  489 + "Unexpected result matrix:\n"+test.print());
  490 +
  491 + // GMatrix - GMatrix
  492 + test = m_test - m_test;
  493 + test_assert(check_matrix(m_test), "Test source matrix");
  494 + test_assert(check_matrix(test, 0.0, 0.0), "Test GMatrix - GMatrix",
  495 + "Unexpected result matrix:\n"+test.print());
  496 +
  497 + // GMatrix * 3.0
  498 + test = m_test * 3.0;
  499 + test_assert(check_matrix(m_test), "Test source matrix");
  500 + test_assert(check_matrix(test, 3.0, 0.0), "Test GMatrix * 3.0",
  501 + "Unexpected result matrix:\n"+test.print());
  502 +
  503 + // 3.0 * GMatrix
  504 + test = 3.0 * m_test;
  505 + test_assert(check_matrix(m_test), "Test source matrix");
  506 + test_assert(check_matrix(test, 3.0, 0.0), "Test 3.0 * GMatrix",
  507 + "Unexpected result matrix:\n"+test.print());
  508 +
  509 + // GMatrix / 3.0
  510 + test = m_test / 3.0;
  511 + test_assert(check_matrix(m_test), "Test source matrix");
  512 + test_assert(check_matrix(test, 1.0/3.0, 0.0), "Test GMatrix / 3.0",
  513 + "Unexpected result matrix:\n"+test.print());
  514 +
  515 + // Test invalid matrix addition
  516 + test_try("Test invalid matrix addition");
622 517 try {
623   - GVector v_test7 = bigger*v_test;
624   - test_try_failure();
  518 + test = m_test;
  519 + test += m_bigger;
  520 + test_try_failure("Expected GException::matrix_mismatch exception.");
625 521 }
626   - catch (GException::matrix_vector_mismatch &e) {
  522 + catch (GException::matrix_mismatch &e) {
627 523 test_try_success();
628 524 }
629 525 catch (std::exception &e) {
630 526 test_try_failure(e);
631 527 }
632 528  
  529 + // Return
633 530 return;
634 531 }
635 532  
636   -// Test 8: Matrix*Matrix multiplication
637   -void TestGMatrix::test8(void)
  533 +
  534 +/***********************************************************************//**
  535 + * @brief Test matrix functions
  536 + *
  537 + * Tests matrix functions.
  538 + ***************************************************************************/
  539 +void TestGMatrix::matrix_functions(void)
638 540 {
639   - GMatrix m_test8 = m_test * transpose(m_test);
640   - test_assert(check_matrix_matrix(m_test8) && check_matrix(m_test, 1.0, 0.0),"","Corrupt Matrix*Matrix multiplication");
  541 + // Minimum
  542 + double min = m_test.min();
  543 +
  544 + // Check mimimum
  545 + double value = g_matrix[0];
  546 + for (int row = 0; row < g_rows; ++row) {
  547 + for (int col = 0; col < g_cols; ++col) {
  548 + if (g_matrix[col+row*g_cols] < value) {
  549 + value = g_matrix[col+row*g_cols];
  550 + }
  551 + }
  552 + }
  553 + test_value(min, value, 0.0, "Test minimum function");
  554 +
  555 + // Maximum
  556 + double max = m_test.max();
  557 +
  558 + // Check maximum
  559 + value = g_matrix[0];
  560 + for (int row = 0; row < g_rows; ++row) {
  561 + for (int col = 0; col < g_cols; ++col) {
  562 + if (g_matrix[col+row*g_cols] > value) {
  563 + value = g_matrix[col+row*g_cols];
  564 + }
  565 + }
  566 + }
  567 + test_value(max, value, 0.0, "Test maximum function");
641 568  
642   - test_try("Bigger*Matrix multiplication");
  569 + // Sum
  570 + double sum = m_test.sum();
  571 +
  572 + // Check sum
  573 + value = 0.0;
  574 + for (int row = 0; row < g_rows; ++row) {
  575 + for (int col = 0; col < g_cols; ++col) {
  576 + value += g_matrix[col+row*g_cols];
  577 + }
  578 + }
  579 + test_value(sum, value, 1.0e-20, "Test sum function");
  580 +
  581 + // Transpose function
  582 + GMatrix test1 = transpose(m_test);
  583 + test_assert(check_matrix(m_test), "Test source matrix");
  584 + test_assert(check_matrix_trans(test1, 1.0, 0.0),
  585 + "Test transpose(GMatrix) function",
  586 + "Unexpected transposed matrix:\n"+test1.print());
  587 +
  588 + // Transpose method
  589 + test1 = m_test;
  590 + test1.transpose();
  591 + test_assert(check_matrix(m_test), "Test source matrix");
  592 + test_assert(check_matrix_trans(test1, 1.0, 0.0),
  593 + "Test GMatrix.transpose() method",
  594 + "Unexpected transposed matrix:\n"+test1.print());
  595 +
  596 + // Convert to general matrix
  597 + GMatrix test2 = GMatrix(m_test);
  598 + test_assert(check_matrix(m_test), "Test source matrix");
  599 + test_assert(check_matrix(test2, 1.0, 0.0),
  600 + "Test GMatrix(GMatrix) constructor",
  601 + "Unexpected GMatrix:\n"+test2.print());
  602 +
  603 + // Try extracting of lower triangle
  604 + test_try("Try extracting of lower triangle");
643 605 try {
644   - GMatrix m_test8 = m_test*bigger;
  606 + test2 = m_test.extract_lower_triangle();
  607 + test_try_failure("Expected GException::matrix_not_square exception.");
  608 + }
  609 + catch (GException::matrix_not_square &e) {
645 610 test_try_success();
646 611 }
647 612 catch (std::exception &e) {
648 613 test_try_failure(e);
649 614 }
650 615  
651   - test_try("Bigger*Matrix multiplication 2");
  616 + // Try extracting of upper triangle
  617 + test_try("Try extracting of lower triangle");
652 618 try {
653   - GMatrix m_test8 = bigger*m_test;
654   - test_try_failure();
  619 + test2 = m_test.extract_upper_triangle();
  620 + test_try_failure("Expected GException::matrix_not_square exception.");
655 621 }
656   - catch (GException::matrix_mismatch &e) {
  622 + catch (GException::matrix_not_square &e) {
657 623 test_try_success();
658 624 }
659 625 catch (std::exception &e) {
660 626 test_try_failure(e);
661 627 }
  628 +
  629 + // Extract lower triangle for square matrix
  630 + GMatrix test3 = m_test * transpose(m_test);
  631 + GMatrix test4 = test3.extract_lower_triangle();
  632 + test_assert(check_matrix_lt(test4, test3),
  633 + "Test GMatrix.extract_lower_triangle() method",
  634 + "Unexpected lower triangle:\n"+test4.print());
  635 +
  636 + // Extract upper triangle
  637 + test4 = test3.extract_upper_triangle();
  638 + test_assert(check_matrix_ut(test4, test3),
  639 + "Test GMatrix.extract_upper_triangle() method",
  640 + "Unexpected lower triangle:\n"+test4.print());
662 641  
  642 + // Return
663 643 return;
664 644 }
665 645  
666   -// Test 9: Assignment and arithmetics
667   -void TestGMatrix::test9(void)
  646 +
  647 +/***********************************************************************//**
  648 + * @brief Test matrix comparisons
  649 + ***************************************************************************/
  650 +void TestGMatrix::matrix_compare(void)
668 651 {
669   - //
670   - // -GMatrix
671   - result = -m_test;
672   - test_assert(check_matrix(result, -1.0, 0.0)&&check_matrix(m_test, 1.0, 0.0),"-GMatrix","Corrupt -GMatrix operator.");
673   -
674   - //
675   - // GMatrix += GMatrix
676   - result = m_test;
677   - result += m_test;
678   - test_assert(check_matrix(result, 2.0, 0.0) && check_matrix(m_test, 1.0, 0.0),"GMatrix += GMatrix","Corrupt GMatrix += GMatrix operator.");
679   -
680   - //
681   - // GMatrix -= GMatrix
682   - result = m_test;
683   - result -= m_test;
684   - test_assert(check_matrix(result, 0.0, 0.0) && check_matrix(m_test, 1.0, 0.0),"GMatrix -= GMatrix","Corrupt GMatrix -= GMatrix operator.");
685   -
686   - //
687   - // GMatrix *= 3.0
688   - result = m_test;
689   - result *= 3.0;
690   - test_assert(check_matrix(result, 3.0, 0.0) && check_matrix(m_test, 1.0, 0.0),"GMatrix *= 3.0","Corrupt GMatrix *= double operator.");
691   -
692   - //
693   - // GMatrix /= 3.0
694   - result = m_test;
695   - result /= 3.0;
696   - test_assert(check_matrix(result, 1.0/3.0, 0.0) && check_matrix(m_test, 1.0, 0.0),"GMatrix /= 3.0","Corrupt GMatrix /= double operator.");
697   -
698   - //
699   - // GMatrix + GMatrix
700   - result = m_test + m_test;
701   - test_assert(check_matrix(result, 2.0, 0.0) && check_matrix(m_test, 1.0, 0.0),"GMatrix + GMatrix","Corrupt GMatrix + GMatrix operator.");
702   -
703   - //
704   - // GMatrix - GMatrix
705   - result = m_test - m_test;
706   - test_assert(check_matrix(result, 0.0, 0.0) && check_matrix(m_test, 1.0, 0.0),"GMatrix - GMatrix","Corrupt GMatrix - GMatrix operator.");
707   -
708   - // GMatrix * 3.0
709   - result = m_test * 3.0;
710   - test_assert(check_matrix(result, 3.0, 0.0) && check_matrix(m_test, 1.0, 0.0),"GMatrix * 3.0","Corrupt GMatrix * double operator.");
711   -
712   - //
713   - // 3.0 * GMatrix
714   - result = 3.0 * m_test;
715   - test_assert(check_matrix(result, 3.0, 0.0) && check_matrix(m_test, 1.0, 0.0),"3.0 * GMatrix","Corrupt double * GMatrix operator.");
716   -
717   - //
718   - // GMatrix / 3.0
719   - result = m_test / 3.0;
720   - test_assert(check_matrix(result, 1.0/3.0, 0.0) && check_matrix(m_test, 1.0, 0.0),"GMatrix / 3.0","Corrupt GMatrix / double operator.");
721   -
722   -
723   - test_try("Test += with bigger");
724   - try {
725   - result = m_test;
726   - result += bigger;
727   - test_try_failure();
728   - }
729   - catch (GException::matrix_mismatch &e) {
730   - test_try_success();
731   - }
732   - catch (std::exception &e) {
733   - test_try_failure(e);
734   - }
  652 + // Allocate an empty matrix
  653 + GMatrix empty(g_rows,g_cols);
  654 +
  655 + // Test operators
  656 + test_assert((m_test == m_test), "Test == operator");
  657 + test_assert(!(m_test == empty), "Test == operator");
  658 + test_assert(!(m_test == m_bigger), "Test == operator");
  659 + test_assert(!(m_test != m_test), "Test != operator");
  660 + test_assert((m_test != empty), "Test != operator");
  661 + test_assert((m_test != m_bigger), "Test != operator");
735 662  
  663 + // Return
736 664 return;
737 665 }
738 666  
739   -// Test 10: Matrix functions
740   -void TestGMatrix::test10(void){
741   - //
742   - double min = m_test.min();
743   - test_assert(check_matrix_min(min),"Test min","Corrupt GMatrix.min() function.");
744 667  
745   - //
746   - double max = m_test.max();
747   - test_assert(check_matrix_max(max),"Test max","Corrupt GMatrix.max() function.");
748   -
749   - //
750   - double sum = m_test.sum();
751   - test_assert(check_matrix_sum(sum),"Test sum","Corrupt GMatrix.sum() function.");
  668 +/***********************************************************************//**
  669 + * @brief Test Cholesky decomposition
  670 + ***************************************************************************/
  671 +/*
  672 +void TestGMatrix::matrix_cholesky(void)
  673 +{
  674 + // Test Cholesky decomposition
  675 + GMatrix cd = cholesky_decompose(m_test);
  676 + GMatrix cd_lower = cd.extract_lower_triangle();
  677 + GMatrix cd_upper = transpose(cd_lower);
  678 + GMatrix cd_product = cd_lower * cd_upper;
  679 + GMatrix cd_residuals = matrix(m_test) - cd_product;
  680 + double res = (abs(cd_residuals)).max();
  681 + test_value(res, 0.0, 1.0e-15, "Test cholesky_decompose() method");
  682 +
  683 + // Test compressed Cholesky decomposition
  684 + GMatrix test_zero = set_matrix_zero();
  685 + GMatrix cd_zero = cholesky_decompose(test_zero);
  686 + GMatrix cd_zero_lower = cd_zero.extract_lower_triangle();
  687 + GMatrix cd_zero_upper = transpose(cd_zero_lower);
  688 + GMatrix cd_zero_product = cd_zero_lower * cd_zero_upper;
  689 + GMatrix cd_zero_residuals = matrix(test_zero) - cd_zero_product;
  690 + res = (abs(cd_zero_residuals)).max();
  691 + test_value(res, 0.0, 1.0e-15, "Test compressed cholesky_decompose() method");
  692 +
  693 + // Test Cholesky inplace decomposition
  694 + GMatrix test = m_test;
  695 + test.cholesky_decompose();
  696 + GMatrix cd_lower2 = test.extract_lower_triangle();
  697 + test_assert((cd_lower2 == cd_lower), "Test inplace cholesky_decompose() method");
  698 +
  699 + // Test Cholesky solver (first test)
  700 + GVector e0(g_rows);
  701 + GVector a0(g_rows);
  702 + e0[0] = 1.0;
  703 + e0[1] = 0.0;
  704 + e0[2] = 0.0;
  705 + a0[0] = g_matrix[0];
  706 + a0[1] = g_matrix[3];
  707 + a0[2] = g_matrix[6];
  708 + GVector s0 = cd.cholesky_solver(a0) - e0;
  709 + res = max(abs(s0));
  710 + test_value(res, 0.0, 1.0e-15, "Test cholesky_solver() method");
  711 +
  712 + // Test Cholesky solver (second test)
  713 + e0[0] = 0.0;
  714 + e0[1] = 1.0;
  715 + e0[2] = 0.0;
  716 + a0[0] = g_matrix[1];
  717 + a0[1] = g_matrix[4];
  718 + a0[2] = g_matrix[7];
  719 + s0 = cd.cholesky_solver(a0) - e0;
  720 + res = max(abs(s0));
  721 + test_value(res, 0.0, 1.0e-15, "Test cholesky_solver() method");
  722 +
  723 + // Test Cholesky solver (third test)
  724 + e0[0] = 0.0;
  725 + e0[1] = 0.0;
  726 + e0[2] = 1.0;
  727 + a0[0] = g_matrix[2];
  728 + a0[1] = g_matrix[5];
  729 + a0[2] = g_matrix[8];
  730 + s0 = cd.cholesky_solver(a0) - e0;
  731 + res = max(abs(s0));
  732 + test_value(res, 0.0, 1.0e-15, "Test cholesky_solver() method");
  733 +
  734 + // Test compressed Cholesky solver (first test)
  735 + e0 = GVector(g_rows+1);
  736 + a0 = GVector(g_rows+1);
  737 + e0[0] = 1.0;
  738 + e0[1] = 0.0;
  739 + e0[2] = 0.0;
  740 + e0[3] = 0.0;
  741 + a0[0] = g_matrix[0];
  742 + a0[1] = g_matrix[3];
  743 + a0[2] = 0.0;
  744 + a0[3] = g_matrix[6];
  745 + s0 = cd_zero.cholesky_solver(a0) - e0;
  746 + res = max(abs(s0));
  747 + test_value(res, 0.0, 1.0e-15, "Test compressed cholesky_solver() method");
  748 +
  749 + // Test compressed Cholesky solver (second test)
  750 + e0[0] = 0.0;
  751 + e0[1] = 1.0;
  752 + e0[2] = 0.0;
  753 + e0[3] = 0.0;
  754 + a0[0] = g_matrix[1];
  755 + a0[1] = g_matrix[4];
  756 + a0[2] = 0.0;
  757 + a0[3] = g_matrix[7];
  758 + s0 = cd_zero.cholesky_solver(a0) - e0;
  759 + res = max(abs(s0));
  760 + test_value(res, 0.0, 1.0e-15, "Test compressed cholesky_solver() method");
  761 +
  762 + // Test compressed Cholesky solver (third test)
  763 + e0[0] = 0.0;
  764 + e0[1] = 0.0;
  765 + e0[2] = 0.0;
  766 + e0[3] = 1.0;
  767 + a0[0] = g_matrix[2];
  768 + a0[1] = g_matrix[5];
  769 + a0[2] = 0.0;
  770 + a0[3] = g_matrix[8];
  771 + s0 = cd_zero.cholesky_solver(a0) - e0;
  772 + res = max(abs(s0));
  773 + test_value(res, 0.0, 1.0e-15, "Test compressed cholesky_solver() method");
  774 +
  775 + // Test Cholesky inverter
  776 + GMatrix unit(g_rows,g_cols);
  777 + unit(0,0) = unit(1,1) = unit(2,2) = 1.0;
  778 + GMatrix test_inv = m_test;
  779 + test_inv.cholesky_invert();
  780 + GMatrix ci_product = m_test * test_inv;
  781 + GMatrix ci_residuals = ci_product - unit;
  782 + res = (abs(ci_residuals)).max();
  783 + test_value(res, 0.0, 1.0e-15, "Test cholesky_invert method");
  784 +
  785 + // Test Cholesky inverter for compressed matrix
  786 + unit = GMatrix(4,4);
  787 + unit(0,0) = unit(1,1) = unit(3,3) = 1.0;
  788 + GMatrix test_zero_inv = test_zero;
  789 + test_zero_inv.cholesky_invert();
  790 + GMatrix ciz_product = test_zero * test_zero_inv;
  791 + GMatrix ciz_residuals = ciz_product - unit;
  792 + res = (abs(ciz_residuals)).max();
  793 + test_value(res, 0.0, 1.0e-15, "Test compressed cholesky_invert method");
752 794  
  795 + // Return
753 796 return;
754 797 }
  798 +*/
755 799  
756   -// Test 11: Matrix comparison
757   -void TestGMatrix::test11(void){
758   -
759   - test_assert(((m_test == m_test) == 1),"GMatrix == GMatrix","Corrupt GMatrix == GMatrix operator.");
760   - //
761   - GMatrix m_test10(m_g_rows,m_g_cols);
762   - test_assert(((m_test == m_test10) == 0),"GMatrix == GMatrix 2","Corrupt GMatrix == GMatrix operator.");
763   - //
764   - test_assert(((m_test == bigger) == 0),"GMatrix == GMatrix 3","Corrupt GMatrix == GMatrix operator.");
765   - //
766   - test_assert(((m_test != m_test) == 0),"GMatrix != GMatrix","Corrupt GMatrix != GMatrix operator.");
767   - //
768   - test_assert(((m_test != m_test10) == 1),"GMatrix != GMatrix 2","Corrupt GMatrix != GMatrix operator.");
769   - //
770   - test_assert(((m_test != bigger) == 1),"GMatrix != GMatrix 3","Corrupt GMatrix != GMatrix operator.");
  800 +/***************************************************************************
  801 + * @brief Test matrix printing
  802 + ***************************************************************************/
  803 +void TestGMatrix::matrix_print(void)
  804 +{
  805 + // Set reference
  806 + std::string reference;
  807 + reference.append("=== GMatrix ===\n");
  808 + reference.append(" Number of rows ............: 3\n");
  809 + reference.append(" Number of columns .........: 4\n");
  810 + reference.append(" Number of elements ........: 12\n");
  811 + reference.append(" Number of allocated cells .: 12\n");
  812 + reference.append(" 1, 2, 3, 4\n");
  813 + reference.append(" 5, 6, 7, 8\n");
  814 + reference.append(" 9, 10, 11, 12");
  815 +
  816 + // Test the print method
  817 + std::string output = m_test.print();
  818 + test_assert((output == reference), "Test matrix printing",
  819 + "Unexpected print() output:\n"+output);
771 820  
  821 + // Return
772 822 return;
773 823 }
774 824  
  825 +
  826 +/***************************************************************************
  827 + * @brief Main entry point for test executable
  828 + ***************************************************************************/
775 829 int main(void)
776 830 {
777   - GTestSuites testsuite("GMatrix");
  831 + // Allocate test suit container
  832 + GTestSuites testsuites("GMatrix class testing");
778 833  
779   - bool was_successful=true;
  834 + // Initially assume that we pass all tests
  835 + bool success = true;
780 836  
781   - //Create a test suite
  837 + // Create a test suite
782 838 TestGMatrix test;
783 839  
784   - //Append to the container
785   - testsuite.append(test);
  840 + // Append test suite to the container
  841 + testsuites.append(test);
786 842  
787   - //Run
788   - was_successful=testsuite.run();
  843 + // Run the testsuites
  844 + success = testsuites.run();
789 845  
790   - //save xml report
791   - testsuite.save("reports/GMatrix.xml");
  846 + // Save test report
  847 + testsuites.save("reports/GMatrix.xml");
792 848  
793   - // Return
794   - return was_successful ? 0:1;
  849 + // Return success status
  850 + return (success ? 0 : 1);
795 851 }
... ...
test/test_GMatrix.hpp
1 1 /***************************************************************************
2   - * test_GMatrix.hpp - test matrix class *
  2 + * test_GMatrix.hpp - Test generic matrix class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2012 by Jean-Baptiste Cayrou *
  4 + * copyright (C) 2012 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -18,70 +18,65 @@
18 18 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19 19 * *
20 20 ***************************************************************************/
  21 +/**
  22 + * @file test_GMatrix.hpp
  23 + * @brief Definition of unit tests for generic matrices
  24 + * @author Juergen Knoedlseder
  25 + */
21 26  
22 27 #ifndef TEST_GMATRIX_HPP
23 28 #define TEST_GMATRIX_HPP
24 29  
25 30 /* __ Includes ___________________________________________________________ */
26 31 #include "GammaLib.hpp"
27   -#include <iostream> // cout, cerr
28 32  
29   -class TestGMatrix : public GTestSuite
30   -{
31   - public:
32   - // Constructors and destructors
33   - TestGMatrix(void) : GTestSuite(){ return; }
34   - virtual ~TestGMatrix(void){ return; }
35 33  
36   - // Methods
37   - virtual void set(void);
38   -
39   - void set_matrix(void);
40   - void set_vector(void);
41   - void set_bigger(void);
42   - void test_output(void);
43   - void test_conversion(void);
44   - void test_extract(void);
45   - void test1(void);
46   - void test2(void);
47   - void test3(void);
48   - void test4(void);
49   - void test5(void);
50   - void test6(void);
51   - void test7(void);
52   - void test8(void);
53   - void test9(void);
54   - void test10(void);
55   - void test11(void);
56   -
57   - // Private methods
58   - private:
59   - void init_matrix(void);
60   - void init_vector(void);
61   -
62   - int check_matrix(const GMatrix& m, const double scale, const double add);
63   - int check_transpose_matrix(const GMatrix& m, const double scale, const double add);
64   - int check_matrix_lt(const GMatrix& m, const double scale, const double add);
65   - int check_matrix_ut(const GMatrix& m, const double scale, const double add);
66   - int check_matrix_vector(const GVector& v);
67   - int check_matrix_matrix(const GMatrix& m);
68   - int check_matrix_min(const double min);
69   - int check_matrix_max(const double max);
70   - int check_matrix_sum(const double sum);
  34 +/***********************************************************************//**
  35 + * @class TestGMatrix
  36 + *
  37 + * @brief Test suite for generic matrix class testing
  38 + *
  39 + * This test suite performs a unit test for the generic matrix class. Tests
  40 + * that match logically are gathered in a number of class methods, and the
  41 + * class methods are executed when running the test.
  42 + ***************************************************************************/
  43 +class TestGMatrix : public GTestSuite {
71 44  
  45 +public:
  46 + // Constructors and destructors
  47 + TestGMatrix(void) : GTestSuite() {}
  48 + virtual ~TestGMatrix(void) {}
72 49  
  50 + // Methods
  51 + virtual void set(void);
  52 + void alloc_matrix(void);
  53 + void assign_values(void);
  54 + void copy_matrix(void);
  55 + void matrix_operations(void);
  56 + void matrix_arithmetics(void);
  57 + void matrix_functions(void);
  58 + void matrix_compare(void);
  59 + //void matrix_cholesky(void);
  60 + void matrix_print(void);
73 61  
  62 +private:
  63 + // Private methods
  64 + GMatrix set_matrix(void) const;
  65 + GMatrix set_matrix_zero(void) const;
  66 + GVector set_vector(void) const;
  67 + bool check_matrix(const GMatrix& matrix,
  68 + const double& scale = 1.0,
  69 + const double& offset = 0.0) const;
  70 + bool check_matrix_trans(const GMatrix& matrix,
  71 + const double& scale,
  72 + const double& offset) const;
  73 + bool check_matrix_lt(const GMatrix& matrix, const GMatrix& ref) const;
  74 + bool check_matrix_ut(const GMatrix& matrix, const GMatrix& ref) const;
74 75  
75   - // Private attributes
76   - GMatrix m_test;
77   - GMatrix bigger;
78   - GMatrix result;
79   - GVector v_test;
80   - double m_g_matrix[12];//
81   - double m_g_vector[4];
82   - int m_g_rows;
83   - int m_g_cols;
84   -
  76 + // Private members;
  77 + GMatrix m_test; //!< Test matrix
  78 + GMatrix m_bigger; //!< Bigger test matrix (for collisions)
  79 + GVector v_test; //!< Test vector
85 80 };
86 81  
87 82 #endif /* TEST_GMATRIX_HPP */
... ...
test/test_GSymMatrix.cpp
... ... @@ -268,7 +268,7 @@ void TestGSymMatrix::alloc_matrix(void)
268 268 test_try("Allocate zero matrix");
269 269 try {
270 270 GSymMatrix test(0,0);
271   - test_try_failure();
  271 + test_try_failure("Expected GException::empty exception.");
272 272 }
273 273 catch (GException::empty &e) {
274 274 test_try_success();
... ... @@ -311,7 +311,7 @@ void TestGSymMatrix::assign_values(void)
311 311 test_try("Verify range checking");
312 312 try {
313 313 test(3,3) = 1.0;
314   - test_try_failure();
  314 + test_try_failure("Expected GException::out_of_range exception.");
315 315 }
316 316 catch (GException::out_of_range &e) {
317 317 test_try_success();
... ... @@ -336,7 +336,8 @@ void TestGSymMatrix::copy_matrix(void)
336 336  
337 337 // Test if original and compied matrices are correct
338 338 test_assert(check_matrix(m_test), "Test source matrix");
339   - test_assert(check_matrix(test), "Test matrix copy operator", test.print());
  339 + test_assert(check_matrix(test), "Test matrix copy operator",
  340 + "Found:\n"+test.print()+"\nExpected:\n"+m_test.print());
340 341  
341 342 // Return
342 343 return;
... ... @@ -354,12 +355,14 @@ void TestGSymMatrix::matrix_operations(void)
354 355 GVector test1 = m_test * v_test;
355 356  
356 357 // Check if the result vector is as expected
  358 + GVector ref1 = test1;
357 359 bool result = true;
358 360 for (int row = 0; row < g_rows; ++row) {
359 361 double value = 0.0;
360 362 for (int col = 0; col < g_cols; ++col) {
361 363 value += g_matrix[col+row*g_cols] * g_vector[col];
362 364 }
  365 + ref1[row] = value;
363 366 if (test1[row] != value) {
364 367 result = false;
365 368 break;
... ... @@ -368,7 +371,8 @@ void TestGSymMatrix::matrix_operations(void)
368 371  
369 372 // Test if original matrix and result vector are correct
370 373 test_assert(check_matrix(m_test), "Test source matrix");
371   - test_assert(result, "Test matrix*vector multiplication", test1.print());
  374 + test_assert(result, "Test matrix*vector multiplication",
  375 + "Found:\n"+test1.print()+"\nExpected:\n"+ref1.print());
372 376  
373 377 // Test incompatible vector multiplication
374 378 test_try("Test incompatible matrix*vector multiplication");
... ... @@ -387,6 +391,7 @@ void TestGSymMatrix::matrix_operations(void)
387 391 GSymMatrix test3 = m_test * m_test;
388 392  
389 393 // Check if the result matrix is as expected
  394 + GSymMatrix ref3 = test3;
390 395 result = true;
391 396 for (int row = 0; row < test3.rows(); ++row) {
392 397 for (int col = 0; col < test3.cols(); ++col) {
... ... @@ -394,6 +399,7 @@ void TestGSymMatrix::matrix_operations(void)
394 399 for (int i = 0; i < g_cols; ++i) {
395 400 value += g_matrix[i+row*g_cols] * g_matrix[i+col*g_cols];
396 401 }
  402 + ref3(row,col) = value;
397 403 if (test3(row,col) != value) {
398 404 result = false;
399 405 break;
... ... @@ -403,7 +409,8 @@ void TestGSymMatrix::matrix_operations(void)
403 409  
404 410 // Test if original matrix and result matrix are correct
405 411 test_assert(check_matrix(m_test), "Test source matrix");
406   - test_assert(result, "Test matrix multiplication", test3.print());
  412 + test_assert(result, "Test matrix multiplication",
  413 + "Found:\n"+test3.print()+"\nExpected:\n"+ref3.print());
407 414 test_assert(test3.rows() == g_rows, "Test number of rows of result matrix");
408 415 test_assert(test3.cols() == g_cols, "Test number of columns of result matrix");
409 416  
... ... @@ -411,7 +418,7 @@ void TestGSymMatrix::matrix_operations(void)
411 418 test_try("Test incompatible matrix multiplication");
412 419 try {
413 420 GSymMatrix test4 = m_test * m_bigger;
414   - test_try_failure();
  421 + test_try_failure("Expected GException::matrix_mismatch exception.");
415 422 }
416 423 catch (GException::matrix_mismatch &e) {
417 424 test_try_success();
... ... @@ -424,7 +431,7 @@ void TestGSymMatrix::matrix_operations(void)
424 431 test_try("Test incompatible matrix multiplication");
425 432 try {
426 433 GSymMatrix test5 = m_bigger * m_test;
427   - test_try_failure();
  434 + test_try_failure("Expected GException::matrix_mismatch exception.");
428 435 }
429 436 catch (GException::matrix_mismatch &e) {
430 437 test_try_success();
... ... @@ -514,7 +521,7 @@ void TestGSymMatrix::matrix_arithmetics(void)
514 521 try {
515 522 test = m_test;
516 523 test += m_bigger;
517   - test_try_failure();
  524 + test_try_failure("Expected GException::matrix_mismatch exception.");
518 525 }
519 526 catch (GException::matrix_mismatch &e) {
520 527 test_try_success();
... ... @@ -578,35 +585,38 @@ void TestGSymMatrix::matrix_functions(void)
578 585 // Transpose function
579 586 GSymMatrix test1 = transpose(m_test);
580 587 test_assert(check_matrix(m_test), "Test source matrix");
581   - test_assert(check_matrix(test1, 1.0, 0.0), "Test transpose(GSymMatrix) function",
582   - test1.print());
  588 + test_assert(check_matrix(test1, 1.0, 0.0),
  589 + "Test transpose(GSymMatrix) function",
  590 + "Unexpected transposed matrix:\n"+test1.print());
583 591  
584 592 // Transpose method
585 593 test1 = m_test;
586 594 test1.transpose();
587 595 test_assert(check_matrix(m_test), "Test source matrix");
588   - test_assert(check_matrix(test1, 1.0, 0.0), "Test GSymMatrix.transpose() method",
589   - test1.print());
  596 + test_assert(check_matrix(test1, 1.0, 0.0),
  597 + "Test GSymMatrix.transpose() method",
  598 + "Unexpected transposed matrix:\n"+test1.print());
590 599  
591 600 // Convert to general matrix
592 601 GMatrix test2 = GMatrix(m_test);
593 602 test_assert(check_matrix(m_test), "Test source matrix");
594   - test_assert(check_matrix(test2, 1.0, 0.0), "Test GMatrix(GSymMatrix) constructor",
595   - test2.print());
  603 + test_assert(check_matrix(test2, 1.0, 0.0),
  604 + "Test GMatrix(GSymMatrix) constructor",
  605 + "Unexpected GMatrix:\n"+test2.print());
596 606  
597 607 // Extract lower triangle
598 608 test2 = m_test.extract_lower_triangle();
599 609 test_assert(check_matrix(m_test), "Test source matrix");
600 610 test_assert(check_matrix_lt(test2, 1.0, 0.0),
601 611 "Test GSymMatrix.extract_lower_triangle() method",
602   - test2.print());
  612 + "Unexpected GMatrix:\n"+test2.print());
603 613  
604 614 // Extract upper triangle
605 615 test2 = m_test.extract_upper_triangle();
606 616 test_assert(check_matrix(m_test), "Test source matrix");
607 617 test_assert(check_matrix_ut(test2, 1.0, 0.0),
608 618 "Test GSymMatrix.extract_upper_triangle() method",
609   - test2.print());
  619 + "Unexpected GMatrix:\n"+test2.print());
610 620  
611 621 // Return
612 622 return;
... ... @@ -644,7 +654,7 @@ void TestGSymMatrix::matrix_cholesky(void)
644 654 GMatrix cd_lower = cd.extract_lower_triangle();
645 655 GMatrix cd_upper = transpose(cd_lower);
646 656 GMatrix cd_product = cd_lower * cd_upper;
647   - GMatrix cd_residuals = matrix(m_test) - cd_product;
  657 + GMatrix cd_residuals = GMatrix(m_test) - cd_product;
648 658 double res = (abs(cd_residuals)).max();
649 659 test_value(res, 0.0, 1.0e-15, "Test cholesky_decompose() method");
650 660  
... ... @@ -654,7 +664,7 @@ void TestGSymMatrix::matrix_cholesky(void)
654 664 GMatrix cd_zero_lower = cd_zero.extract_lower_triangle();
655 665 GMatrix cd_zero_upper = transpose(cd_zero_lower);
656 666 GMatrix cd_zero_product = cd_zero_lower * cd_zero_upper;
657   - GMatrix cd_zero_residuals = matrix(test_zero) - cd_zero_product;
  667 + GMatrix cd_zero_residuals = GMatrix(test_zero) - cd_zero_product;
658 668 res = (abs(cd_zero_residuals)).max();
659 669 test_value(res, 0.0, 1.0e-15, "Test compressed cholesky_decompose() method");
660 670  
... ... @@ -745,8 +755,8 @@ void TestGSymMatrix::matrix_cholesky(void)
745 755 unit(0,0) = unit(1,1) = unit(2,2) = 1.0;
746 756 GSymMatrix test_inv = m_test;
747 757 test_inv.cholesky_invert();
748   - GSymMatrix ci_product = m_test * test_inv;
749   - GSymMatrix ci_residuals = ci_product - unit;
  758 + GMatrix ci_product = m_test * test_inv;
  759 + GMatrix ci_residuals = ci_product - unit;
750 760 res = (abs(ci_residuals)).max();
751 761 test_value(res, 0.0, 1.0e-15, "Test cholesky_invert method");
752 762  
... ... @@ -755,8 +765,8 @@ void TestGSymMatrix::matrix_cholesky(void)
755 765 unit(0,0) = unit(1,1) = unit(3,3) = 1.0;
756 766 GSymMatrix test_zero_inv = test_zero;
757 767 test_zero_inv.cholesky_invert();
758   - GSymMatrix ciz_product = test_zero * test_zero_inv;
759   - GSymMatrix ciz_residuals = ciz_product - unit;
  768 + GMatrix ciz_product = test_zero * test_zero_inv;
  769 + GMatrix ciz_residuals = ciz_product - unit;
760 770 res = (abs(ciz_residuals)).max();
761 771 test_value(res, 0.0, 1.0e-15, "Test compressed cholesky_invert method");
762 772  
... ... @@ -783,7 +793,8 @@ void TestGSymMatrix::matrix_print(void)
783 793  
784 794 // Test the print method
785 795 std::string output = m_test.print();
786   - test_assert((output == reference), "Test matrix printing", output);
  796 + test_assert((output == reference), "Test matrix printing",
  797 + "Unexpected print() output:\n"+output);
787 798  
788 799 // Return
789 800 return;
... ...