Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:39:31

0001 //  (C) Copyright Matt Borland 2021.
0002 //  Use, modification and distribution are subject to the
0003 //  Boost Software License, Version 1.0. (See accompanying file
0004 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 //
0006 //  Constepxr implementation of abs (see c.math.abs secion 26.8.2 of the ISO standard)
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 } // Namespace detail
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 // If abs() is called with an argument of type X for which is_unsigned_v<X> is true and if X
0062 // cannot be converted to int by integral promotion (7.3.7), the program is ill-formed.
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); // Unreachable, but suppresses warnings
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 } // Namespaces
0088 
0089 #endif // BOOST_MATH_CCMATH_ABS