ldexp.hpp 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. // (C) Copyright Matt Borland 2021.
  2. // (C) Copyright John Maddock 2021.
  3. // Use, modification and distribution are subject to the
  4. // Boost Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_MATH_CCMATH_LDEXP_HPP
  7. #define BOOST_MATH_CCMATH_LDEXP_HPP
  8. #include <boost/math/ccmath/detail/config.hpp>
  9. #ifdef BOOST_MATH_NO_CCMATH
  10. #error "The header <boost/math/ldexp.hpp> can only be used in C++17 and later."
  11. #endif
  12. #include <stdexcept>
  13. #include <boost/math/ccmath/abs.hpp>
  14. #include <boost/math/ccmath/isinf.hpp>
  15. #include <boost/math/ccmath/isnan.hpp>
  16. namespace boost::math::ccmath {
  17. namespace detail {
  18. template <typename Real>
  19. inline constexpr Real ldexp_impl(Real arg, int exp) noexcept
  20. {
  21. while(exp > 0)
  22. {
  23. arg *= 2;
  24. --exp;
  25. }
  26. while(exp < 0)
  27. {
  28. arg /= 2;
  29. ++exp;
  30. }
  31. return arg;
  32. }
  33. } // Namespace detail
  34. template <typename Real, std::enable_if_t<!std::is_integral_v<Real>, bool> = true>
  35. inline constexpr Real ldexp(Real arg, int exp) noexcept
  36. {
  37. if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg))
  38. {
  39. return boost::math::ccmath::abs(arg) == Real(0) ? arg :
  40. (boost::math::ccmath::isinf)(arg) ? arg :
  41. (boost::math::ccmath::isnan)(arg) ? arg :
  42. boost::math::ccmath::detail::ldexp_impl(arg, exp);
  43. }
  44. else
  45. {
  46. using std::ldexp;
  47. return ldexp(arg, exp);
  48. }
  49. }
  50. template <typename Z, std::enable_if_t<std::is_integral_v<Z>, bool> = true>
  51. inline constexpr double ldexp(Z arg, int exp) noexcept
  52. {
  53. return boost::math::ccmath::ldexp(static_cast<double>(arg), exp);
  54. }
  55. inline constexpr float ldexpf(float arg, int exp) noexcept
  56. {
  57. return boost::math::ccmath::ldexp(arg, exp);
  58. }
  59. #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
  60. inline constexpr long double ldexpl(long double arg, int exp) noexcept
  61. {
  62. return boost::math::ccmath::ldexp(arg, exp);
  63. }
  64. #endif
  65. } // Namespaces
  66. #endif // BOOST_MATH_CCMATH_LDEXP_HPP