]>
Commit | Line | Data |
---|---|---|
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(_success_counter, _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 |