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
0005
0006 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
0007 # pragma once
0008 #endif
0009
0010
0011
0012
0013
0014
0015
0016
0017
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
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
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
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 }
0113 }
0114
0115 #else
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
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
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
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 }
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
0291 #endif
0292
0293 }
0294 }
0295
0296 #endif
0297
0298 #endif