• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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