File indexing completed on 2025-01-30 09:45:15
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_MATH_CCMATH_SCALBN_HPP
0008 #define BOOST_MATH_CCMATH_SCALBN_HPP
0009
0010 #include <boost/math/ccmath/detail/config.hpp>
0011
0012 #ifdef BOOST_MATH_NO_CCMATH
0013 #error "The header <boost/math/scalbn.hpp> can only be used in C++17 and later."
0014 #endif
0015
0016 #include <cfloat>
0017 #include <boost/math/ccmath/abs.hpp>
0018 #include <boost/math/ccmath/isinf.hpp>
0019 #include <boost/math/ccmath/isnan.hpp>
0020
0021 namespace boost::math::ccmath {
0022
0023 namespace detail {
0024
0025 template <typename Real, typename Z>
0026 inline constexpr Real scalbn_impl(Real arg, Z exp) noexcept
0027 {
0028 while(exp > 0)
0029 {
0030 arg *= FLT_RADIX;
0031 --exp;
0032 }
0033 while(exp < 0)
0034 {
0035 arg /= FLT_RADIX;
0036 ++exp;
0037 }
0038
0039 return arg;
0040 }
0041
0042 }
0043
0044 template <typename Real, std::enable_if_t<!std::is_integral_v<Real>, bool> = true>
0045 inline constexpr Real scalbn(Real arg, int exp) noexcept
0046 {
0047 if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg))
0048 {
0049 return boost::math::ccmath::abs(arg) == Real(0) ? arg :
0050 boost::math::ccmath::isinf(arg) ? arg :
0051 boost::math::ccmath::isnan(arg) ? arg :
0052 boost::math::ccmath::detail::scalbn_impl(arg, exp);
0053 }
0054 else
0055 {
0056 using std::scalbn;
0057 return scalbn(arg, exp);
0058 }
0059 }
0060
0061 template <typename Z, std::enable_if_t<std::is_integral_v<Z>, bool> = true>
0062 inline constexpr double scalbn(Z arg, int exp) noexcept
0063 {
0064 return boost::math::ccmath::scalbn(static_cast<double>(arg), exp);
0065 }
0066
0067 inline constexpr float scalbnf(float arg, int exp) noexcept
0068 {
0069 return boost::math::ccmath::scalbn(arg, exp);
0070 }
0071
0072 #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
0073 inline constexpr long double scalbnl(long double arg, int exp) noexcept
0074 {
0075 return boost::math::ccmath::scalbn(arg, exp);
0076 }
0077 #endif
0078
0079 }
0080
0081 #endif