Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:40:23

0001 //  (C) Copyright John Maddock 2006.
0002 //  (C) Copyright Johan Rade 2006.
0003 //  (C) Copyright Paul A. Bristow 2011 (added changesign).
0004 
0005 //  Use, modification and distribution are subject to the
0006 //  Boost Software License, Version 1.0. (See accompanying file
0007 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0008 
0009 #ifndef BOOST_MATH_TOOLS_SIGN_HPP
0010 #define BOOST_MATH_TOOLS_SIGN_HPP
0011 
0012 #ifdef _MSC_VER
0013 #pragma once
0014 #endif
0015 
0016 #include <boost/math/tools/config.hpp>
0017 #include <boost/math/special_functions/math_fwd.hpp>
0018 #include <boost/math/special_functions/detail/fp_traits.hpp>
0019 
0020 namespace boost{ namespace math{ 
0021 
0022 namespace detail {
0023 
0024   // signbit
0025 
0026 #ifdef BOOST_MATH_USE_STD_FPCLASSIFY
0027     template<class T> 
0028     inline int signbit_impl(T x, native_tag const&)
0029     {
0030         return (std::signbit)(x) ? 1 : 0;
0031     }
0032 #endif
0033 
0034     // Generic versions first, note that these do not handle
0035     // signed zero or NaN.
0036 
0037     template<class T>
0038     inline int signbit_impl(T x, generic_tag<true> const&)
0039     {
0040         return x < 0;
0041     }
0042 
0043     template<class T> 
0044     inline int signbit_impl(T x, generic_tag<false> const&)
0045     {
0046         return x < 0;
0047     }
0048 
0049 #if defined(__GNUC__) && (LDBL_MANT_DIG == 106)
0050     //
0051     // Special handling for GCC's "double double" type, 
0052     // in this case the sign is the same as the sign we
0053     // get by casting to double, no overflow/underflow
0054     // can occur since the exponents are the same magnitude
0055     // for the two types:
0056     //
0057     inline int signbit_impl(long double x, generic_tag<true> const&)
0058     {
0059        return (boost::math::signbit)(static_cast<double>(x));
0060     }
0061     inline int signbit_impl(long double x, generic_tag<false> const&)
0062     {
0063        return (boost::math::signbit)(static_cast<double>(x));
0064     }
0065 #endif
0066 
0067     template<class T>
0068     inline int signbit_impl(T x, ieee_copy_all_bits_tag const&)
0069     {
0070         typedef typename fp_traits<T>::type traits;
0071 
0072         typename traits::bits a;
0073         traits::get_bits(x,a);
0074         return a & traits::sign ? 1 : 0;
0075     }
0076 
0077     template<class T> 
0078     inline int signbit_impl(T x, ieee_copy_leading_bits_tag const&)
0079     {
0080         typedef typename fp_traits<T>::type traits;
0081 
0082         typename traits::bits a;
0083         traits::get_bits(x,a);
0084 
0085         return a & traits::sign ? 1 : 0;
0086     }
0087 
0088     // Changesign
0089     
0090     // Generic versions first, note that these do not handle
0091     // signed zero or NaN.
0092 
0093     template<class T>
0094     inline T (changesign_impl)(T x, generic_tag<true> const&)
0095     {
0096         return -x;
0097     }
0098 
0099     template<class T>
0100     inline T (changesign_impl)(T x, generic_tag<false> const&)
0101     {
0102         return -x;
0103     }
0104 #if defined(__GNUC__) && (LDBL_MANT_DIG == 106)
0105     //
0106     // Special handling for GCC's "double double" type, 
0107     // in this case we need to change the sign of both
0108     // components of the "double double":
0109     //
0110     inline long double (changesign_impl)(long double x, generic_tag<true> const&)
0111     {
0112        double* pd = reinterpret_cast<double*>(&x);
0113        pd[0] = boost::math::changesign(pd[0]);
0114        pd[1] = boost::math::changesign(pd[1]);
0115        return x;
0116     }
0117     inline long double (changesign_impl)(long double x, generic_tag<false> const&)
0118     {
0119        double* pd = reinterpret_cast<double*>(&x);
0120        pd[0] = boost::math::changesign(pd[0]);
0121        pd[1] = boost::math::changesign(pd[1]);
0122        return x;
0123     }
0124 #endif
0125 
0126     template<class T>
0127     inline T changesign_impl(T x, ieee_copy_all_bits_tag const&)
0128     {
0129         typedef typename fp_traits<T>::sign_change_type traits;
0130 
0131         typename traits::bits a;
0132         traits::get_bits(x,a);
0133         a ^= traits::sign;
0134         traits::set_bits(x,a);
0135         return x;
0136     }
0137 
0138     template<class T>
0139     inline T (changesign_impl)(T x, ieee_copy_leading_bits_tag const&)
0140     {
0141         typedef typename fp_traits<T>::sign_change_type traits;
0142 
0143         typename traits::bits a;
0144         traits::get_bits(x,a);
0145         a ^= traits::sign;
0146         traits::set_bits(x,a);
0147         return x;
0148     }
0149 
0150 
0151 }   // namespace detail
0152 
0153 template<class T> int (signbit)(T x)
0154 { 
0155    typedef typename detail::fp_traits<T>::type traits;
0156    typedef typename traits::method method;
0157    // typedef typename boost::is_floating_point<T>::type fp_tag;
0158    typedef typename tools::promote_args_permissive<T>::type result_type;
0159    return detail::signbit_impl(static_cast<result_type>(x), method());
0160 }
0161 
0162 template <class T>
0163 inline int sign BOOST_NO_MACRO_EXPAND(const T& z)
0164 {
0165    return (z == 0) ? 0 : (boost::math::signbit)(z) ? -1 : 1;
0166 }
0167 
0168 template <class T> typename tools::promote_args_permissive<T>::type (changesign)(const T& x)
0169 { //!< \brief return unchanged binary pattern of x, except for change of sign bit. 
0170    typedef typename detail::fp_traits<T>::sign_change_type traits;
0171    typedef typename traits::method method;
0172    // typedef typename boost::is_floating_point<T>::type fp_tag;
0173    typedef typename tools::promote_args_permissive<T>::type result_type;
0174 
0175    return detail::changesign_impl(static_cast<result_type>(x), method());
0176 }
0177 
0178 template <class T, class U>
0179 inline typename tools::promote_args_permissive<T, U>::type 
0180    copysign BOOST_NO_MACRO_EXPAND(const T& x, const U& y)
0181 {
0182    BOOST_MATH_STD_USING
0183    typedef typename tools::promote_args_permissive<T, U>::type result_type;
0184    return (boost::math::signbit)(static_cast<result_type>(x)) != (boost::math::signbit)(static_cast<result_type>(y)) 
0185       ? (boost::math::changesign)(static_cast<result_type>(x)) : static_cast<result_type>(x);
0186 }
0187 
0188 } // namespace math
0189 } // namespace boost
0190 
0191 
0192 #endif // BOOST_MATH_TOOLS_SIGN_HPP
0193 
0194