]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
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: | |
21 | value_with_epsilon(T value, T epsilon) : m_value(value), m_epsilon(epsilon) {} | |
22 | ||
23 | T value() const | |
24 | { | |
25 | return m_value; | |
26 | } | |
27 | ||
28 | T epsilon() const | |
29 | { | |
30 | return m_epsilon; | |
31 | } | |
32 | ||
33 | bool equal(T value) const | |
34 | { | |
35 | return value >= (m_value - m_epsilon) && value <= (m_value + m_epsilon); | |
36 | } | |
37 | ||
38 | friend bool operator== (T left, value_with_epsilon< T > const& right) | |
39 | { | |
40 | return right.equal(left); | |
41 | } | |
42 | friend bool operator== (value_with_epsilon< T > const& left, T right) | |
43 | { | |
44 | return left.equal(right); | |
45 | } | |
46 | ||
47 | friend bool operator!= (T left, value_with_epsilon< T > const& right) | |
48 | { | |
49 | return !right.equal(left); | |
50 | } | |
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 > | |
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 > | |
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 > | |
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_ |