copysign.hpp 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  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_COPYSIGN_HPP
  6. #define BOOST_MATH_CCMATH_COPYSIGN_HPP
  7. #include <cmath>
  8. #include <cstdint>
  9. #include <limits>
  10. #include <type_traits>
  11. #include <boost/math/tools/is_constant_evaluated.hpp>
  12. #include <boost/math/tools/promotion.hpp>
  13. #include <boost/math/tools/config.hpp>
  14. #include <boost/math/ccmath/abs.hpp>
  15. #include <boost/math/ccmath/signbit.hpp>
  16. namespace boost::math::ccmath {
  17. namespace detail {
  18. template <typename T>
  19. constexpr T copysign_impl(const T mag, const T sgn) noexcept
  20. {
  21. if (boost::math::ccmath::signbit(sgn))
  22. {
  23. return -boost::math::ccmath::abs(mag);
  24. }
  25. else
  26. {
  27. return boost::math::ccmath::abs(mag);
  28. }
  29. }
  30. } // Namespace detail
  31. template <typename Real, std::enable_if_t<!std::is_integral_v<Real>, bool> = true>
  32. constexpr Real copysign(Real mag, Real sgn) noexcept
  33. {
  34. if(BOOST_MATH_IS_CONSTANT_EVALUATED(mag))
  35. {
  36. return boost::math::ccmath::detail::copysign_impl(mag, sgn);
  37. }
  38. else
  39. {
  40. using std::copysign;
  41. return copysign(mag, sgn);
  42. }
  43. }
  44. template <typename T1, typename T2>
  45. constexpr auto copysign(T1 mag, T2 sgn) noexcept
  46. {
  47. if (BOOST_MATH_IS_CONSTANT_EVALUATED(mag))
  48. {
  49. using promoted_type = boost::math::tools::promote_args_2_t<T1, T2>;
  50. return boost::math::ccmath::copysign(static_cast<promoted_type>(mag), static_cast<promoted_type>(sgn));
  51. }
  52. else
  53. {
  54. using std::copysign;
  55. return copysign(mag, sgn);
  56. }
  57. }
  58. constexpr float copysignf(float mag, float sgn) noexcept
  59. {
  60. return boost::math::ccmath::copysign(mag, sgn);
  61. }
  62. #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
  63. constexpr long double copysignl(long double mag, long double sgn) noexcept
  64. {
  65. return boost::math::ccmath::copysign(mag, sgn);
  66. }
  67. #endif
  68. } // Namespaces
  69. #endif // BOOST_MATH_CCMATH_COPYSIGN_HPP