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