]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // (C) Copyright Gennadiy Rozental 2001-2015. |
2 | // Distributed under the Boost Software License, Version 1.0. | |
3 | // (See accompanying file LICENSE_1_0.txt or copy at | |
4 | // http://www.boost.org/LICENSE_1_0.txt) | |
5 | ||
6 | // See http://www.boost.org/libs/test for the library home page. | |
7 | // | |
8 | // File : $RCSfile$ | |
9 | // | |
10 | // Version : $Revision$ | |
11 | // | |
12 | // Description : tests floating point comparison algorithms | |
13 | // *************************************************************************** | |
14 | ||
15 | // Boost.Test | |
16 | #define BOOST_TEST_MAIN | |
17 | #include <boost/test/unit_test.hpp> | |
18 | ||
19 | // Boost | |
20 | #include <boost/mpl/list.hpp> | |
21 | #include <boost/bind.hpp> | |
22 | ||
23 | // STL | |
24 | #include <functional> | |
25 | ||
26 | using namespace boost; | |
27 | using namespace boost::unit_test; | |
28 | using namespace boost::test_tools; | |
29 | namespace tt=boost::test_tools; | |
30 | ||
31 | bool not_func( bool argb ) { return !argb; } | |
32 | ||
33 | //____________________________________________________________________________// | |
34 | ||
35 | typedef boost::mpl::list<float,double,long double> test_types; | |
36 | ||
37 | BOOST_AUTO_TEST_CASE_TEMPLATE( test_fp_comparizon_with_percent_tolerance, FPT, test_types ) | |
38 | { | |
39 | #define CHECK_CLOSE( first, second, e ) \ | |
40 | fp1 = static_cast<FPT>(first); \ | |
41 | fp2 = static_cast<FPT>(second); \ | |
42 | epsilon = static_cast<FPT>(e); \ | |
43 | \ | |
44 | BOOST_TEST( fp1 == fp2, epsilon% tt::tolerance() ) \ | |
45 | /**/ | |
46 | ||
47 | #define CHECK_NOT_CLOSE( first, second, e ) \ | |
48 | fp1 = static_cast<FPT>(first); \ | |
49 | fp2 = static_cast<FPT>(second); \ | |
50 | epsilon = static_cast<FPT>(e); \ | |
51 | \ | |
52 | BOOST_TEST( fp1 != fp2, epsilon% tt::tolerance() ) \ | |
53 | /**/ | |
54 | ||
55 | FPT fp1, fp2, epsilon; | |
56 | ||
57 | CHECK_CLOSE( 1, 1, 0 ); | |
58 | ||
59 | CHECK_CLOSE( 0, 1e-20, 1e-5 ); | |
60 | CHECK_CLOSE( 0, 1e-30, 1e-5 ); | |
61 | CHECK_CLOSE( 0, -1e-10, 0.1 ); | |
62 | CHECK_NOT_CLOSE( 0.123456, 0.123457, 1e-4 ); | |
63 | ||
64 | CHECK_CLOSE( 0.123456, 0.123457, 1e-3 ); | |
65 | ||
66 | CHECK_NOT_CLOSE( 0.123456, -0.123457, 1e-3 ); | |
67 | ||
68 | CHECK_CLOSE( 1.23456e28, 1.23457e28, 1e-3 ); | |
69 | ||
70 | CHECK_CLOSE( 1.23456e-10, 1.23457e-10, 1e-3 ); | |
71 | CHECK_NOT_CLOSE( 1.111e-10, 1.112e-10, 0.0899 ); | |
72 | CHECK_CLOSE( 1.112e-10, 1.111e-10, 0.1 ); | |
73 | ||
74 | CHECK_CLOSE( 1, 1.0001, 1.1e-2 ); | |
75 | CHECK_CLOSE( 1.0002, 1.0001, 1.1e-2 ); | |
76 | ||
77 | CHECK_NOT_CLOSE( 1, 1.0002, 1.1e-2 ); | |
78 | ||
79 | #undef CHECK_CLOSE | |
80 | #undef CHECK_NOT_CLOSE | |
81 | } | |
82 | ||
83 | //____________________________________________________________________________// | |
84 | ||
85 | BOOST_AUTO_TEST_CASE_TEMPLATE( test_fp_comparizon_with_fraction_tolerance, FPT, test_types ) | |
86 | { | |
87 | #define CHECK_CLOSE( first, second, e ) \ | |
88 | fp1 = static_cast<FPT>(first); \ | |
89 | fp2 = static_cast<FPT>(second); \ | |
90 | epsilon = static_cast<FPT>(e); \ | |
91 | \ | |
92 | BOOST_TEST( fp1 == fp2, tt::tolerance(epsilon) ); \ | |
93 | /**/ | |
94 | ||
95 | #define CHECK_NOT_CLOSE( first, second, e ) \ | |
96 | fp1 = static_cast<FPT>(first); \ | |
97 | fp2 = static_cast<FPT>(second); \ | |
98 | epsilon = static_cast<FPT>(e); \ | |
99 | \ | |
100 | BOOST_TEST( fp1 != fp2, tt::tolerance(epsilon) ); \ | |
101 | /**/ | |
102 | ||
103 | ||
104 | FPT fp1, fp2, epsilon; | |
105 | ||
106 | CHECK_CLOSE( 1, 1, 0 ); | |
107 | ||
108 | CHECK_CLOSE( 0, 1e-20, 1e-5 ); | |
109 | CHECK_CLOSE( 0, 1e-30, 1e-5 ); | |
110 | CHECK_CLOSE( 0, -1e-10, 0.1 ); | |
111 | CHECK_NOT_CLOSE( 0.123456, 0.123457, 1e-6 ); | |
112 | ||
113 | CHECK_CLOSE( 0.123456, 0.123457, 1e-3 ); | |
114 | ||
115 | CHECK_NOT_CLOSE( 0.123456, -0.123457, 1e-3 ); | |
116 | ||
117 | CHECK_CLOSE( 1.23456e28, 1.23457e28, 1e-3 ); | |
118 | ||
119 | CHECK_CLOSE( 1.23456e-10, 1.23457e-10, 1e-3 ); | |
120 | CHECK_NOT_CLOSE( 1.111e-10, 1.112e-10, 0.000899 ); | |
121 | CHECK_CLOSE( 1.112e-10, 1.111e-10, 0.1 ); | |
122 | ||
123 | CHECK_CLOSE( 1, 1.0001, 1.1e-2 ); | |
124 | CHECK_CLOSE( 1.0002, 1.0001, 1.1e-2 ); | |
125 | ||
126 | CHECK_NOT_CLOSE( 1, 1.0002, 1.1e-4 ); | |
127 | ||
128 | #undef CHECK_CLOSE | |
129 | #undef CHECK_NOT_CLOSE | |
130 | } | |
131 | ||
132 | //____________________________________________________________________________// | |
133 | ||
134 | BOOST_AUTO_TEST_CASE( test_type_mismatch ) | |
135 | { | |
136 | BOOST_CHECK_CLOSE_FRACTION( 2., 2.1, 0.06 ); | |
137 | BOOST_CHECK_CLOSE( 2.1, 2., 6. ); | |
138 | BOOST_CHECK_CLOSE( 2.1, 2.f, 6. ); | |
139 | } | |
140 | ||
141 | //____________________________________________________________________________// | |
142 | ||
143 | BOOST_AUTO_TEST_CASE( test_strong_weak, * expected_failures( 4 ) ) | |
144 | { | |
145 | BOOST_TEST(1./3 == 1./2, tt::tolerance(1.)); | |
146 | BOOST_TEST(1./3 == 1./2, tt::tolerance(0.4)); // will fail 1/2 > 0.4 | |
147 | BOOST_TEST(1./3 == 1./2, tt::tolerance(1./3)); // will fail; both 1/3 and 1/2 > 1/3 | |
148 | BOOST_TEST(1./3 != 1./2, tt::tolerance(1.)); // will fail; both 1/3 and 1/2 < 1 | |
149 | BOOST_TEST(1./3 != 1./2, tt::tolerance(0.4)); // will fail 1/3 < 0.4 | |
150 | BOOST_TEST(1./3 != 1./2, tt::tolerance(1./3)); | |
151 | } | |
152 | ||
153 | BOOST_AUTO_TEST_CASE(test_strict_order_operations_ne, | |
154 | * boost::unit_test::tolerance(0.01) | |
155 | * expected_failures( 1 ) ) | |
156 | { | |
157 | double x = 10.00; | |
158 | double y = 10.01; // diff within tolerance | |
159 | BOOST_TEST(x == y); | |
160 | BOOST_TEST(x != y); // fails | |
161 | BOOST_TEST(x <= y); | |
162 | BOOST_TEST(x >= y); | |
163 | } | |
164 | ||
165 | BOOST_AUTO_TEST_CASE(test_strict_order_operations_lt, | |
166 | * boost::unit_test::tolerance(0.01) | |
167 | * expected_failures( 3 ) ) | |
168 | { | |
169 | double x = 10.00; | |
170 | double y = 10.01; // diff within tolerance | |
171 | BOOST_TEST(x == y); | |
172 | BOOST_TEST(x != y); // fails | |
173 | BOOST_TEST(x <= y); | |
174 | BOOST_TEST(y <= x); | |
175 | BOOST_TEST(x < y); // fails y ~= x | |
176 | BOOST_TEST(y < x); // fails, y > x | |
177 | } | |
178 | ||
179 | BOOST_AUTO_TEST_CASE(test_strict_order_operations_lt_0, | |
180 | * boost::unit_test::tolerance(0.02) | |
181 | * expected_failures( 3 ) ) | |
182 | { | |
183 | double x = 0.00; | |
184 | double y = 0.01; | |
185 | BOOST_TEST(x == y); | |
186 | BOOST_TEST(x != y); // fails | |
187 | BOOST_TEST(x <= y); | |
188 | BOOST_TEST(y <= x); | |
189 | BOOST_TEST(x < y); // fails, too close to 0 | |
190 | BOOST_TEST(y < x); // fails, y > x | |
191 | } | |
192 | ||
193 | BOOST_AUTO_TEST_CASE(test_strict_order_operations_le, | |
194 | * boost::unit_test::tolerance(0.01) | |
195 | * expected_failures( 1 ) ) | |
196 | { | |
197 | double x = 10.01; | |
198 | double y = 10.00; // diff within tolerance | |
199 | BOOST_TEST(x == y); | |
200 | BOOST_TEST(x != y); // fails | |
201 | BOOST_TEST(x <= y); | |
202 | } | |
203 | ||
204 | ||
205 | BOOST_AUTO_TEST_CASE(test_strict_order_operations_gt, | |
206 | * boost::unit_test::tolerance(0.01) | |
207 | * expected_failures( 3 ) ) | |
208 | { | |
209 | double x = 10.00; | |
210 | double y = 10.01; // diff within tolerance | |
211 | BOOST_TEST(x == y); | |
212 | BOOST_TEST(x != y); // fails | |
213 | BOOST_TEST(x > y); // fails | |
214 | BOOST_TEST(y > x); // fails | |
215 | } | |
216 | ||
217 | BOOST_AUTO_TEST_CASE(test_strict_order_operations_ge, | |
218 | * boost::unit_test::tolerance(0.01) | |
219 | * expected_failures( 1 ) ) | |
220 | { | |
221 | double x = 10.00; | |
222 | double y = 10.01; // diff within tolerance | |
223 | BOOST_TEST(x == y); | |
224 | BOOST_TEST(x != y); // fails | |
225 | BOOST_TEST(x >= y); | |
226 | BOOST_TEST(y >= x); | |
227 | } | |
228 | ||
229 | BOOST_AUTO_TEST_CASE(test_strict_order_operations_gt_0, | |
230 | * boost::unit_test::tolerance(0.02) | |
231 | * expected_failures( 3 ) ) | |
232 | { | |
233 | double x = 0.00; | |
234 | double y = 0.01; | |
235 | BOOST_TEST(x == y); | |
236 | BOOST_TEST(x != y); // fails | |
237 | BOOST_TEST(x >= y); | |
238 | BOOST_TEST(y >= x); | |
239 | BOOST_TEST(x <= y); | |
240 | BOOST_TEST(y <= x); | |
241 | BOOST_TEST(x > y); // fails, too close to 0 | |
242 | BOOST_TEST(y > x); // fails, too close to 0 | |
243 | } | |
244 | ||
245 | //____________________________________________________________________________// | |
246 | ||
247 | BOOST_AUTO_TEST_CASE( test_CHECK_SMALL ) | |
248 | { | |
249 | BOOST_CHECK_SMALL( 1e-6, 1e-5 ); | |
250 | BOOST_CHECK_SMALL( -1e-6, 1e-5 ); | |
251 | ||
252 | BOOST_TEST( 1e-6 != 0., 1e-7 ); | |
253 | } | |
254 | ||
255 | //____________________________________________________________________________// | |
256 | ||
257 | namespace fpc = boost::math::fpc; | |
258 | ||
259 | BOOST_AUTO_TEST_CASE( test_close_at_tolerance ) | |
260 | { | |
261 | double fp1 = 1.00000001; | |
262 | double fp2 = 1.00000002; | |
263 | double epsilon = 1e-6; | |
264 | ||
265 | ::fpc::close_at_tolerance<double> pred( ::fpc::percent_tolerance( epsilon ), ::fpc::FPC_WEAK ); | |
266 | BOOST_CHECK_PREDICATE( pred, (fp1)(fp2) ); | |
267 | ||
268 | #ifndef BOOST_TEST_NO_OLD_TOOLS | |
269 | BOOST_TEST( !check_is_close( fp1, fp2, ::fpc::percent_tolerance( epsilon ) ) ); | |
270 | #endif | |
271 | ||
272 | fp1 = 1.23456e-10; | |
273 | fp2 = 1.23457e-10; | |
274 | epsilon = 8.1e-4; | |
275 | ||
276 | BOOST_CHECK_PREDICATE( ::fpc::close_at_tolerance<double>( ::fpc::percent_tolerance( epsilon ), ::fpc::FPC_WEAK ), (fp1)(fp2) ); | |
277 | ||
278 | BOOST_TEST( !::fpc::close_at_tolerance<double>( ::fpc::percent_tolerance( epsilon ) )(fp1, fp2) ); | |
279 | } | |
280 | ||
92f5a8d4 TL |
281 | |
282 | BOOST_AUTO_TEST_CASE( test_comparison_if_one_is_FPV, * boost::unit_test::tolerance(1E-6) ) | |
283 | { | |
284 | BOOST_TEST(1.000001 == 1); | |
285 | BOOST_TEST(1 == 1.000001); | |
286 | ||
287 | BOOST_TEST(0.000001 == 0); | |
288 | BOOST_TEST(0 == 0.000001); | |
289 | } | |
290 | ||
291 | BOOST_AUTO_TEST_CASE( test_comparison_if_one_is_FPV_2 ) | |
292 | { | |
293 | BOOST_TEST(1.000001 == 1, tt::tolerance(1E-6)); | |
294 | BOOST_TEST(1 == 1.000001, tt::tolerance(1E-6)); | |
295 | ||
296 | BOOST_TEST(0.000001 == 0, tt::tolerance(1E-6)); | |
297 | BOOST_TEST(0 == 0.000001, tt::tolerance(1E-6)); | |
298 | } | |
299 | ||
300 | BOOST_AUTO_TEST_CASE( test_check_close ) | |
301 | { | |
302 | // GH-162 BOOST_CHECK_CLOSE(0, smallnumber) fails | |
303 | BOOST_CHECK_SMALL(-4.37113883e-08, 1.); | |
304 | // does not compile with the old tools disabled | |
305 | // never compiled with the old tools | |
306 | //BOOST_CHECK_SMALL(-4.37113883e-08, 1); | |
307 | } | |
308 | ||
7c673cae | 309 | // EOF |