div.hpp 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  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_DIV_HPP
  6. #define BOOST_MATH_CCMATH_DIV_HPP
  7. #include <cinttypes>
  8. #include <cstdint>
  9. #include <boost/math/ccmath/detail/config.hpp>
  10. #ifdef BOOST_MATH_NO_CCMATH
  11. #error "The header <boost/math/div.hpp> can only be used in C++17 and later."
  12. #endif
  13. namespace boost::math::ccmath {
  14. namespace detail {
  15. template <typename ReturnType, typename Z>
  16. inline constexpr ReturnType div_impl(const Z x, const Z y) noexcept
  17. {
  18. // std::div_t/ldiv_t/lldiv_t/imaxdiv_t can be defined as either { Z quot; Z rem; }; or { Z rem; Z quot; };
  19. // so don't use braced initialization to guarantee compatibility
  20. ReturnType ans {0, 0};
  21. ans.quot = x / y;
  22. ans.rem = x % y;
  23. return ans;
  24. }
  25. } // Namespace detail
  26. // Used for types other than built-ins (e.g. boost multiprecision)
  27. template <typename Z>
  28. struct div_t
  29. {
  30. Z quot;
  31. Z rem;
  32. };
  33. template <typename Z>
  34. inline constexpr auto div(Z x, Z y) noexcept
  35. {
  36. if constexpr (std::is_same_v<Z, int>)
  37. {
  38. return detail::div_impl<std::div_t>(x, y);
  39. }
  40. else if constexpr (std::is_same_v<Z, long>)
  41. {
  42. return detail::div_impl<std::ldiv_t>(x, y);
  43. }
  44. else if constexpr (std::is_same_v<Z, long long>)
  45. {
  46. return detail::div_impl<std::lldiv_t>(x, y);
  47. }
  48. else if constexpr (std::is_same_v<Z, std::intmax_t>)
  49. {
  50. return detail::div_impl<std::imaxdiv_t>(x, y);
  51. }
  52. else
  53. {
  54. return detail::div_impl<boost::math::ccmath::div_t<Z>>(x, y);
  55. }
  56. }
  57. inline constexpr std::ldiv_t ldiv(long x, long y) noexcept
  58. {
  59. return detail::div_impl<std::ldiv_t>(x, y);
  60. }
  61. inline constexpr std::lldiv_t lldiv(long long x, long long y) noexcept
  62. {
  63. return detail::div_impl<std::lldiv_t>(x, y);
  64. }
  65. inline constexpr std::imaxdiv_t imaxdiv(std::intmax_t x, std::intmax_t y) noexcept
  66. {
  67. return detail::div_impl<std::imaxdiv_t>(x, y);
  68. }
  69. } // Namespaces
  70. #endif // BOOST_MATH_CCMATH_DIV_HPP