Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-15 08:40:22

0001 //  Copyright John Maddock 2007.
0002 //  Copyright Matt Borland 2023.
0003 //  Use, modification and distribution are subject to the
0004 //  Boost Software License, Version 1.0. (See accompanying file
0005 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 #ifndef BOOST_MATH_ROUND_HPP
0008 #define BOOST_MATH_ROUND_HPP
0009 
0010 #ifdef _MSC_VER
0011 #pragma once
0012 #endif
0013 
0014 #include <boost/math/tools/config.hpp>
0015 
0016 #ifndef BOOST_MATH_HAS_NVRTC
0017 
0018 #include <boost/math/ccmath/detail/config.hpp>
0019 #include <boost/math/policies/error_handling.hpp>
0020 #include <boost/math/special_functions/math_fwd.hpp>
0021 #include <boost/math/special_functions/fpclassify.hpp>
0022 #include <type_traits>
0023 #include <limits>
0024 #include <cmath>
0025 
0026 #if !defined(BOOST_MATH_NO_CCMATH) && !defined(BOOST_MATH_NO_CONSTEXPR_DETECTION)
0027 #include <boost/math/ccmath/ldexp.hpp>
0028 #    define BOOST_MATH_HAS_CONSTEXPR_LDEXP
0029 #endif
0030 
0031 namespace boost{ namespace math{
0032 
0033 namespace detail{
0034 
0035 template <class T, class Policy>
0036 BOOST_MATH_GPU_ENABLED inline tools::promote_args_t<T> round(const T& v, const Policy& pol, const std::false_type&)
0037 {
0038    BOOST_MATH_STD_USING
0039    using result_type = tools::promote_args_t<T>;
0040 
0041    if(!(boost::math::isfinite)(v))
0042    {
0043       return policies::raise_rounding_error("boost::math::round<%1%>(%1%)", nullptr, static_cast<result_type>(v), static_cast<result_type>(v), pol);
0044    }
0045    //
0046    // The logic here is rather convoluted, but avoids a number of traps,
0047    // see discussion here https://github.com/boostorg/math/pull/8
0048    //
0049    if (T(-0.5) < v && v < T(0.5))
0050    {
0051       // special case to avoid rounding error on the direct
0052       // predecessor of +0.5 resp. the direct successor of -0.5 in
0053       // IEEE floating point types
0054       return static_cast<result_type>(0);
0055    }
0056    else if (v > 0)
0057    {
0058       // subtract v from ceil(v) first in order to avoid rounding
0059       // errors on largest representable integer numbers
0060       result_type c(ceil(v));
0061       return T(0.5) < c - v ? c - 1 : c;
0062    }
0063    else
0064    {
0065       // see former branch
0066       result_type f(floor(v));
0067       return T(0.5) < v - f ? f + 1 : f;
0068    }
0069 }
0070 template <class T, class Policy>
0071 BOOST_MATH_GPU_ENABLED inline tools::promote_args_t<T> round(const T& v, const Policy&, const std::true_type&)
0072 {
0073    return v;
0074 }
0075 
0076 } // namespace detail
0077 
0078 template <class T, class Policy>
0079 BOOST_MATH_GPU_ENABLED inline tools::promote_args_t<T> round(const T& v, const Policy& pol)
0080 {
0081    return detail::round(v, pol, std::integral_constant<bool, detail::is_integer_for_rounding<T>::value>());
0082 }
0083 template <class T>
0084 BOOST_MATH_GPU_ENABLED inline tools::promote_args_t<T> round(const T& v)
0085 {
0086    return round(v, policies::policy<>());
0087 }
0088 //
0089 // The following functions will not compile unless T has an
0090 // implicit conversion to the integer types.  For user-defined
0091 // number types this will likely not be the case.  In that case
0092 // these functions should either be specialized for the UDT in
0093 // question, or else overloads should be placed in the same
0094 // namespace as the UDT: these will then be found via argument
0095 // dependent lookup.  See our concept archetypes for examples.
0096 //
0097 // Non-standard numeric limits syntax "(std::numeric_limits<int>::max)()"
0098 // is to avoid macro substiution from MSVC
0099 // https://stackoverflow.com/questions/27442885/syntax-error-with-stdnumeric-limitsmax
0100 //
0101 template <class T, class Policy>
0102 inline int iround(const T& v, const Policy& pol)
0103 {
0104    BOOST_MATH_STD_USING
0105    using result_type = tools::promote_args_t<T>;
0106 
0107    result_type r = boost::math::round(v, pol);
0108 
0109    #if defined(BOOST_MATH_HAS_CONSTEXPR_LDEXP) && !defined(BOOST_MATH_HAS_GPU_SUPPORT)
0110    if constexpr (std::is_arithmetic_v<result_type>
0111                  #ifdef BOOST_MATH_FLOAT128_TYPE
0112                  && !std::is_same_v<BOOST_MATH_FLOAT128_TYPE, result_type>
0113                  #endif
0114                 )
0115    {
0116       constexpr result_type max_val = boost::math::ccmath::ldexp(static_cast<result_type>(1), std::numeric_limits<int>::digits);
0117       
0118       if (r >= max_val || r < -max_val)
0119       {
0120          return static_cast<int>(boost::math::policies::raise_rounding_error("boost::math::iround<%1%>(%1%)", nullptr, v, static_cast<int>(0), pol));
0121       }
0122    }
0123    else
0124    {
0125       static const result_type max_val = ldexp(static_cast<result_type>(1), std::numeric_limits<int>::digits);
0126    
0127       if (r >= max_val || r < -max_val)
0128       {
0129          return static_cast<int>(boost::math::policies::raise_rounding_error("boost::math::iround<%1%>(%1%)", nullptr, v, static_cast<int>(0), pol));
0130       }
0131    }
0132    #else
0133    BOOST_MATH_STATIC_LOCAL_VARIABLE const result_type max_val = ldexp(static_cast<result_type>(1), std::numeric_limits<int>::digits);
0134 
0135    if (r >= max_val || r < -max_val)
0136    {
0137       return static_cast<int>(boost::math::policies::raise_rounding_error("boost::math::iround<%1%>(%1%)", nullptr, v, static_cast<int>(0), pol));
0138    }
0139    #endif
0140 
0141    return static_cast<int>(r);
0142 }
0143 template <class T>
0144 BOOST_MATH_GPU_ENABLED inline int iround(const T& v)
0145 {
0146    return iround(v, policies::policy<>());
0147 }
0148 
0149 template <class T, class Policy>
0150 BOOST_MATH_GPU_ENABLED inline long lround(const T& v, const Policy& pol)
0151 {
0152    BOOST_MATH_STD_USING
0153    using result_type = tools::promote_args_t<T>;
0154 
0155    result_type r = boost::math::round(v, pol);
0156    
0157    #if defined(BOOST_MATH_HAS_CONSTEXPR_LDEXP) && !defined(BOOST_MATH_HAS_GPU_SUPPORT)
0158    if constexpr (std::is_arithmetic_v<result_type>
0159                  #ifdef BOOST_MATH_FLOAT128_TYPE
0160                  && !std::is_same_v<BOOST_MATH_FLOAT128_TYPE, result_type>
0161                  #endif
0162                 )
0163    {
0164       constexpr result_type max_val = boost::math::ccmath::ldexp(static_cast<result_type>(1), std::numeric_limits<long>::digits);
0165       
0166       if (r >= max_val || r < -max_val)
0167       {
0168          return static_cast<long>(boost::math::policies::raise_rounding_error("boost::math::lround<%1%>(%1%)", nullptr, v, static_cast<long>(0), pol));
0169       }
0170    }
0171    else
0172    {
0173       static const result_type max_val = ldexp(static_cast<result_type>(1), std::numeric_limits<long>::digits);
0174    
0175       if (r >= max_val || r < -max_val)
0176       {
0177          return static_cast<long>(boost::math::policies::raise_rounding_error("boost::math::lround<%1%>(%1%)", nullptr, v, static_cast<long>(0), pol));
0178       }
0179    }
0180    #else
0181    BOOST_MATH_STATIC_LOCAL_VARIABLE const result_type max_val = ldexp(static_cast<result_type>(1), std::numeric_limits<long>::digits);
0182 
0183    if (r >= max_val || r < -max_val)
0184    {
0185       return static_cast<long>(boost::math::policies::raise_rounding_error("boost::math::lround<%1%>(%1%)", nullptr, v, static_cast<long>(0), pol));
0186    }
0187    #endif
0188 
0189    return static_cast<long>(r);
0190 }
0191 template <class T>
0192 BOOST_MATH_GPU_ENABLED inline long lround(const T& v)
0193 {
0194    return lround(v, policies::policy<>());
0195 }
0196 
0197 template <class T, class Policy>
0198 BOOST_MATH_GPU_ENABLED inline long long llround(const T& v, const Policy& pol)
0199 {
0200    BOOST_MATH_STD_USING
0201    using result_type = boost::math::tools::promote_args_t<T>;
0202 
0203    result_type r = boost::math::round(v, pol);
0204 
0205    #if defined(BOOST_MATH_HAS_CONSTEXPR_LDEXP) && !defined(BOOST_MATH_HAS_GPU_SUPPORT)
0206    if constexpr (std::is_arithmetic_v<result_type>
0207                  #ifdef BOOST_MATH_FLOAT128_TYPE
0208                  && !std::is_same_v<BOOST_MATH_FLOAT128_TYPE, result_type>
0209                  #endif
0210                 )
0211    {
0212       constexpr result_type max_val = boost::math::ccmath::ldexp(static_cast<result_type>(1), std::numeric_limits<long long>::digits);
0213       
0214       if (r >= max_val || r < -max_val)
0215       {
0216          return static_cast<long long>(boost::math::policies::raise_rounding_error("boost::math::llround<%1%>(%1%)", nullptr, v, static_cast<long long>(0), pol));
0217       }
0218    }
0219    else
0220    {
0221       static const result_type max_val = ldexp(static_cast<result_type>(1), std::numeric_limits<long long>::digits);
0222    
0223       if (r >= max_val || r < -max_val)
0224       {
0225          return static_cast<long long>(boost::math::policies::raise_rounding_error("boost::math::llround<%1%>(%1%)", nullptr, v, static_cast<long long>(0), pol));
0226       }
0227    }
0228    #else
0229    BOOST_MATH_STATIC_LOCAL_VARIABLE const result_type max_val = ldexp(static_cast<result_type>(1), std::numeric_limits<long long>::digits);
0230 
0231    if (r >= max_val || r < -max_val)
0232    {
0233       return static_cast<long long>(boost::math::policies::raise_rounding_error("boost::math::llround<%1%>(%1%)", nullptr, v, static_cast<long long>(0), pol));
0234    }
0235    #endif
0236 
0237    return static_cast<long long>(r);
0238 }
0239 template <class T>
0240 BOOST_MATH_GPU_ENABLED inline long long llround(const T& v)
0241 {
0242    return llround(v, policies::policy<>());
0243 }
0244 
0245 }} // namespaces
0246 
0247 #else // Specialized NVRTC overloads
0248 
0249 namespace boost {
0250 namespace math {
0251 
0252 template <typename T>
0253 BOOST_MATH_GPU_ENABLED T round(T x)
0254 {
0255    return ::round(x);
0256 }
0257 
0258 template <>
0259 BOOST_MATH_GPU_ENABLED float round(float x)
0260 {
0261    return ::roundf(x);
0262 }
0263 
0264 template <typename T, typename Policy>
0265 BOOST_MATH_GPU_ENABLED T round(T x, const Policy&)
0266 {
0267    return ::round(x);
0268 }
0269 
0270 template <typename Policy>
0271 BOOST_MATH_GPU_ENABLED float round(float x, const Policy&)
0272 {
0273    return ::roundf(x);
0274 }
0275 
0276 template <typename T>
0277 BOOST_MATH_GPU_ENABLED int iround(T x)
0278 {
0279    return static_cast<int>(::lround(x));
0280 }
0281 
0282 template <>
0283 BOOST_MATH_GPU_ENABLED int iround(float x)
0284 {
0285    return static_cast<int>(::lroundf(x));
0286 }
0287 
0288 template <typename T, typename Policy>
0289 BOOST_MATH_GPU_ENABLED int iround(T x, const Policy&)
0290 {
0291    return static_cast<int>(::lround(x));
0292 }
0293 
0294 template <typename Policy>
0295 BOOST_MATH_GPU_ENABLED int iround(float x, const Policy&)
0296 {
0297    return static_cast<int>(::lroundf(x));
0298 }
0299 
0300 template <typename T>
0301 BOOST_MATH_GPU_ENABLED long lround(T x)
0302 {
0303    return ::lround(x);
0304 }
0305 
0306 template <>
0307 BOOST_MATH_GPU_ENABLED long lround(float x)
0308 {
0309    return ::lroundf(x);
0310 }
0311 
0312 template <typename T, typename Policy>
0313 BOOST_MATH_GPU_ENABLED long lround(T x, const Policy&)
0314 {
0315    return ::lround(x);
0316 }
0317 
0318 template <typename Policy>
0319 BOOST_MATH_GPU_ENABLED long lround(float x, const Policy&)
0320 {
0321    return ::lroundf(x);
0322 }
0323 
0324 template <typename T>
0325 BOOST_MATH_GPU_ENABLED long long llround(T x)
0326 {
0327    return ::llround(x);
0328 }
0329 
0330 template <>
0331 BOOST_MATH_GPU_ENABLED long long llround(float x)
0332 {
0333    return ::llroundf(x);
0334 }
0335 
0336 template <typename T, typename Policy>
0337 BOOST_MATH_GPU_ENABLED long long llround(T x, const Policy&)
0338 {
0339    return ::llround(x);
0340 }
0341 
0342 template <typename Policy>
0343 BOOST_MATH_GPU_ENABLED long long llround(float x, const Policy&)
0344 {
0345    return ::llroundf(x);
0346 }
0347 
0348 } // Namespace math
0349 } // Namespace boost
0350 
0351 #endif // BOOST_MATH_HAS_NVRTC
0352 
0353 #endif // BOOST_MATH_ROUND_HPP