// Copyright (c) 2018 Andrey Semashev // // Distributed under the Boost Software License, Version 1.0. // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_ATOMIC_TESTS_VALUE_WITH_EPSILON_H_INCLUDED_ #define BOOST_ATOMIC_TESTS_VALUE_WITH_EPSILON_H_INCLUDED_ #include #include template< typename T > class value_with_epsilon { private: T m_value; T m_epsilon; public: value_with_epsilon(T value, T epsilon) : m_value(value), m_epsilon(epsilon) {} T value() const { return m_value; } T epsilon() const { return m_epsilon; } bool equal(T value) const { return value >= (m_value - m_epsilon) && value <= (m_value + m_epsilon); } friend bool operator== (T left, value_with_epsilon< T > const& right) { return right.equal(left); } friend bool operator== (value_with_epsilon< T > const& left, T right) { return left.equal(right); } friend bool operator!= (T left, value_with_epsilon< T > const& right) { return !right.equal(left); } friend bool operator!= (value_with_epsilon< T > const& left, T right) { return !left.equal(right); } }; template< typename Char, typename Traits, typename T > inline std::basic_ostream< Char, Traits >& operator<< (std::basic_ostream< Char, Traits >& strm, value_with_epsilon< T > const& val) { // Note: libstdc++ does not provide output operators for __float128. There may also be no operators for long double. // We don't use such floating point values in our tests where the cast would matter. strm << static_cast< double >(val.value()) << " (+/-" << static_cast< double >(val.epsilon()) << ")"; return strm; } template< typename T, typename U > inline value_with_epsilon< T > approx(T value, U epsilon) { return value_with_epsilon< T >(value, static_cast< T >(epsilon)); } template< typename T > inline value_with_epsilon< T > approx(T value) { return value_with_epsilon< T >(value, static_cast< T >(0.0000001)); } #endif // BOOST_ATOMIC_TESTS_VALUE_WITH_EPSILON_H_INCLUDED_