floor.hpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. // (C) Copyright Matt Borland 2021.
  2. // Use, modification and distribution are subject to the
  3. // Boost Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_MATH_CCMATH_FLOOR_HPP
  6. #define BOOST_MATH_CCMATH_FLOOR_HPP
  7. #include <boost/math/ccmath/detail/config.hpp>
  8. #ifdef BOOST_MATH_NO_CCMATH
  9. #error "The header <boost/math/floor.hpp> can only be used in C++17 and later."
  10. #endif
  11. #include <boost/math/ccmath/abs.hpp>
  12. #include <boost/math/ccmath/isinf.hpp>
  13. #include <boost/math/ccmath/isnan.hpp>
  14. namespace boost::math::ccmath {
  15. namespace detail {
  16. template <typename T>
  17. inline constexpr T floor_pos_impl(T arg) noexcept
  18. {
  19. T result = 1;
  20. if(result < arg)
  21. {
  22. while(result < arg)
  23. {
  24. result *= 2;
  25. }
  26. while(result > arg)
  27. {
  28. --result;
  29. }
  30. return result;
  31. }
  32. else
  33. {
  34. return T(0);
  35. }
  36. }
  37. template <typename T>
  38. inline constexpr T floor_neg_impl(T arg) noexcept
  39. {
  40. T result = -1;
  41. if(result > arg)
  42. {
  43. while(result > arg)
  44. {
  45. result *= 2;
  46. }
  47. while(result < arg)
  48. {
  49. ++result;
  50. }
  51. if(result != arg)
  52. {
  53. --result;
  54. }
  55. }
  56. return result;
  57. }
  58. template <typename T>
  59. inline constexpr T floor_impl(T arg) noexcept
  60. {
  61. if(arg > 0)
  62. {
  63. return floor_pos_impl(arg);
  64. }
  65. else
  66. {
  67. return floor_neg_impl(arg);
  68. }
  69. }
  70. } // Namespace detail
  71. template <typename Real, std::enable_if_t<!std::is_integral_v<Real>, bool> = true>
  72. inline constexpr Real floor(Real arg) noexcept
  73. {
  74. if(BOOST_MATH_IS_CONSTANT_EVALUATED(arg))
  75. {
  76. return boost::math::ccmath::abs(arg) == Real(0) ? arg :
  77. boost::math::ccmath::isinf(arg) ? arg :
  78. boost::math::ccmath::isnan(arg) ? arg :
  79. boost::math::ccmath::detail::floor_impl(arg);
  80. }
  81. else
  82. {
  83. using std::floor;
  84. return floor(arg);
  85. }
  86. }
  87. template <typename Z, std::enable_if_t<std::is_integral_v<Z>, bool> = true>
  88. inline constexpr double floor(Z arg) noexcept
  89. {
  90. return boost::math::ccmath::floor(static_cast<double>(arg));
  91. }
  92. inline constexpr float floorf(float arg) noexcept
  93. {
  94. return boost::math::ccmath::floor(arg);
  95. }
  96. #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
  97. inline constexpr long double floorl(long double arg) noexcept
  98. {
  99. return boost::math::ccmath::floor(arg);
  100. }
  101. #endif
  102. } // Namespaces
  103. #endif // BOOST_MATH_CCMATH_FLOOR_HPP