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/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
not_func(bool argb)31 bool not_func( bool argb ) { return !argb; }
32
33 //____________________________________________________________________________//
34
35 typedef boost::mpl::list<float,double,long double> test_types;
36
BOOST_AUTO_TEST_CASE_TEMPLATE(test_fp_comparizon_with_percent_tolerance,FPT,test_types)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
BOOST_AUTO_TEST_CASE_TEMPLATE(test_fp_comparizon_with_fraction_tolerance,FPT,test_types)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
BOOST_AUTO_TEST_CASE(test_type_mismatch)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
BOOST_AUTO_TEST_CASE(test_CHECK_SMALL)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
BOOST_AUTO_TEST_CASE(test_close_at_tolerance)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
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
BOOST_AUTO_TEST_CASE(test_comparison_if_one_is_FPV_2)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
BOOST_AUTO_TEST_CASE(test_check_close)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
309 // EOF
310