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
20namespace boost{ namespace math{
21
22namespace 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
109template<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
117template <class T>
118inline int sign BOOST_NO_MACRO_EXPAND(const T& z)
119{
120   return (z == 0) ? 0 : (boost::math::signbit)(z) ? -1 : 1;
121}
122
123template<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
132template <class T>
133inline 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