File indexing completed on 2025-01-18 09:52:41
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef BOOST_TEST_TOOLS_FPC_OP_HPP_050915GER
0013 #define BOOST_TEST_TOOLS_FPC_OP_HPP_050915GER
0014
0015
0016 #include <boost/test/tools/assertion.hpp>
0017
0018 #include <boost/test/tools/floating_point_comparison.hpp>
0019 #include <boost/test/tools/fpc_tolerance.hpp>
0020
0021
0022 #include <boost/type_traits/common_type.hpp>
0023 #include <boost/type_traits/is_arithmetic.hpp>
0024 #include <boost/utility/enable_if.hpp>
0025
0026 #include <boost/test/detail/suppress_warnings.hpp>
0027
0028
0029
0030 namespace boost {
0031 namespace test_tools {
0032 namespace assertion {
0033 namespace op {
0034
0035
0036
0037
0038
0039
0040 template<typename OP>
0041 struct fpctraits {
0042
0043
0044 static const bool equality_logical_disjunction = true;
0045 };
0046
0047 template <typename Lhs, typename Rhs>
0048 struct fpctraits<op::LT<Lhs,Rhs> > {
0049 static const bool equality_logical_disjunction = false;
0050 };
0051
0052 template <typename Lhs, typename Rhs>
0053 struct fpctraits<op::GT<Lhs,Rhs> > {
0054 static const bool equality_logical_disjunction = false;
0055 };
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065 template <typename FPT, typename Lhs, typename Rhs, typename OP>
0066 inline assertion_result
0067 compare_fpv( Lhs const& lhs, Rhs const& rhs, OP* cmp_operator)
0068 {
0069 assertion_result result_direct_compare = cmp_operator->eval_direct(lhs, rhs);
0070 if(fpctraits<OP>::equality_logical_disjunction) {
0071
0072
0073 if( result_direct_compare ) {
0074 result_direct_compare.message() << "operation" << OP::forward() << "on arguments yields 'true'.";
0075 return result_direct_compare;
0076 }
0077
0078 assertion_result result_eq = compare_fpv<FPT>(lhs, rhs, (op::EQ<Lhs, Rhs>*)0);
0079 result_direct_compare = result_direct_compare || result_eq;
0080 if( !result_eq ) {
0081 result_direct_compare.message() << "operation" << op::EQ<Lhs, Rhs>::forward() << "on arguments yields 'false': " << result_eq.message() << ".";
0082 }
0083 return result_direct_compare;
0084 }
0085 if( !result_direct_compare ) {
0086 result_direct_compare.message() << "operation" << OP::forward() << " on arguments yields 'false'.";
0087 return result_direct_compare;
0088 }
0089
0090 assertion_result result_neq = compare_fpv<FPT>(lhs, rhs, (op::NE<Lhs, Rhs>*)0);
0091 result_direct_compare = result_direct_compare && result_neq;
0092 if( !result_neq ) {
0093 result_direct_compare.message() << "operation" << op::NE<Lhs, Rhs>::forward() << "on arguments yields 'false': " << result_neq.message() << ".";
0094 }
0095 return result_direct_compare;
0096 }
0097
0098
0099
0100 template <typename FPT, typename Lhs, typename Rhs>
0101 inline assertion_result
0102 compare_fpv_near_zero( FPT const& fpv, op::EQ<Lhs,Rhs>* )
0103 {
0104 fpc::small_with_tolerance<FPT> P( fpc_tolerance<FPT>() );
0105
0106 assertion_result ar( P( fpv ) );
0107 if( !ar )
0108 ar.message() << "absolute value exceeds tolerance [|" << fpv << "| > "<< fpc_tolerance<FPT>() << ']';
0109
0110 return ar;
0111 }
0112
0113
0114
0115 template <typename FPT, typename Lhs, typename Rhs>
0116 inline assertion_result
0117 compare_fpv_near_zero( FPT const& fpv, op::NE<Lhs,Rhs>* )
0118 {
0119 fpc::small_with_tolerance<FPT> P( fpc_tolerance<FPT>() );
0120
0121 assertion_result ar( !P( fpv ) );
0122 if( !ar )
0123 ar.message() << "absolute value is within tolerance [|" << fpv << "| < "<< fpc_tolerance<FPT>() << ']';
0124 return ar;
0125 }
0126
0127
0128
0129 template <typename FPT, typename Lhs, typename Rhs>
0130 inline assertion_result
0131 compare_fpv( Lhs const& lhs, Rhs const& rhs, op::EQ<Lhs,Rhs>* )
0132 {
0133 if( lhs == 0 ) {
0134 return compare_fpv_near_zero<FPT>( rhs, (op::EQ<Lhs,Rhs>*)0 );
0135 }
0136 else if( rhs == 0) {
0137 return compare_fpv_near_zero<FPT>( lhs, (op::EQ<Lhs,Rhs>*)0 );
0138 }
0139 else {
0140 fpc::close_at_tolerance<FPT> P( fpc_tolerance<FPT>(), fpc::FPC_STRONG );
0141
0142 assertion_result ar( P( lhs, rhs ) );
0143 if( !ar )
0144 ar.message() << "relative difference exceeds tolerance ["
0145 << P.tested_rel_diff() << " > " << P.fraction_tolerance() << ']';
0146 return ar;
0147 }
0148 }
0149
0150
0151
0152 template <typename FPT, typename Lhs, typename Rhs>
0153 inline assertion_result
0154 compare_fpv( Lhs const& lhs, Rhs const& rhs, op::NE<Lhs,Rhs>* )
0155 {
0156 if( lhs == 0 ) {
0157 return compare_fpv_near_zero<FPT>( rhs, (op::NE<Lhs,Rhs>*)0 );
0158 }
0159 else if( rhs == 0 ) {
0160 return compare_fpv_near_zero<FPT>( lhs, (op::NE<Lhs,Rhs>*)0 );
0161 }
0162 else {
0163 fpc::close_at_tolerance<FPT> P( fpc_tolerance<FPT>(), fpc::FPC_WEAK );
0164
0165 assertion_result ar( !P( lhs, rhs ) );
0166 if( !ar )
0167 ar.message() << "relative difference is within tolerance ["
0168 << P.tested_rel_diff() << " < " << fpc_tolerance<FPT>() << ']';
0169
0170 return ar;
0171 }
0172 }
0173
0174
0175
0176 #define DEFINE_FPV_COMPARISON( oper, name, rev, name_inverse ) \
0177 template<typename Lhs,typename Rhs> \
0178 struct name<Lhs,Rhs,typename boost::enable_if_c< \
0179 (fpc::tolerance_based<Lhs>::value && \
0180 fpc::tolerance_based<Rhs>::value) || \
0181 (fpc::tolerance_based<Lhs>::value && \
0182 boost::is_arithmetic<Rhs>::value) || \
0183 (boost::is_arithmetic<Lhs>::value && \
0184 fpc::tolerance_based<Rhs>::value) \
0185 >::type> { \
0186 public: \
0187 typedef typename common_type<Lhs,Rhs>::type FPT; \
0188 typedef name<Lhs,Rhs> OP; \
0189 typedef name_inverse<Lhs, Rhs> inverse; \
0190 \
0191 typedef assertion_result result_type; \
0192 \
0193 static bool \
0194 eval_direct( Lhs const& lhs, Rhs const& rhs ) \
0195 { \
0196 return lhs oper rhs; \
0197 } \
0198 \
0199 static assertion_result \
0200 eval( Lhs const& lhs, Rhs const& rhs ) \
0201 { \
0202 if( fpc_tolerance<FPT>() == FPT(0) \
0203 || (std::numeric_limits<Lhs>::has_infinity \
0204 && (lhs == std::numeric_limits<Lhs>::infinity())) \
0205 || (std::numeric_limits<Rhs>::has_infinity \
0206 && (rhs == std::numeric_limits<Rhs>::infinity()))) \
0207 { \
0208 return eval_direct( lhs, rhs ); \
0209 } \
0210 \
0211 return compare_fpv<FPT>( lhs, rhs, (OP*)0 ); \
0212 } \
0213 \
0214 template<typename PrevExprType> \
0215 static void \
0216 report( std::ostream& ostr, \
0217 PrevExprType const& lhs, \
0218 Rhs const& rhs ) \
0219 { \
0220 lhs.report( ostr ); \
0221 ostr << revert() \
0222 << tt_detail::print_helper( rhs ); \
0223 } \
0224 \
0225 static char const* forward() \
0226 { return " " #oper " "; } \
0227 static char const* revert() \
0228 { return " " #rev " "; } \
0229 }; \
0230
0231
0232 BOOST_TEST_FOR_EACH_COMP_OP( DEFINE_FPV_COMPARISON )
0233 #undef DEFINE_FPV_COMPARISON
0234
0235
0236
0237 }
0238 }
0239 }
0240 }
0241
0242 #include <boost/test/detail/enable_warnings.hpp>
0243
0244 #endif