1 // (C) Copyright John Maddock 2006. 2 // (C) Copyright Johan Rade 2006. 3 // (C) Copyright Paul A. Bristow 2011 (added changesign). 4 5 // Use, modification and distribution are subject to the 6 // Boost Software License, Version 1.0. (See accompanying file 7 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 9 #ifndef BOOST_MATH_TOOLS_SIGN_HPP 10 #define BOOST_MATH_TOOLS_SIGN_HPP 11 12 #ifdef _MSC_VER 13 #pragma once 14 #endif 15 16 #include <boost/math/tools/config.hpp> 17 #include <boost/math/special_functions/math_fwd.hpp> 18 #include <boost/math/special_functions/detail/fp_traits.hpp> 19 20 namespace boost{ namespace math{ 21 22 namespace detail { 23 24 // signbit 25 26 #ifdef BOOST_MATH_USE_STD_FPCLASSIFY 27 template<class T> 28 inline int signbit_impl(T x, native_tag const&) 29 { 30 return (std::signbit)(x); 31 } 32 #endif 33 34 template<class T> 35 inline int signbit_impl(T x, generic_tag<true> const&) 36 { 37 return x < 0; 38 } 39 40 template<class T> 41 inline int signbit_impl(T x, generic_tag<false> const&) 42 { 43 return x < 0; 44 } 45 46 template<class T> 47 inline int signbit_impl(T x, ieee_copy_all_bits_tag const&) 48 { 49 typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits; 50 51 BOOST_DEDUCED_TYPENAME traits::bits a; 52 traits::get_bits(x,a); 53 return a & traits::sign ? 1 : 0; 54 } 55 56 template<class T> 57 inline int signbit_impl(T x, ieee_copy_leading_bits_tag const&) 58 { 59 typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::type traits; 60 61 BOOST_DEDUCED_TYPENAME traits::bits a; 62 traits::get_bits(x,a); 63 64 return a & traits::sign ? 1 : 0; 65 } 66 67 // Changesign 68 69 template<class T> 70 inline T (changesign_impl)(T x, generic_tag<true> const&) 71 { 72 return -x; 73 } 74 75 template<class T> 76 inline T (changesign_impl)(T x, generic_tag<false> const&) 77 { 78 return -x; 79 } 80 81 82 template<class T> 83 inline T changesign_impl(T x, ieee_copy_all_bits_tag const&) 84 { 85 typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::sign_change_type traits; 86 87 BOOST_DEDUCED_TYPENAME traits::bits a; 88 traits::get_bits(x,a); 89 a ^= traits::sign; 90 traits::set_bits(x,a); 91 return x; 92 } 93 94 template<class T> 95 inline T (changesign_impl)(T x, ieee_copy_leading_bits_tag const&) 96 { 97 typedef BOOST_DEDUCED_TYPENAME fp_traits<T>::sign_change_type traits; 98 99 BOOST_DEDUCED_TYPENAME traits::bits a; 100 traits::get_bits(x,a); 101 a ^= traits::sign; 102 traits::set_bits(x,a); 103 return x; 104 } 105 106 107 } // namespace detail 108 109 template<class T> int (signbit)(T x) 110 { 111 typedef typename detail::fp_traits<T>::type traits; 112 typedef typename traits::method method; 113 typedef typename boost::is_floating_point<T>::type fp_tag; 114 return detail::signbit_impl(x, method()); 115 } 116 117 template <class T> 118 inline int sign BOOST_NO_MACRO_EXPAND(const T& z) 119 { 120 return (z == 0) ? 0 : (boost::math::signbit)(z) ? -1 : 1; 121 } 122 123 template<class T> T (changesign)(const T& x) 124 { //!< \brief return unchanged binary pattern of x, except for change of sign bit. 125 typedef typename detail::fp_traits<T>::sign_change_type traits; 126 typedef typename traits::method method; 127 typedef typename boost::is_floating_point<T>::type fp_tag; 128 129 return detail::changesign_impl(x, method()); 130 } 131 132 template <class T> 133 inline T copysign BOOST_NO_MACRO_EXPAND(const T& x, const T& y) 134 { 135 BOOST_MATH_STD_USING 136 return (boost::math::signbit)(x) != (boost::math::signbit)(y) ? (boost::math::changesign)(x) : x; 137 } 138 139 } // namespace math 140 } // namespace boost 141 142 143 #endif // BOOST_MATH_TOOLS_SIGN_HPP 144 145 146