File indexing completed on 2025-01-18 09:39:32
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_MATH_CCMATH_LDEXP_HPP
0008 #define BOOST_MATH_CCMATH_LDEXP_HPP
0009
0010 #include <boost/math/ccmath/detail/config.hpp>
0011
0012 #ifdef BOOST_MATH_NO_CCMATH
0013 #error "The header <boost/math/ldexp.hpp> can only be used in C++17 and later."
0014 #endif
0015
0016 #include <stdexcept>
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>
0026 inline constexpr Real ldexp_impl(Real arg, int exp) noexcept
0027 {
0028 while(exp > 0)
0029 {
0030 arg *= 2;
0031 --exp;
0032 }
0033 while(exp < 0)
0034 {
0035 arg /= 2;
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 ldexp(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::ldexp_impl(arg, exp);
0053 }
0054 else
0055 {
0056 using std::ldexp;
0057 return ldexp(arg, exp);
0058 }
0059 }
0060
0061 template <typename Z, std::enable_if_t<std::is_integral_v<Z>, bool> = true>
0062 inline constexpr double ldexp(Z arg, int exp) noexcept
0063 {
0064 return boost::math::ccmath::ldexp(static_cast<double>(arg), exp);
0065 }
0066
0067 inline constexpr float ldexpf(float arg, int exp) noexcept
0068 {
0069 return boost::math::ccmath::ldexp(arg, exp);
0070 }
0071
0072 #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
0073 inline constexpr long double ldexpl(long double arg, int exp) noexcept
0074 {
0075 return boost::math::ccmath::ldexp(arg, exp);
0076 }
0077 #endif
0078
0079 }
0080
0081 #endif