Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:35:13

0001 #ifndef BOOST_CORE_CMATH_HPP_INCLUDED
0002 #define BOOST_CORE_CMATH_HPP_INCLUDED
0003 
0004 // MS compatible compilers support #pragma once
0005 
0006 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
0007 # pragma once
0008 #endif
0009 
0010 // boost/core/cmath.hpp
0011 //
0012 // Floating point classification and sign manipulation functions
0013 // Extracted from https://github.com/boostorg/lexical_cast/pull/37
0014 //
0015 // Copyright 2020, 2021 Peter Dimov
0016 // Distributed under the Boost Software License, Version 1.0.
0017 // https://www.boost.org/LICENSE_1_0.txt
0018 
0019 #include <cmath>
0020 
0021 #if defined(BOOST_CORE_USE_GENERIC_CMATH) || (!defined(_MSC_VER) && !defined(FP_SUBNORMAL))
0022 
0023 #include <boost/cstdint.hpp>
0024 #include <boost/static_assert.hpp>
0025 #include <limits>
0026 #include <cstring>
0027 
0028 namespace boost
0029 {
0030 namespace core
0031 {
0032 
0033 // fpclassify return values
0034 
0035 int const fp_zero = 0;
0036 int const fp_subnormal = 1;
0037 int const fp_normal = 2;
0038 int const fp_infinite = 3;
0039 int const fp_nan = 4;
0040 
0041 // Classification functions
0042 
0043 template<class T> bool isfinite( T x )
0044 {
0045     return x <= (std::numeric_limits<T>::max)() && x >= -(std::numeric_limits<T>::max)();
0046 }
0047 
0048 template<class T> bool isinf( T x )
0049 {
0050     return x > (std::numeric_limits<T>::max)() || x < -(std::numeric_limits<T>::max)();
0051 }
0052 
0053 template<class T> bool isnan( T x )
0054 {
0055     return !isfinite( x ) && !isinf( x );
0056 }
0057 
0058 template<class T> bool isnormal( T x )
0059 {
0060     return isfinite( x ) && ( x >= (std::numeric_limits<T>::min)() || x <= -(std::numeric_limits<T>::min)() );
0061 }
0062 
0063 template<class T> int fpclassify( T x )
0064 {
0065     if( x == 0 ) return fp_zero;
0066 
0067     if( x < 0 ) x = -x;
0068 
0069     if( x > (std::numeric_limits<T>::max)() ) return fp_infinite;
0070 
0071     if( x >= (std::numeric_limits<T>::min)() ) return fp_normal;
0072 
0073     if( x < (std::numeric_limits<T>::min)() ) return fp_subnormal;
0074 
0075     return fp_nan;
0076 }
0077 
0078 // Sign manipulation functions
0079 
0080 inline bool signbit( float x )
0081 {
0082     boost::int32_t y;
0083 
0084     BOOST_STATIC_ASSERT( sizeof( x ) == sizeof( y ) );
0085 
0086     std::memcpy( &y, &x, sizeof( y ) );
0087 
0088     return y < 0;
0089 }
0090 
0091 inline bool signbit( double x )
0092 {
0093     boost::int64_t y;
0094 
0095     BOOST_STATIC_ASSERT( sizeof( x ) == sizeof( y ) );
0096 
0097     std::memcpy( &y, &x, sizeof( y ) );
0098 
0099     return y < 0;
0100 }
0101 
0102 inline bool signbit( long double x )
0103 {
0104     return signbit( static_cast<double>( x ) );
0105 }
0106 
0107 template<class T> T copysign( T x, T y )
0108 {
0109     return signbit( x ) == signbit( y )? x: -x;
0110 }
0111 
0112 } // namespace core
0113 } // namespace boost
0114 
0115 #else // defined(BOOST_CORE_USE_GENERIC_CMATH)
0116 
0117 #if defined(_MSC_VER) && _MSC_VER < 1800
0118 # include <float.h>
0119 #endif
0120 
0121 namespace boost
0122 {
0123 namespace core
0124 {
0125 #if defined(_MSC_VER) && _MSC_VER < 1800
0126 
0127 template<class T> T copysign( T x, T y )
0128 {
0129     return static_cast<T>( _copysign( static_cast<double>( x ), static_cast<double>( y ) ) );
0130 }
0131 
0132 template<class T> bool isnan( T x )
0133 {
0134     return _isnan( static_cast<double>( x ) ) != 0;
0135 }
0136 
0137 template<class T> bool isfinite( T x )
0138 {
0139     return _finite( static_cast<double>( x ) ) != 0;
0140 }
0141 
0142 template<class T> bool isinf( T x )
0143 {
0144     return ( _fpclass( static_cast<double>( x ) ) & ( _FPCLASS_PINF | _FPCLASS_NINF ) ) != 0;
0145 }
0146 
0147 inline bool isnormal( float x )
0148 {
0149     // no _fpclassf in 32 bit mode
0150     unsigned y = reinterpret_cast< unsigned const& >( x );
0151     unsigned exp = ( y >> 23 ) & 0xFF;
0152     return exp != 0 && exp != 0xFF;
0153 }
0154 
0155 inline bool isnormal( double x )
0156 {
0157     return ( _fpclass( x ) & ( _FPCLASS_PN | _FPCLASS_NN ) ) != 0;
0158 }
0159 
0160 inline bool isnormal( long double x )
0161 {
0162     return boost::core::isnormal( static_cast<double>( x ) );
0163 }
0164 
0165 template<class T> bool signbit( T x )
0166 {
0167     return _copysign( 1.0, static_cast<double>( x ) ) < 0.0;
0168 }
0169 
0170 int const fp_zero = 0;
0171 int const fp_subnormal = 1;
0172 int const fp_normal = 2;
0173 int const fp_infinite = 3;
0174 int const fp_nan = 4;
0175 
0176 inline int fpclassify( float x )
0177 {
0178     switch( _fpclass( x ) )
0179     {
0180     case _FPCLASS_SNAN:
0181     case _FPCLASS_QNAN:
0182 
0183         return fp_nan;
0184 
0185     case _FPCLASS_NINF:
0186     case _FPCLASS_PINF:
0187 
0188         return fp_infinite;
0189 
0190     case _FPCLASS_NZ:
0191     case _FPCLASS_PZ:
0192 
0193         return fp_zero;
0194 
0195     default:
0196 
0197         return boost::core::isnormal( x )? fp_normal: fp_subnormal;
0198     }
0199 }
0200 
0201 inline int fpclassify( double x )
0202 {
0203     switch( _fpclass( x ) )
0204     {
0205     case _FPCLASS_SNAN:
0206     case _FPCLASS_QNAN:
0207 
0208         return fp_nan;
0209 
0210     case _FPCLASS_NINF:
0211     case _FPCLASS_PINF:
0212 
0213         return fp_infinite;
0214 
0215     case _FPCLASS_NZ:
0216     case _FPCLASS_PZ:
0217 
0218         return fp_zero;
0219 
0220     case _FPCLASS_ND:
0221     case _FPCLASS_PD:
0222 
0223         return fp_subnormal;
0224 
0225     default:
0226 
0227         return fp_normal;
0228     }
0229 }
0230 
0231 inline int fpclassify( long double x )
0232 {
0233     return boost::core::fpclassify( static_cast<double>( x ) );
0234 }
0235 
0236 #else
0237 
0238 using std::isfinite;
0239 using std::isnan;
0240 using std::isinf;
0241 using std::isnormal;
0242 using std::fpclassify;
0243 
0244 int const fp_zero = FP_ZERO;
0245 int const fp_subnormal = FP_SUBNORMAL;
0246 int const fp_normal = FP_NORMAL;
0247 int const fp_infinite = FP_INFINITE;
0248 int const fp_nan = FP_NAN;
0249 
0250 using std::signbit;
0251 
0252 // std::copysign doesn't exist in libstdc++ under -std=c++03
0253 
0254 #if !defined(__GNUC__)
0255 
0256 template<class T> T copysign( T x, T y )
0257 {
0258     return std::copysign( x, y );
0259 }
0260 
0261 #else
0262 
0263 namespace detail
0264 {
0265 
0266 // ::copysignl is unreliable, use the built-ins
0267 
0268 inline float copysign_impl( float x, float y )
0269 {
0270     return __builtin_copysignf( x, y );
0271 }
0272 
0273 inline double copysign_impl( double x, double y )
0274 {
0275     return __builtin_copysign( x, y );
0276 }
0277 
0278 inline long double copysign_impl( long double x, long double y )
0279 {
0280     return __builtin_copysignl( x, y );
0281 }
0282 
0283 } // namespace detail
0284 
0285 template<class T> T copysign( T x, T y )
0286 {
0287     return boost::core::detail::copysign_impl( x, y );
0288 }
0289 
0290 #endif // !defined(__GNUC__)
0291 #endif // #if defined(_MSC_VER) && _MSC_VER < 1800
0292 
0293 } // namespace core
0294 } // namespace boost
0295 
0296 #endif // defined(BOOST_CORE_USE_GENERIC_CMATH)
0297 
0298 #endif  // #ifndef BOOST_CORE_CMATH_HPP_INCLUDED