Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 08:49:25

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