Chris@16: // (C) Copyright John Maddock 2006. Chris@16: // (C) Copyright Johan Rade 2006. Chris@16: // (C) Copyright Paul A. Bristow 2011 (added changesign). Chris@16: Chris@16: // Use, modification and distribution are subject to the Chris@16: // Boost Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #ifndef BOOST_MATH_TOOLS_SIGN_HPP Chris@16: #define BOOST_MATH_TOOLS_SIGN_HPP Chris@16: Chris@16: #ifdef _MSC_VER Chris@16: #pragma once Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost{ namespace math{ Chris@16: Chris@16: namespace detail { Chris@16: Chris@16: // signbit Chris@16: Chris@16: #ifdef BOOST_MATH_USE_STD_FPCLASSIFY Chris@16: template Chris@16: inline int signbit_impl(T x, native_tag const&) Chris@16: { Chris@16: return (std::signbit)(x); Chris@16: } Chris@16: #endif Chris@16: Chris@101: // Generic versions first, note that these do not handle Chris@101: // signed zero or NaN. Chris@101: Chris@101: template Chris@16: inline int signbit_impl(T x, generic_tag const&) Chris@16: { Chris@16: return x < 0; Chris@16: } Chris@16: Chris@16: template Chris@16: inline int signbit_impl(T x, generic_tag const&) Chris@16: { Chris@16: return x < 0; Chris@16: } Chris@16: Chris@101: #if defined(__GNUC__) && (LDBL_MANT_DIG == 106) Chris@101: // Chris@101: // Special handling for GCC's "double double" type, Chris@101: // in this case the sign is the same as the sign we Chris@101: // get by casting to double, no overflow/underflow Chris@101: // can occur since the exponents are the same magnitude Chris@101: // for the two types: Chris@101: // Chris@101: inline int signbit_impl(long double x, generic_tag const&) Chris@101: { Chris@101: return (boost::math::signbit)(static_cast(x)); Chris@101: } Chris@101: inline int signbit_impl(long double x, generic_tag const&) Chris@101: { Chris@101: return (boost::math::signbit)(static_cast(x)); Chris@101: } Chris@101: #endif Chris@101: Chris@101: template Chris@16: inline int signbit_impl(T x, ieee_copy_all_bits_tag const&) Chris@16: { Chris@16: typedef BOOST_DEDUCED_TYPENAME fp_traits::type traits; Chris@16: Chris@16: BOOST_DEDUCED_TYPENAME traits::bits a; Chris@16: traits::get_bits(x,a); Chris@16: return a & traits::sign ? 1 : 0; Chris@16: } Chris@16: Chris@16: template Chris@16: inline int signbit_impl(T x, ieee_copy_leading_bits_tag const&) Chris@16: { Chris@16: typedef BOOST_DEDUCED_TYPENAME fp_traits::type traits; Chris@16: Chris@16: BOOST_DEDUCED_TYPENAME traits::bits a; Chris@16: traits::get_bits(x,a); Chris@16: Chris@16: return a & traits::sign ? 1 : 0; Chris@16: } Chris@16: Chris@16: // Changesign Chris@101: Chris@101: // Generic versions first, note that these do not handle Chris@101: // signed zero or NaN. Chris@16: Chris@16: template Chris@16: inline T (changesign_impl)(T x, generic_tag const&) Chris@16: { Chris@16: return -x; Chris@16: } Chris@16: Chris@16: template Chris@16: inline T (changesign_impl)(T x, generic_tag const&) Chris@16: { Chris@16: return -x; Chris@16: } Chris@101: #if defined(__GNUC__) && (LDBL_MANT_DIG == 106) Chris@101: // Chris@101: // Special handling for GCC's "double double" type, Chris@101: // in this case we need to change the sign of both Chris@101: // components of the "double double": Chris@101: // Chris@101: inline long double (changesign_impl)(long double x, generic_tag const&) Chris@101: { Chris@101: double* pd = reinterpret_cast(&x); Chris@101: pd[0] = boost::math::changesign(pd[0]); Chris@101: pd[1] = boost::math::changesign(pd[1]); Chris@101: return x; Chris@101: } Chris@101: inline long double (changesign_impl)(long double x, generic_tag const&) Chris@101: { Chris@101: double* pd = reinterpret_cast(&x); Chris@101: pd[0] = boost::math::changesign(pd[0]); Chris@101: pd[1] = boost::math::changesign(pd[1]); Chris@101: return x; Chris@101: } Chris@101: #endif Chris@16: Chris@16: template Chris@16: inline T changesign_impl(T x, ieee_copy_all_bits_tag const&) Chris@16: { Chris@16: typedef BOOST_DEDUCED_TYPENAME fp_traits::sign_change_type traits; Chris@16: Chris@16: BOOST_DEDUCED_TYPENAME traits::bits a; Chris@16: traits::get_bits(x,a); Chris@16: a ^= traits::sign; Chris@16: traits::set_bits(x,a); Chris@16: return x; Chris@16: } Chris@16: Chris@16: template Chris@16: inline T (changesign_impl)(T x, ieee_copy_leading_bits_tag const&) Chris@16: { Chris@16: typedef BOOST_DEDUCED_TYPENAME fp_traits::sign_change_type traits; Chris@16: Chris@16: BOOST_DEDUCED_TYPENAME traits::bits a; Chris@16: traits::get_bits(x,a); Chris@16: a ^= traits::sign; Chris@16: traits::set_bits(x,a); Chris@16: return x; Chris@16: } Chris@16: Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: template int (signbit)(T x) Chris@16: { Chris@16: typedef typename detail::fp_traits::type traits; Chris@16: typedef typename traits::method method; Chris@16: // typedef typename boost::is_floating_point::type fp_tag; Chris@16: typedef typename tools::promote_args_permissive::type result_type; Chris@16: return detail::signbit_impl(static_cast(x), method()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline int sign BOOST_NO_MACRO_EXPAND(const T& z) Chris@16: { Chris@16: return (z == 0) ? 0 : (boost::math::signbit)(z) ? -1 : 1; Chris@16: } Chris@16: Chris@16: template typename tools::promote_args_permissive::type (changesign)(const T& x) Chris@16: { //!< \brief return unchanged binary pattern of x, except for change of sign bit. Chris@16: typedef typename detail::fp_traits::sign_change_type traits; Chris@16: typedef typename traits::method method; Chris@16: // typedef typename boost::is_floating_point::type fp_tag; Chris@16: typedef typename tools::promote_args_permissive::type result_type; Chris@16: Chris@16: return detail::changesign_impl(static_cast(x), method()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline typename tools::promote_args_permissive::type Chris@16: copysign BOOST_NO_MACRO_EXPAND(const T& x, const U& y) Chris@16: { Chris@16: BOOST_MATH_STD_USING Chris@16: typedef typename tools::promote_args_permissive::type result_type; Chris@16: return (boost::math::signbit)(static_cast(x)) != (boost::math::signbit)(static_cast(y)) Chris@16: ? (boost::math::changesign)(static_cast(x)) : static_cast(x); Chris@16: } Chris@16: Chris@16: } // namespace math Chris@16: } // namespace boost Chris@16: Chris@16: Chris@16: #endif // BOOST_MATH_TOOLS_SIGN_HPP Chris@16: Chris@16: