1 //  Copyright (c) 2018 Andrey Semashev
2 //
3 //  Distributed under the Boost Software License, Version 1.0.
4 //  See accompanying file LICENSE_1_0.txt or copy at
5 //  http://www.boost.org/LICENSE_1_0.txt)
6 
7 #ifndef BOOST_ATOMIC_TESTS_VALUE_WITH_EPSILON_H_INCLUDED_
8 #define BOOST_ATOMIC_TESTS_VALUE_WITH_EPSILON_H_INCLUDED_
9 
10 #include <limits>
11 #include <iosfwd>
12 
13 template< typename T >
14 class value_with_epsilon
15 {
16 private:
17     T m_value;
18     T m_epsilon;
19 
20 public:
value_with_epsilon(T value,T epsilon)21     value_with_epsilon(T value, T epsilon) : m_value(value), m_epsilon(epsilon) {}
22 
value() const23     T value() const
24     {
25         return m_value;
26     }
27 
epsilon() const28     T epsilon() const
29     {
30         return m_epsilon;
31     }
32 
equal(T value) const33     bool equal(T value) const
34     {
35         return value >= (m_value - m_epsilon) && value <= (m_value + m_epsilon);
36     }
37 
operator ==(T left,value_with_epsilon<T> const & right)38     friend bool operator== (T left, value_with_epsilon< T > const& right)
39     {
40         return right.equal(left);
41     }
operator ==(value_with_epsilon<T> const & left,T right)42     friend bool operator== (value_with_epsilon< T > const& left, T right)
43     {
44         return left.equal(right);
45     }
46 
operator !=(T left,value_with_epsilon<T> const & right)47     friend bool operator!= (T left, value_with_epsilon< T > const& right)
48     {
49         return !right.equal(left);
50     }
operator !=(value_with_epsilon<T> const & left,T right)51     friend bool operator!= (value_with_epsilon< T > const& left, T right)
52     {
53         return !left.equal(right);
54     }
55 };
56 
57 template< typename Char, typename Traits, typename T >
operator <<(std::basic_ostream<Char,Traits> & strm,value_with_epsilon<T> const & val)58 inline std::basic_ostream< Char, Traits >& operator<< (std::basic_ostream< Char, Traits >& strm, value_with_epsilon< T > const& val)
59 {
60     // Note: libstdc++ does not provide output operators for __float128. There may also be no operators for long double.
61     //       We don't use such floating point values in our tests where the cast would matter.
62     strm << static_cast< double >(val.value()) << " (+/-" << static_cast< double >(val.epsilon()) << ")";
63     return strm;
64 }
65 
66 template< typename T, typename U >
approx(T value,U epsilon)67 inline value_with_epsilon< T > approx(T value, U epsilon)
68 {
69     return value_with_epsilon< T >(value, static_cast< T >(epsilon));
70 }
71 
72 template< typename T >
approx(T value)73 inline value_with_epsilon< T > approx(T value)
74 {
75     return value_with_epsilon< T >(value, static_cast< T >(0.0000001));
76 }
77 
78 #endif // BOOST_ATOMIC_TESTS_VALUE_WITH_EPSILON_H_INCLUDED_
79