File indexing completed on 2025-09-17 08:36:24
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_MATH_TRUNC_HPP
0008 #define BOOST_MATH_TRUNC_HPP
0009
0010 #ifdef _MSC_VER
0011 #pragma once
0012 #endif
0013
0014 #include <boost/math/tools/config.hpp>
0015 #include <boost/math/tools/type_traits.hpp>
0016 #include <boost/math/tools/numeric_limits.hpp>
0017
0018 #ifndef BOOST_MATH_HAS_NVRTC
0019
0020 #include <type_traits>
0021 #include <boost/math/special_functions/math_fwd.hpp>
0022 #include <boost/math/ccmath/detail/config.hpp>
0023 #include <boost/math/policies/error_handling.hpp>
0024 #include <boost/math/special_functions/fpclassify.hpp>
0025 #include <boost/math/tools/is_constant_evaluated.hpp>
0026
0027 #if !defined(BOOST_MATH_NO_CCMATH) && !defined(BOOST_MATH_NO_CONSTEXPR_DETECTION)
0028 #include <boost/math/ccmath/ldexp.hpp>
0029 # define BOOST_MATH_HAS_CONSTEXPR_LDEXP
0030 #endif
0031
0032 namespace boost{ namespace math{ namespace detail{
0033
0034 template <class T, class Policy>
0035 BOOST_MATH_GPU_ENABLED inline tools::promote_args_t<T> trunc(const T& v, const Policy& pol, const std::false_type&)
0036 {
0037 BOOST_MATH_STD_USING
0038 using result_type = tools::promote_args_t<T>;
0039 if(!(boost::math::isfinite)(v))
0040 {
0041 return policies::raise_rounding_error("boost::math::trunc<%1%>(%1%)", nullptr, static_cast<result_type>(v), static_cast<result_type>(v), pol);
0042 }
0043 return (v >= 0) ? static_cast<result_type>(floor(v)) : static_cast<result_type>(ceil(v));
0044 }
0045
0046 template <class T, class Policy>
0047 BOOST_MATH_GPU_ENABLED inline tools::promote_args_t<T> trunc(const T& v, const Policy&, const std::true_type&)
0048 {
0049 return v;
0050 }
0051
0052 }
0053
0054 template <class T, class Policy>
0055 BOOST_MATH_GPU_ENABLED inline tools::promote_args_t<T> trunc(const T& v, const Policy& pol)
0056 {
0057 return detail::trunc(v, pol, std::integral_constant<bool, detail::is_integer_for_rounding<T>::value>());
0058 }
0059
0060 template <class T>
0061 BOOST_MATH_GPU_ENABLED inline tools::promote_args_t<T> trunc(const T& v)
0062 {
0063 return trunc(v, policies::policy<>());
0064 }
0065
0066 #else
0067
0068 namespace boost {
0069 namespace math {
0070
0071 namespace detail {
0072
0073 template <typename T>
0074 BOOST_MATH_GPU_ENABLED double trunc_impl(T x)
0075 {
0076 return static_cast<double>(x);
0077 }
0078
0079 BOOST_MATH_GPU_ENABLED inline float trunc_impl(float x)
0080 {
0081 return ::truncf(x);
0082 }
0083
0084 BOOST_MATH_GPU_ENABLED inline double trunc_impl(double x)
0085 {
0086 return ::trunc(x);
0087 }
0088
0089 }
0090
0091 template <typename T, typename Policy>
0092 BOOST_MATH_GPU_ENABLED auto trunc(T x, const Policy&)
0093 {
0094 return detail::trunc_impl(x);
0095 }
0096
0097 template <typename T>
0098 BOOST_MATH_GPU_ENABLED auto trunc(T x)
0099 {
0100 return detail::trunc_impl(x);
0101 }
0102
0103 #endif
0104
0105 #ifndef BOOST_MATH_HAS_NVRTC
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120 template <class T, class Policy>
0121 BOOST_MATH_GPU_ENABLED inline int itrunc(const T& v, const Policy& pol)
0122 {
0123 BOOST_MATH_STD_USING
0124 using result_type = tools::promote_args_t<T>;
0125 result_type r = boost::math::trunc(v, pol);
0126
0127 #if defined(BOOST_MATH_HAS_CONSTEXPR_LDEXP) && !defined(BOOST_MATH_HAS_GPU_SUPPORT)
0128 if constexpr (std::is_arithmetic_v<result_type>
0129 #ifdef BOOST_MATH_FLOAT128_TYPE
0130 && !std::is_same_v<BOOST_MATH_FLOAT128_TYPE, result_type>
0131 #endif
0132 )
0133 {
0134 constexpr result_type max_val = boost::math::ccmath::ldexp(static_cast<result_type>(1), std::numeric_limits<int>::digits);
0135
0136 if (r >= max_val || r < -max_val)
0137 {
0138 return static_cast<int>(boost::math::policies::raise_rounding_error("boost::math::itrunc<%1%>(%1%)", nullptr, v, static_cast<int>(0), pol));
0139 }
0140 }
0141 else
0142 {
0143 static const result_type max_val = ldexp(static_cast<result_type>(1), std::numeric_limits<int>::digits);
0144
0145 if (r >= max_val || r < -max_val)
0146 {
0147 return static_cast<int>(boost::math::policies::raise_rounding_error("boost::math::itrunc<%1%>(%1%)", nullptr, v, static_cast<int>(0), pol));
0148 }
0149 }
0150 #else
0151 BOOST_MATH_STATIC_LOCAL_VARIABLE const result_type max_val = ldexp(static_cast<result_type>(1), std::numeric_limits<int>::digits);
0152
0153 if (r >= max_val || r < -max_val)
0154 {
0155 return static_cast<int>(boost::math::policies::raise_rounding_error("boost::math::itrunc<%1%>(%1%)", nullptr, v, static_cast<int>(0), pol));
0156 }
0157 #endif
0158
0159 return static_cast<int>(r);
0160 }
0161
0162 template <class T>
0163 BOOST_MATH_GPU_ENABLED inline int itrunc(const T& v)
0164 {
0165 return itrunc(v, policies::policy<>());
0166 }
0167
0168 template <class T, class Policy>
0169 BOOST_MATH_GPU_ENABLED inline long ltrunc(const T& v, const Policy& pol)
0170 {
0171 BOOST_MATH_STD_USING
0172 using result_type = tools::promote_args_t<T>;
0173 result_type r = boost::math::trunc(v, pol);
0174
0175 #if defined(BOOST_MATH_HAS_CONSTEXPR_LDEXP) && !defined(BOOST_MATH_HAS_GPU_SUPPORT)
0176 if constexpr (std::is_arithmetic_v<result_type>
0177 #ifdef BOOST_MATH_FLOAT128_TYPE
0178 && !std::is_same_v<BOOST_MATH_FLOAT128_TYPE, result_type>
0179 #endif
0180 )
0181 {
0182 constexpr result_type max_val = boost::math::ccmath::ldexp(static_cast<result_type>(1), std::numeric_limits<long>::digits);
0183
0184 if (r >= max_val || r < -max_val)
0185 {
0186 return static_cast<long>(boost::math::policies::raise_rounding_error("boost::math::ltrunc<%1%>(%1%)", nullptr, v, static_cast<long>(0), pol));
0187 }
0188 }
0189 else
0190 {
0191 static const result_type max_val = ldexp(static_cast<result_type>(1), std::numeric_limits<long>::digits);
0192
0193 if (r >= max_val || r < -max_val)
0194 {
0195 return static_cast<long>(boost::math::policies::raise_rounding_error("boost::math::ltrunc<%1%>(%1%)", nullptr, v, static_cast<long>(0), pol));
0196 }
0197 }
0198 #else
0199 BOOST_MATH_STATIC_LOCAL_VARIABLE const result_type max_val = ldexp(static_cast<result_type>(1), std::numeric_limits<long>::digits);
0200
0201 if (r >= max_val || r < -max_val)
0202 {
0203 return static_cast<long>(boost::math::policies::raise_rounding_error("boost::math::ltrunc<%1%>(%1%)", nullptr, v, static_cast<long>(0), pol));
0204 }
0205 #endif
0206
0207 return static_cast<long>(r);
0208 }
0209
0210 template <class T>
0211 BOOST_MATH_GPU_ENABLED inline long ltrunc(const T& v)
0212 {
0213 return ltrunc(v, policies::policy<>());
0214 }
0215
0216 template <class T, class Policy>
0217 BOOST_MATH_GPU_ENABLED inline long long lltrunc(const T& v, const Policy& pol)
0218 {
0219 BOOST_MATH_STD_USING
0220 using result_type = tools::promote_args_t<T>;
0221 result_type r = boost::math::trunc(v, pol);
0222
0223 #if defined(BOOST_MATH_HAS_CONSTEXPR_LDEXP) && !defined(BOOST_MATH_HAS_GPU_SUPPORT)
0224 if constexpr (std::is_arithmetic_v<result_type>
0225 #ifdef BOOST_MATH_FLOAT128_TYPE
0226 && !std::is_same_v<BOOST_MATH_FLOAT128_TYPE, result_type>
0227 #endif
0228 )
0229 {
0230 constexpr result_type max_val = boost::math::ccmath::ldexp(static_cast<result_type>(1), std::numeric_limits<long long>::digits);
0231
0232 if (r >= max_val || r < -max_val)
0233 {
0234 return static_cast<long long>(boost::math::policies::raise_rounding_error("boost::math::lltrunc<%1%>(%1%)", nullptr, v, static_cast<long long>(0), pol));
0235 }
0236 }
0237 else
0238 {
0239 static const result_type max_val = ldexp(static_cast<result_type>(1), std::numeric_limits<long long>::digits);
0240
0241 if (r >= max_val || r < -max_val)
0242 {
0243 return static_cast<long long>(boost::math::policies::raise_rounding_error("boost::math::lltrunc<%1%>(%1%)", nullptr, v, static_cast<long long>(0), pol));
0244 }
0245 }
0246 #else
0247 BOOST_MATH_STATIC_LOCAL_VARIABLE const result_type max_val = ldexp(static_cast<result_type>(1), std::numeric_limits<long long>::digits);
0248
0249 if (r >= max_val || r < -max_val)
0250 {
0251 return static_cast<long long>(boost::math::policies::raise_rounding_error("boost::math::lltrunc<%1%>(%1%)", nullptr, v, static_cast<long long>(0), pol));
0252 }
0253 #endif
0254
0255 return static_cast<long long>(r);
0256 }
0257
0258 template <class T>
0259 BOOST_MATH_GPU_ENABLED inline long long lltrunc(const T& v)
0260 {
0261 return lltrunc(v, policies::policy<>());
0262 }
0263
0264 #else
0265
0266 namespace detail {
0267
0268 template <typename TargetType, typename T>
0269 BOOST_MATH_GPU_ENABLED TargetType integer_trunc_impl(T v)
0270 {
0271 double r = boost::math::trunc(v);
0272
0273 const double max_val = ldexp(1.0, boost::math::numeric_limits<TargetType>::digits);
0274
0275 if (r >= max_val || r < -max_val)
0276 {
0277 r = 0;
0278 }
0279
0280 return static_cast<TargetType>(r);
0281 }
0282
0283 }
0284
0285 template <typename T>
0286 BOOST_MATH_GPU_ENABLED int itrunc(T v)
0287 {
0288 return detail::integer_trunc_impl<int>(v);
0289 }
0290
0291 template <typename T, typename Policy>
0292 BOOST_MATH_GPU_ENABLED int itrunc(T v, const Policy&)
0293 {
0294 return detail::integer_trunc_impl<int>(v);
0295 }
0296
0297 template <typename T>
0298 BOOST_MATH_GPU_ENABLED long ltrunc(T v)
0299 {
0300 return detail::integer_trunc_impl<long>(v);
0301 }
0302
0303 template <typename T, typename Policy>
0304 BOOST_MATH_GPU_ENABLED long ltrunc(T v, const Policy&)
0305 {
0306 return detail::integer_trunc_impl<long>(v);
0307 }
0308
0309 template <typename T>
0310 BOOST_MATH_GPU_ENABLED long long lltrunc(T v)
0311 {
0312 return detail::integer_trunc_impl<long long>(v);
0313 }
0314
0315 template <typename T, typename Policy>
0316 BOOST_MATH_GPU_ENABLED long long lltrunc(T v, const Policy&)
0317 {
0318 return detail::integer_trunc_impl<long long>(v);
0319 }
0320
0321 #endif
0322
0323 template <class T, class Policy>
0324 BOOST_MATH_GPU_ENABLED inline boost::math::enable_if_t<boost::math::is_constructible_v<int, T>, int>
0325 iconvert(const T& v, const Policy&)
0326 {
0327 return static_cast<int>(v);
0328 }
0329
0330 template <class T, class Policy>
0331 BOOST_MATH_GPU_ENABLED inline boost::math::enable_if_t<!boost::math::is_constructible_v<int, T>, int>
0332 iconvert(const T& v, const Policy& pol)
0333 {
0334 using boost::math::itrunc;
0335 return itrunc(v, pol);
0336 }
0337
0338 template <class T, class Policy>
0339 BOOST_MATH_GPU_ENABLED inline boost::math::enable_if_t<boost::math::is_constructible_v<long, T>, long>
0340 lconvert(const T& v, const Policy&)
0341 {
0342 return static_cast<long>(v);
0343 }
0344
0345 template <class T, class Policy>
0346 BOOST_MATH_GPU_ENABLED inline boost::math::enable_if_t<!boost::math::is_constructible_v<long, T>, long>
0347 lconvert(const T& v, const Policy& pol)
0348 {
0349 using boost::math::ltrunc;
0350 return ltrunc(v, pol);
0351 }
0352
0353 template <class T, class Policy>
0354 BOOST_MATH_GPU_ENABLED inline boost::math::enable_if_t<boost::math::is_constructible_v<long long, T>, long long>
0355 llconvert(const T& v, const Policy&)
0356 {
0357 return static_cast<long long>(v);
0358 }
0359
0360 template <class T, class Policy>
0361 BOOST_MATH_GPU_ENABLED inline typename boost::math::enable_if_t<!boost::math::is_constructible_v<long long, T>, long long>
0362 llconvert(const T& v, const Policy& pol)
0363 {
0364 using boost::math::lltrunc;
0365 return lltrunc(v, pol);
0366 }
0367
0368 template <class T, class Policy>
0369 BOOST_MATH_GPU_ENABLED [[deprecated("Use llconvert")]] inline boost::math::enable_if_t<boost::math::is_constructible_v<long long, T>, long long>
0370 llconvertert(const T& v, const Policy&)
0371 {
0372 return static_cast<long long>(v);
0373 }
0374
0375 template <class T, class Policy>
0376 BOOST_MATH_GPU_ENABLED [[deprecated("Use llconvert")]] inline typename boost::math::enable_if_t<!boost::math::is_constructible_v<long long, T>, long long>
0377 llconvertert(const T& v, const Policy& pol)
0378 {
0379 using boost::math::lltrunc;
0380 return lltrunc(v, pol);
0381 }
0382
0383 }}
0384
0385 #endif