]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/test/tools/fpc_op.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / test / tools / fpc_op.hpp
1 // (C) Copyright Gennadiy Rozental 2001.
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
9 //!@brief Floating point comparison with enhanced reporting
10 // ***************************************************************************
11
12 #ifndef BOOST_TEST_TOOLS_FPC_OP_HPP_050915GER
13 #define BOOST_TEST_TOOLS_FPC_OP_HPP_050915GER
14
15 // Boost.Test
16 #include <boost/test/tools/assertion.hpp>
17
18 #include <boost/test/tools/floating_point_comparison.hpp>
19 #include <boost/test/tools/fpc_tolerance.hpp>
20
21 // Boost
22 #include <boost/type_traits/common_type.hpp>
23 #include <boost/utility/enable_if.hpp>
24
25 #include <boost/test/detail/suppress_warnings.hpp>
26
27 //____________________________________________________________________________//
28
29 namespace boost {
30 namespace test_tools {
31 namespace assertion {
32 namespace op {
33
34 // ************************************************************************** //
35 // ************** fpctraits ************** //
36 // ************************************************************************** //
37 // set of floating point comparison traits per comparison OP
38
39 template<typename OP>
40 struct fpctraits {
41 // indicate if we should perform the operation with a "logical OR"
42 // with the "equality under tolerance".
43 static const bool equality_logical_disjunction = true;
44 };
45
46 template <typename Lhs, typename Rhs>
47 struct fpctraits<op::LT<Lhs,Rhs> > {
48 static const bool equality_logical_disjunction = false;
49 };
50
51 template <typename Lhs, typename Rhs>
52 struct fpctraits<op::GT<Lhs,Rhs> > {
53 static const bool equality_logical_disjunction = false;
54 };
55
56 //____________________________________________________________________________//
57
58 // ************************************************************************** //
59 // ************** set of overloads to select correct fpc algo ************** //
60 // ************************************************************************** //
61 // we really only care about EQ vs NE. All other comparisons use direct first
62 // and then need EQ. For example a <= b (tolerance t) IFF a <= b OR a == b (tolerance t)
63
64 template <typename FPT, typename Lhs, typename Rhs, typename OP>
65 inline assertion_result
66 compare_fpv( Lhs const& lhs, Rhs const& rhs, OP* cmp_operator)
67 {
68 bool result = cmp_operator->eval_direct(lhs, rhs);
69 if(fpctraits<OP>::equality_logical_disjunction) {
70 return result || compare_fpv<FPT>(lhs, rhs, (op::EQ<Lhs, Rhs>*)0);
71 }
72 return result && compare_fpv<FPT>(lhs, rhs, (op::NE<Lhs, Rhs>*)0);
73 }
74
75 //____________________________________________________________________________//
76
77 template <typename FPT, typename Lhs, typename Rhs>
78 inline assertion_result
79 compare_fpv_near_zero( FPT const& fpv, op::EQ<Lhs,Rhs>* )
80 {
81 fpc::small_with_tolerance<FPT> P( fpc_tolerance<FPT>() );
82
83 assertion_result ar( P( fpv ) );
84 if( !ar )
85 ar.message() << "Absolute value exceeds tolerance [|" << fpv << "| > "<< fpc_tolerance<FPT>() << ']';
86
87 return ar;
88 }
89
90 //____________________________________________________________________________//
91
92 template <typename FPT, typename Lhs, typename Rhs>
93 inline assertion_result
94 compare_fpv_near_zero( FPT const& fpv, op::NE<Lhs,Rhs>* )
95 {
96 fpc::small_with_tolerance<FPT> P( fpc_tolerance<FPT>() );
97
98 assertion_result ar( !P( fpv ) );
99 if( !ar )
100 ar.message() << "Absolute value is within tolerance [|" << fpv << "| < "<< fpc_tolerance<FPT>() << ']';
101 return ar;
102 }
103
104 //____________________________________________________________________________//
105
106 template <typename FPT, typename Lhs, typename Rhs>
107 inline assertion_result
108 compare_fpv( Lhs const& lhs, Rhs const& rhs, op::EQ<Lhs,Rhs>* )
109 {
110 if( lhs == 0 ) {
111 return compare_fpv_near_zero( rhs, (op::EQ<Lhs,Rhs>*)0 );
112 }
113 else if( rhs == 0) {
114 return compare_fpv_near_zero( lhs, (op::EQ<Lhs,Rhs>*)0 );
115 }
116 else {
117 fpc::close_at_tolerance<FPT> P( fpc_tolerance<FPT>(), fpc::FPC_STRONG );
118
119 assertion_result ar( P( lhs, rhs ) );
120 if( !ar )
121 ar.message() << "Relative difference exceeds tolerance ["
122 << P.tested_rel_diff() << " > " << P.fraction_tolerance() << ']';
123 return ar;
124 }
125 }
126
127 //____________________________________________________________________________//
128
129 template <typename FPT, typename Lhs, typename Rhs>
130 inline assertion_result
131 compare_fpv( Lhs const& lhs, Rhs const& rhs, op::NE<Lhs,Rhs>* )
132 {
133 if( lhs == 0 ) {
134 return compare_fpv_near_zero( rhs, (op::NE<Lhs,Rhs>*)0 );
135 }
136 else if( rhs == 0 ) {
137 return compare_fpv_near_zero( lhs, (op::NE<Lhs,Rhs>*)0 );
138 }
139 else {
140 fpc::close_at_tolerance<FPT> P( fpc_tolerance<FPT>(), fpc::FPC_WEAK );
141
142 assertion_result ar( !P( lhs, rhs ) );
143 if( !ar )
144 ar.message() << "Relative difference is within tolerance ["
145 << P.tested_rel_diff() << " < " << fpc_tolerance<FPT>() << ']';
146
147 return ar;
148 }
149 }
150
151 //____________________________________________________________________________//
152
153 #define DEFINE_FPV_COMPARISON( oper, name, rev ) \
154 template<typename Lhs,typename Rhs> \
155 struct name<Lhs,Rhs,typename boost::enable_if_c< \
156 (fpc::tolerance_based<Lhs>::value && \
157 fpc::tolerance_based<Rhs>::value)>::type> { \
158 public: \
159 typedef typename common_type<Lhs,Rhs>::type FPT; \
160 typedef name<Lhs,Rhs> OP; \
161 \
162 typedef assertion_result result_type; \
163 \
164 static bool \
165 eval_direct( Lhs const& lhs, Rhs const& rhs ) \
166 { \
167 return lhs oper rhs; \
168 } \
169 \
170 static assertion_result \
171 eval( Lhs const& lhs, Rhs const& rhs ) \
172 { \
173 if( fpc_tolerance<FPT>() == FPT(0) ) \
174 { \
175 return eval_direct( lhs, rhs ); \
176 } \
177 \
178 return compare_fpv<FPT>( lhs, rhs, (OP*)0 ); \
179 } \
180 \
181 template<typename PrevExprType> \
182 static void \
183 report( std::ostream& ostr, \
184 PrevExprType const& lhs, \
185 Rhs const& rhs ) \
186 { \
187 lhs.report( ostr ); \
188 ostr << revert() \
189 << tt_detail::print_helper( rhs ); \
190 } \
191 \
192 static char const* revert() \
193 { return " " #rev " "; } \
194 }; \
195 /**/
196
197 BOOST_TEST_FOR_EACH_COMP_OP( DEFINE_FPV_COMPARISON )
198 #undef DEFINE_FPV_COMPARISON
199
200 //____________________________________________________________________________//
201
202 } // namespace op
203 } // namespace assertion
204 } // namespace test_tools
205 } // namespace boost
206
207 #include <boost/test/detail/enable_warnings.hpp>
208
209 #endif // BOOST_TEST_TOOLS_FPC_OP_HPP_050915GER
210