2
0
mirror of https://github.com/boostorg/test.git synced 2026-01-24 18:32:30 +00:00

introduce fpc::tolerance_based to be used instead of if_floating_point. This should allow us to extend tolerance based comparisons t omore types

This commit is contained in:
Gennadiy Rozental
2015-03-24 00:14:48 -04:00
parent 5c1c95110f
commit 573eef160d
4 changed files with 71 additions and 76 deletions

View File

@@ -24,11 +24,11 @@
#include <boost/test/tools/fpc_tolerance.hpp>
// Boost
#include <boost/numeric/conversion/conversion_traits.hpp> // for numeric::conversion_traits
#include <boost/mpl/assert.hpp>
#include <boost/utility/declval.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/is_floating_point.hpp>
// STL
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
@@ -323,7 +323,7 @@ struct compare_fpv<op::NE<Lhs,Rhs>,FPT> {
compare( Lhs const& lhs, Rhs const& rhs )
{
fpc::close_at_tolerance<FPT> P( fpc_tolerance<FPT>(), fpc::FPC_STRONG );
assertion_result ar( !P( lhs, rhs ) );
if( !ar )
ar.message() << "Relative difference is within tolerance ["
@@ -350,8 +350,8 @@ struct compare_fpv<op::NE<Lhs,Rhs>,FPT> {
#define DEFINE_FPV_COMPARISON( oper, name, rev ) \
template<typename Lhs,typename Rhs> \
struct name<Lhs,Rhs,typename boost::enable_if_c< \
is_floating_point<Lhs>::value && \
is_floating_point<Rhs>::value>::type> { \
fpc::tolerance_based<Lhs>::value && \
fpc::tolerance_based<Rhs>::value>::type> { \
typedef typename numeric::conversion_traits<Lhs,Rhs \
>::supertype FPT; \
typedef name<Lhs,Rhs> OP; \

View File

@@ -21,9 +21,6 @@
#include <boost/test/tools/fpc_tolerance.hpp>
// Boost
#include <boost/type_traits/is_floating_point.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
@@ -51,7 +48,7 @@ template<typename FPT>
inline tolerance_manip<FPT>
operator%( FPT v, tolerance_manip_delay const& )
{
BOOST_STATIC_ASSERT( is_floating_point<FPT>::value );
BOOST_STATIC_ASSERT( fpc::tolerance_based<FPT>::value );
return tolerance_manip<FPT>( v * static_cast<FPT>(0.01) );
}
@@ -87,7 +84,7 @@ template<typename FPT>
inline tt_detail::tolerance_manip<FPT>
tolerance( FPT v )
{
BOOST_STATIC_ASSERT( is_floating_point<FPT>::value );
BOOST_STATIC_ASSERT( fpc::tolerance_based<FPT>::value );
return tt_detail::tolerance_manip<FPT>( v );
}
@@ -98,7 +95,7 @@ template<typename FPT>
inline tt_detail::tolerance_manip<FPT>
tolerance( fpc::percent_tolerance_t<FPT> v )
{
BOOST_STATIC_ASSERT( is_floating_point<FPT>::value );
BOOST_STATIC_ASSERT( fpc::tolerance_based<FPT>::value );
return tt_detail::tolerance_manip<FPT>( v.m_value * static_cast<FPT>(0.01) );
}

View File

@@ -18,9 +18,9 @@
// Boost
#include <boost/limits.hpp> // for std::numeric_limits
#include <boost/numeric/conversion/conversion_traits.hpp> // for numeric::conversion_traits
#include <boost/static_assert.hpp>
#include <boost/assert.hpp>
#include <boost/type_traits/is_floating_point.hpp>
// STL
#include <iosfwd>
@@ -33,6 +33,17 @@ namespace boost {
namespace math {
namespace fpc {
// ************************************************************************** //
// ************** fpc::tolerance_based ************** //
// ************************************************************************** //
template<typename T>
struct tolerance_based : mpl::bool_<
is_floating_point<T>::value ||
std::numeric_limits<T>::is_specialized &&
!std::numeric_limits<T>::is_integer &&
!std::numeric_limits<T>::is_exact> {};
// ************************************************************************** //
// ************** fpc::strength ************** //
// ************************************************************************** //
@@ -42,6 +53,37 @@ enum strength {
FPC_WEAK // "Close enough" - equation 2' in docs.
};
// ************************************************************************** //
// ************** tolerance presentation types ************** //
// ************************************************************************** //
template<typename FPT>
struct percent_tolerance_t {
explicit percent_tolerance_t( FPT v ) : m_value( v ) {}
FPT m_value;
};
//____________________________________________________________________________//
template<typename FPT>
inline std::ostream& operator<<( std::ostream& out, percent_tolerance_t<FPT> t )
{
return out << t.m_value;
}
//____________________________________________________________________________//
template<typename FPT>
inline percent_tolerance_t<FPT>
percent_tolerance( FPT v )
{
return percent_tolerance_t<FPT>( v );
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** details ************** //
// ************************************************************************** //
@@ -95,71 +137,26 @@ safe_fpt_division( FPT f1, FPT f2 )
//____________________________________________________________________________//
template<typename FPT, typename ToleranceType>
inline FPT
fraction_tolerance( ToleranceType tolerance )
{
return static_cast<FPT>(tolerance);
}
//____________________________________________________________________________//
template<typename FPT2, typename FPT>
inline FPT2
fraction_tolerance( percent_tolerance_t<FPT> tolerance )
{
return static_cast<FPT2>(tolerance.m_value)*static_cast<FPT2>(0.01);
}
//____________________________________________________________________________//
} // namespace fpc_detail
// ************************************************************************** //
// ************** tolerance presentation types ************** //
// ************************************************************************** //
template<typename ToleranceType>
struct tolerance_traits {
template<typename FPT>
static ToleranceType actual_tolerance( FPT fraction_tolerance )
{
return static_cast<ToleranceType>( fraction_tolerance );
}
template<typename FPT>
static FPT fraction_tolerance( ToleranceType tolerance )
{
return static_cast<FPT>(tolerance);
}
};
//____________________________________________________________________________//
template<typename FPT>
struct percent_tolerance_t {
explicit percent_tolerance_t( FPT v ) : m_value( v ) {}
FPT m_value;
};
//____________________________________________________________________________//
template<typename FPT>
struct tolerance_traits<percent_tolerance_t<FPT> > {
template<typename FPT2>
static percent_tolerance_t<FPT> actual_tolerance( FPT2 fraction_tolerance )
{
return percent_tolerance_t<FPT>( fraction_tolerance * static_cast<FPT2>(100.) );
}
template<typename FPT2>
static FPT2 fraction_tolerance( percent_tolerance_t<FPT> tolerance )
{
return static_cast<FPT2>(tolerance.m_value)*static_cast<FPT2>(0.01);
}
};
//____________________________________________________________________________//
template<typename FPT>
inline std::ostream& operator<<( std::ostream& out, percent_tolerance_t<FPT> t )
{
return out << t.m_value;
}
//____________________________________________________________________________//
template<typename FPT>
inline percent_tolerance_t<FPT>
percent_tolerance( FPT v )
{
return percent_tolerance_t<FPT>( v );
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** close_at_tolerance ************** //
// ************************************************************************** //
@@ -173,7 +170,7 @@ public:
// Constructor
template<typename ToleranceType>
explicit close_at_tolerance( ToleranceType tolerance, fpc::strength fpc_strength = FPC_STRONG )
: m_fraction_tolerance( tolerance_traits<ToleranceType>::template fraction_tolerance<FPT>( tolerance ) )
: m_fraction_tolerance( fpc_detail::fraction_tolerance<FPT>( tolerance ) )
, m_strength( fpc_strength )
, m_failed_fraction()
{
@@ -191,7 +188,7 @@ public:
FPT diff = fpc_detail::fpt_abs<FPT>( left - right );
FPT fraction_of_right = fpc_detail::safe_fpt_division( diff, fpc_detail::fpt_abs( right ) );
FPT fraction_of_left = fpc_detail::safe_fpt_division( diff, fpc_detail::fpt_abs( left ) );
bool res( m_strength == FPC_STRONG
? (fraction_of_right <= m_fraction_tolerance && fraction_of_left <= m_fraction_tolerance)
: (fraction_of_right <= m_fraction_tolerance || fraction_of_left <= m_fraction_tolerance) );

View File

@@ -25,6 +25,7 @@
// Boost
#include <boost/limits.hpp>
#include <boost/numeric/conversion/conversion_traits.hpp> // for numeric::conversion_traits
#include <boost/type_traits/is_array.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>