File indexing completed on 2025-01-18 09:39:31
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_MATH_CCMATH_ABS
0009 #define BOOST_MATH_CCMATH_ABS
0010
0011 #include <boost/math/ccmath/detail/config.hpp>
0012
0013 #ifdef BOOST_MATH_NO_CCMATH
0014 #error "The header <boost/math/abs.hpp> can only be used in C++17 and later."
0015 #endif
0016
0017 #include <boost/math/tools/assert.hpp>
0018 #include <boost/math/ccmath/isnan.hpp>
0019 #include <boost/math/ccmath/isinf.hpp>
0020
0021 namespace boost::math::ccmath {
0022
0023 namespace detail {
0024
0025 template <typename T>
0026 constexpr T abs_impl(T x) noexcept
0027 {
0028 if ((boost::math::ccmath::isnan)(x))
0029 {
0030 return std::numeric_limits<T>::quiet_NaN();
0031 }
0032 else if (x == static_cast<T>(-0))
0033 {
0034 return static_cast<T>(0);
0035 }
0036
0037 if constexpr (std::is_integral_v<T>)
0038 {
0039 BOOST_MATH_ASSERT(x != (std::numeric_limits<T>::min)());
0040 }
0041
0042 return x >= 0 ? x : -x;
0043 }
0044
0045 }
0046
0047 template <typename T, std::enable_if_t<!std::is_unsigned_v<T>, bool> = true>
0048 constexpr T abs(T x) noexcept
0049 {
0050 if(BOOST_MATH_IS_CONSTANT_EVALUATED(x))
0051 {
0052 return detail::abs_impl<T>(x);
0053 }
0054 else
0055 {
0056 using std::abs;
0057 return abs(x);
0058 }
0059 }
0060
0061
0062
0063 template <typename T, std::enable_if_t<std::is_unsigned_v<T>, bool> = true>
0064 constexpr T abs(T x) noexcept
0065 {
0066 if constexpr (std::is_convertible_v<T, int>)
0067 {
0068 return detail::abs_impl<int>(static_cast<int>(x));
0069 }
0070 else
0071 {
0072 static_assert(sizeof(T) == 0, "Taking the absolute value of an unsigned value not convertible to int is UB.");
0073 return T(0);
0074 }
0075 }
0076
0077 constexpr long int labs(long int j) noexcept
0078 {
0079 return boost::math::ccmath::abs(j);
0080 }
0081
0082 constexpr long long int llabs(long long int j) noexcept
0083 {
0084 return boost::math::ccmath::abs(j);
0085 }
0086
0087 }
0088
0089 #endif