scalbn.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_SCALBN_HPP
  7. #define BOOST_MATH_CCMATH_SCALBN_HPP
  8. #include <boost/math/ccmath/detail/config.hpp>
  9. #ifdef BOOST_MATH_NO_CCMATH
  10. #error "The header <boost/math/scalbn.hpp> can only be used in C++17 and later."
  11. #endif
  12. #include <cfloat>
  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, typename Z>
  19. inline constexpr Real scalbn_impl(Real arg, Z exp) noexcept
  20. {
  21. while(exp > 0)
  22. {
  23. arg *= FLT_RADIX;
  24. --exp;
  25. }
  26. while(exp < 0)
  27. {
  28. arg /= FLT_RADIX;
  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 scalbn(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::scalbn_impl(arg, exp);
  43. }
  44. else
  45. {
  46. using std::scalbn;
  47. return scalbn(arg, exp);
  48. }
  49. }
  50. template <typename Z, std::enable_if_t<std::is_integral_v<Z>, bool> = true>
  51. inline constexpr double scalbn(Z arg, int exp) noexcept
  52. {
  53. return boost::math::ccmath::scalbn(static_cast<double>(arg), exp);
  54. }
  55. inline constexpr float scalbnf(float arg, int exp) noexcept
  56. {
  57. return boost::math::ccmath::scalbn(arg, exp);
  58. }
  59. #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
  60. inline constexpr long double scalbnl(long double arg, int exp) noexcept
  61. {
  62. return boost::math::ccmath::scalbn(arg, exp);
  63. }
  64. #endif
  65. } // Namespaces
  66. #endif // BOOST_MATH_CCMATH_SCALBN_HPP