1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 |
- #ifndef BOOST_MATH_CCMATH_ABS
- #define BOOST_MATH_CCMATH_ABS
- #include <boost/math/ccmath/detail/config.hpp>
- #ifdef BOOST_MATH_NO_CCMATH
- #error "The header <boost/math/abs.hpp> can only be used in C++17 and later."
- #endif
- #include <boost/math/tools/assert.hpp>
- #include <boost/math/ccmath/isnan.hpp>
- #include <boost/math/ccmath/isinf.hpp>
- namespace boost::math::ccmath {
- namespace detail {
- template <typename T>
- constexpr T abs_impl(T x) noexcept
- {
- if ((boost::math::ccmath::isnan)(x))
- {
- return std::numeric_limits<T>::quiet_NaN();
- }
- else if (x == static_cast<T>(-0))
- {
- return static_cast<T>(0);
- }
- if constexpr (std::is_integral_v<T>)
- {
- BOOST_MATH_ASSERT(x != (std::numeric_limits<T>::min)());
- }
-
- return x >= 0 ? x : -x;
- }
- }
- template <typename T, std::enable_if_t<!std::is_unsigned_v<T>, bool> = true>
- constexpr T abs(T x) noexcept
- {
- if(BOOST_MATH_IS_CONSTANT_EVALUATED(x))
- {
- return detail::abs_impl<T>(x);
- }
- else
- {
- using std::abs;
- return abs(x);
- }
- }
- template <typename T, std::enable_if_t<std::is_unsigned_v<T>, bool> = true>
- constexpr T abs(T x) noexcept
- {
- if constexpr (std::is_convertible_v<T, int>)
- {
- return detail::abs_impl<int>(static_cast<int>(x));
- }
- else
- {
- static_assert(sizeof(T) == 0, "Taking the absolute value of an unsigned value not convertible to int is UB.");
- return T(0);
- }
- }
- constexpr long int labs(long int j) noexcept
- {
- return boost::math::ccmath::abs(j);
- }
- constexpr long long int llabs(long long int j) noexcept
- {
- return boost::math::ccmath::abs(j);
- }
- }
- #endif
|