atomic/test/value_with_epsilon.hpp
Andrey Semashev edef50f042 Added support for atomic floating point operations.
The support includes:

- The standard fetch_add/fetch_sub operations.
- Extra operations: (fetch_/opaque_)negate, (opaque_)add/sub.
- Extra capability macros: BOOST_ATOMIC_FLOAT/DOUBLE/LONG_DOUBLE_LOCK_FREE.

The atomic operations are currently implemented on top of the integer-based
backends and thus are mostly CAS-based. The CAS operations perform binary
comparisons, and as such have different behavior wrt. special FP values like
NaN and signed zero than normal C++.

The support for floating point types is optional and can be disabled by
defining BOOST_ATOMIC_NO_FLOATING_POINT. This can be useful if on a certain
platform parameters of the floating point types cannot be deduced from the
compiler-defined or system macros (in which case the compilation fails).

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0020r6.html
2018-02-13 03:36:35 +03:00

79 lines
2.1 KiB
C++

// 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 <limits>
#include <iosfwd>
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_