// Distributed under the Boost Software License Version 1.0 https://www.boost.org/LICENSE_1_0.txt // Copyright Gero Peterhoff #ifndef BOOST_MATH_CCMATH_COPYSIGN_HPP #define BOOST_MATH_CCMATH_COPYSIGN_HPP #include #include #include #include #include #include #include namespace boost::math::ccmath { namespace detail { template inline constexpr T copysign_impl(const T mag, const T sgn) noexcept { if constexpr (boost::is_float128_v) { auto bits = BOOST_MATH_BIT_CAST(float128_bits, mag); bits.sign = boost::math::ccmath::signbit(sgn); return BOOST_MATH_BIT_CAST(T, bits); } else if constexpr (boost::is_float80_v) { if constexpr (sizeof(T) == 16) { auto bits = BOOST_MATH_BIT_CAST(float80_bits_128, mag); bits.sign = boost::math::ccmath::signbit(sgn); return BOOST_MATH_BIT_CAST(T, bits); } else if constexpr (sizeof(T) == 12) { auto bits = BOOST_MATH_BIT_CAST(float80_bits_96, mag); bits.sign = boost::math::ccmath::signbit(sgn); return BOOST_MATH_BIT_CAST(T, bits); } else if constexpr (sizeof(T) == 10) { auto bits = BOOST_MATH_BIT_CAST(float80_bits_80, mag); bits.sign = boost::math::ccmath::signbit(sgn); return BOOST_MATH_BIT_CAST(T, bits); } else { static_assert(boost::dependent_false_v, "copysign is not supported with this type or platform"); return 0; } } else if constexpr (boost::is_float64_v) { auto bits = BOOST_MATH_BIT_CAST(float64_bits, mag); bits.sign = boost::math::ccmath::signbit(sgn); return BOOST_MATH_BIT_CAST(T, bits); } else if constexpr (boost::is_float32_v) { auto bits = BOOST_MATH_BIT_CAST(float32_bits, mag); bits.sign = boost::math::ccmath::signbit(sgn); return BOOST_MATH_BIT_CAST(T, bits); } else if constexpr (boost::is_float16_v) { auto bits = BOOST_MATH_BIT_CAST(float16_bits, mag); bits.sign = boost::math::ccmath::signbit(sgn); return BOOST_MATH_BIT_CAST(T, bits); } else if constexpr (boost::is_bfloat16_v) { auto bits = BOOST_MATH_BIT_CAST(bfloat16_bits, mag); bits.sign = boost::math::ccmath::signbit(sgn); return BOOST_MATH_BIT_CAST(T, bits); } else { static_assert(boost::dependent_false_v, "copysign is not supported with this type or platform"); return 0; } } } // detail template constexpr auto copysign(const T1 mag, const T2 sgn) noexcept { BOOST_IF_CONSTEXPR (std::is_arithmetic_v && std::is_arithmetic_v) { if (BOOST_MATH_IS_CONSTANT_EVALUATED(mag)) { using promoted_type = decltype(std::copysign(mag, sgn)); return detail::copysign_impl(promoted_type(mag), promoted_type(sgn)); } else { return std::copysign(mag, sgn); } } else { static_assert(boost::dependent_false_v, "copysign is not supported with this type or platform"); return 0; } } constexpr float copysignf(const float mag, const float sgn) noexcept { return boost::math::ccmath::copysign(mag, sgn); } constexpr long double copysignl(const long double mag, const long double sgn) noexcept { return boost::math::ccmath::copysign(mag, sgn); } } // boost::math::ccmath #endif // BOOST_MATH_CCMATH_COPYSIGN_HPP