1 | // Copyright 2008 Gunter Winkler <guwi17@gmx.de> |
2 | // Distributed under the Boost Software License, Version 1.0. (See |
3 | // accompanying file LICENSE_1_0.txt or copy at |
4 | // http://www.boost.org/LICENSE_1_0.txt) |
5 | |
6 | |
7 | #ifndef _HPP_TESTHELPER_ |
8 | #define _HPP_TESTHELPER_ |
9 | |
10 | #include <utility> |
11 | #include <iostream> |
12 | #include <boost/numeric/ublas/vector_expression.hpp> |
13 | #include <boost/numeric/ublas/matrix_expression.hpp> |
14 | #include <boost/mpl/if.hpp> |
15 | #include <boost/type_traits/is_integral.hpp> |
16 | #include <boost/numeric/ublas/traits.hpp> |
17 | |
18 | static unsigned _success_counter = 0; |
19 | static unsigned _fail_counter = 0; |
20 | |
21 | static inline |
22 | void assertTrue(const char* message, bool condition) { |
23 | #ifndef NOMESSAGES |
24 | std::cout << message; |
25 | #else |
26 | (void)message; |
27 | #endif |
28 | if ( condition ) { |
29 | ++ _success_counter; |
30 | std::cout << "1\n" ; // success |
31 | } else { |
32 | ++ _fail_counter; |
33 | std::cout << "0\n" ; // failed |
34 | } |
35 | } |
36 | |
37 | template < class T > |
38 | void assertEquals(const char* message, T expected, T actual) { |
39 | #ifndef NOMESSAGES |
40 | std::cout << message; |
41 | #else |
42 | (void)message; |
43 | #endif |
44 | if ( expected == actual ) { |
45 | ++ _success_counter; |
46 | std::cout << "1\n" ; // success |
47 | } else { |
48 | #ifndef NOMESSAGES |
49 | std::cout << " expected " << expected << " actual " << actual << " " ; |
50 | #endif |
51 | ++ _fail_counter; |
52 | std::cout << "0\n" ; // failed |
53 | } |
54 | } |
55 | |
56 | inline static |
57 | std::pair<unsigned, unsigned> getResults() { |
58 | return std::make_pair(x&: _success_counter, y&: _fail_counter); |
59 | } |
60 | |
61 | template < class M1, class M2 > |
62 | bool compare( const boost::numeric::ublas::matrix_expression<M1> & m1, |
63 | const boost::numeric::ublas::matrix_expression<M2> & m2 ) { |
64 | if ((m1().size1() != m2().size1()) || |
65 | (m1().size2() != m2().size2())) { |
66 | return false; |
67 | } |
68 | |
69 | size_t size1 = m1().size1(); |
70 | size_t size2 = m1().size2(); |
71 | for (size_t i=0; i < size1; ++i) { |
72 | for (size_t j=0; j < size2; ++j) { |
73 | if ( m1()(i,j) != m2()(i,j) ) return false; |
74 | } |
75 | } |
76 | return true; |
77 | } |
78 | |
79 | template < class M1, class M2 > |
80 | bool compare( const boost::numeric::ublas::vector_expression<M1> & m1, |
81 | const boost::numeric::ublas::vector_expression<M2> & m2 ) { |
82 | if (m1().size() != m2().size()) { |
83 | return false; |
84 | } |
85 | |
86 | size_t size = m1().size(); |
87 | for (size_t i=0; i < size; ++i) { |
88 | if ( m1()(i) != m2()(i) ) return false; |
89 | } |
90 | return true; |
91 | } |
92 | |
93 | // Compare if two matrices or vectors are equals based on distance. |
94 | |
95 | template <typename T> |
96 | struct promote_distance { |
97 | typedef typename boost::mpl::if_c<boost::is_integral<T>::value, |
98 | long double, |
99 | T>::type type; |
100 | }; |
101 | |
102 | template <typename M1, typename M2 = void> |
103 | struct distance { |
104 | private: |
105 | typedef typename boost::numeric::ublas::promote_traits<typename M1::value_type, |
106 | typename M2::value_type>::promote_type value_type; |
107 | |
108 | public: |
109 | typedef typename promote_distance<value_type>::type type; |
110 | }; |
111 | |
112 | template <typename AE> |
113 | struct distance<AE, void> { |
114 | typedef typename promote_distance<typename AE::value_type>::type type; |
115 | }; |
116 | |
117 | |
118 | template <class AE> |
119 | typename distance<AE>::type mean_square(const boost::numeric::ublas::matrix_expression<AE> &me) { |
120 | typename distance<AE>::type s(0); |
121 | typename AE::size_type i, j; |
122 | for (i=0; i!= me().size1(); i++) { |
123 | for (j=0; j!= me().size2(); j++) { |
124 | s += boost::numeric::ublas::scalar_traits<typename AE::value_type>::type_abs(me()(i,j)); |
125 | } |
126 | } |
127 | return s / (me().size1() * me().size2()); |
128 | } |
129 | |
130 | template <class AE> |
131 | typename distance<AE>::type mean_square(const boost::numeric::ublas::vector_expression<AE> &ve) { |
132 | // We could have use norm2 here, but ublas' ABS does not support unsigned types. |
133 | typename distance<AE>::type s(0); |
134 | typename AE::size_type i; |
135 | for (i = 0; i != ve().size(); i++) { |
136 | s += boost::numeric::ublas::scalar_traits<typename AE::value_type>::type_abs(ve()(i)); |
137 | } |
138 | return s / ve().size(); |
139 | } |
140 | |
141 | template < class M1, class M2 > |
142 | bool compare_distance( const boost::numeric::ublas::matrix_expression<M1> & m1, |
143 | const boost::numeric::ublas::matrix_expression<M2> & m2, |
144 | typename distance<M1, M2>::type tolerance = 0 ) { |
145 | if ((m1().size1() != m2().size1()) || |
146 | (m1().size2() != m2().size2())) { |
147 | return false; |
148 | } |
149 | |
150 | return mean_square(m2() - m1()) <= tolerance; |
151 | } |
152 | |
153 | template < class M1, class M2 > |
154 | bool compare_distance( const boost::numeric::ublas::vector_expression<M1> & m1, |
155 | const boost::numeric::ublas::vector_expression<M2> & m2, |
156 | typename distance<M1, M2>::type tolerance = 0 ) { |
157 | if (m1().size() != m2().size()) { |
158 | return false; |
159 | } |
160 | |
161 | return mean_square(m2() - m1()) <= tolerance; |
162 | } |
163 | |
164 | |
165 | #endif |
166 | |