File indexing completed on 2025-09-15 08:40:22
0001
0002
0003
0004
0005
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
0047
0048
0049 if (T(-0.5) < v && v < T(0.5))
0050 {
0051
0052
0053
0054 return static_cast<result_type>(0);
0055 }
0056 else if (v > 0)
0057 {
0058
0059
0060 result_type c(ceil(v));
0061 return T(0.5) < c - v ? c - 1 : c;
0062 }
0063 else
0064 {
0065
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 }
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
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
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 }}
0246
0247 #else
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 }
0349 }
0350
0351 #endif
0352
0353 #endif