fdim.hpp 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. // (C) Copyright Matt Borland 2022.
  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_FDIM_HPP
  6. #define BOOST_MATH_CCMATH_FDIM_HPP
  7. #include <boost/math/ccmath/detail/config.hpp>
  8. #ifdef BOOST_MATH_NO_CCMATH
  9. #error "The header <boost/math/fdim.hpp> can only be used in C++17 and later."
  10. #endif
  11. #include <boost/math/tools/promotion.hpp>
  12. #include <boost/math/ccmath/isnan.hpp>
  13. namespace boost::math::ccmath {
  14. namespace detail {
  15. template <typename T>
  16. constexpr T fdim_impl(const T x, const T y) noexcept
  17. {
  18. if (x <= y)
  19. {
  20. return 0;
  21. }
  22. else if ((y < 0) && (x > (std::numeric_limits<T>::max)() + y))
  23. {
  24. return std::numeric_limits<T>::infinity();
  25. }
  26. else
  27. {
  28. return x - y;
  29. }
  30. }
  31. } // Namespace detail
  32. template <typename Real, std::enable_if_t<!std::is_integral_v<Real>, bool> = true>
  33. constexpr Real fdim(Real x, Real y) noexcept
  34. {
  35. if (BOOST_MATH_IS_CONSTANT_EVALUATED(x))
  36. {
  37. if (boost::math::ccmath::isnan(x))
  38. {
  39. return x;
  40. }
  41. else if (boost::math::ccmath::isnan(y))
  42. {
  43. return y;
  44. }
  45. return boost::math::ccmath::detail::fdim_impl(x, y);
  46. }
  47. else
  48. {
  49. using std::fdim;
  50. return fdim(x, y);
  51. }
  52. }
  53. template <typename T1, typename T2>
  54. constexpr auto fdim(T1 x, T2 y) noexcept
  55. {
  56. if (BOOST_MATH_IS_CONSTANT_EVALUATED(x))
  57. {
  58. using promoted_type = boost::math::tools::promote_args_2_t<T1, T2>;
  59. return boost::math::ccmath::fdim(promoted_type(x), promoted_type(y));
  60. }
  61. else
  62. {
  63. using std::fdim;
  64. return fdim(x, y);
  65. }
  66. }
  67. constexpr float fdimf(float x, float y) noexcept
  68. {
  69. return boost::math::ccmath::fdim(x, y);
  70. }
  71. #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
  72. constexpr long double fdiml(long double x, long double y) noexcept
  73. {
  74. return boost::math::ccmath::fdim(x, y);
  75. }
  76. #endif
  77. } // Namespace boost::math::ccmath
  78. #endif // BOOST_MATH_CCMATH_FDIM_HPP