]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/core/cmath.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / core / cmath.hpp
1 #ifndef BOOST_CORE_CMATH_HPP_INCLUDED
2 #define BOOST_CORE_CMATH_HPP_INCLUDED
3
4 // MS compatible compilers support #pragma once
5
6 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
7 # pragma once
8 #endif
9
10 // boost/core/cmath.hpp
11 //
12 // Floating point classification and sign manipulation functions
13 // Extracted from https://github.com/boostorg/lexical_cast/pull/37
14 //
15 // Copyright 2020, 2021 Peter Dimov
16 // Distributed under the Boost Software License, Version 1.0.
17 // https://www.boost.org/LICENSE_1_0.txt
18
19 #include <cmath>
20
21 #if defined(BOOST_CORE_USE_GENERIC_CMATH) || (!defined(_MSC_VER) && !defined(FP_SUBNORMAL))
22
23 #include <boost/cstdint.hpp>
24 #include <boost/static_assert.hpp>
25 #include <limits>
26 #include <cstring>
27
28 namespace boost
29 {
30 namespace core
31 {
32
33 // fpclassify return values
34
35 int const fp_zero = 0;
36 int const fp_subnormal = 1;
37 int const fp_normal = 2;
38 int const fp_infinite = 3;
39 int const fp_nan = 4;
40
41 // Classification functions
42
43 template<class T> bool isfinite( T x )
44 {
45 return x <= (std::numeric_limits<T>::max)() && x >= -(std::numeric_limits<T>::max)();
46 }
47
48 template<class T> bool isinf( T x )
49 {
50 return x > (std::numeric_limits<T>::max)() || x < -(std::numeric_limits<T>::max)();
51 }
52
53 template<class T> bool isnan( T x )
54 {
55 return !isfinite( x ) && !isinf( x );
56 }
57
58 template<class T> bool isnormal( T x )
59 {
60 return isfinite( x ) && ( x >= (std::numeric_limits<T>::min)() || x <= -(std::numeric_limits<T>::min)() );
61 }
62
63 template<class T> int fpclassify( T x )
64 {
65 if( x == 0 ) return fp_zero;
66
67 if( x < 0 ) x = -x;
68
69 if( x > (std::numeric_limits<T>::max)() ) return fp_infinite;
70
71 if( x >= (std::numeric_limits<T>::min)() ) return fp_normal;
72
73 if( x < (std::numeric_limits<T>::min)() ) return fp_subnormal;
74
75 return fp_nan;
76 }
77
78 // Sign manipulation functions
79
80 inline bool signbit( float x )
81 {
82 boost::int32_t y;
83
84 BOOST_STATIC_ASSERT( sizeof( x ) == sizeof( y ) );
85
86 std::memcpy( &y, &x, sizeof( y ) );
87
88 return y < 0;
89 }
90
91 inline bool signbit( double x )
92 {
93 boost::int64_t y;
94
95 BOOST_STATIC_ASSERT( sizeof( x ) == sizeof( y ) );
96
97 std::memcpy( &y, &x, sizeof( y ) );
98
99 return y < 0;
100 }
101
102 inline bool signbit( long double x )
103 {
104 return signbit( static_cast<double>( x ) );
105 }
106
107 template<class T> T copysign( T x, T y )
108 {
109 return signbit( x ) == signbit( y )? x: -x;
110 }
111
112 } // namespace core
113 } // namespace boost
114
115 #else // defined(BOOST_CORE_USE_GENERIC_CMATH)
116
117 #if defined(_MSC_VER) && _MSC_VER < 1800
118 # include <float.h>
119 #endif
120
121 namespace boost
122 {
123 namespace core
124 {
125 #if defined(_MSC_VER) && _MSC_VER < 1800
126
127 template<class T> T copysign( T x, T y )
128 {
129 return static_cast<T>( _copysign( static_cast<double>( x ), static_cast<double>( y ) ) );
130 }
131
132 template<class T> bool isnan( T x )
133 {
134 return _isnan( static_cast<double>( x ) ) != 0;
135 }
136
137 template<class T> bool isfinite( T x )
138 {
139 return _finite( static_cast<double>( x ) ) != 0;
140 }
141
142 template<class T> bool isinf( T x )
143 {
144 return ( _fpclass( static_cast<double>( x ) ) & ( _FPCLASS_PINF | _FPCLASS_NINF ) ) != 0;
145 }
146
147 inline bool isnormal( float x )
148 {
149 // no _fpclassf in 32 bit mode
150 unsigned y = reinterpret_cast< unsigned const& >( x );
151 unsigned exp = ( y >> 23 ) & 0xFF;
152 return exp != 0 && exp != 0xFF;
153 }
154
155 inline bool isnormal( double x )
156 {
157 return ( _fpclass( x ) & ( _FPCLASS_PN | _FPCLASS_NN ) ) != 0;
158 }
159
160 inline bool isnormal( long double x )
161 {
162 return boost::core::isnormal( static_cast<double>( x ) );
163 }
164
165 template<class T> bool signbit( T x )
166 {
167 return _copysign( 1.0, static_cast<double>( x ) ) < 0.0;
168 }
169
170 int const fp_zero = 0;
171 int const fp_subnormal = 1;
172 int const fp_normal = 2;
173 int const fp_infinite = 3;
174 int const fp_nan = 4;
175
176 inline int fpclassify( float x )
177 {
178 switch( _fpclass( x ) )
179 {
180 case _FPCLASS_SNAN:
181 case _FPCLASS_QNAN:
182
183 return fp_nan;
184
185 case _FPCLASS_NINF:
186 case _FPCLASS_PINF:
187
188 return fp_infinite;
189
190 case _FPCLASS_NZ:
191 case _FPCLASS_PZ:
192
193 return fp_zero;
194
195 default:
196
197 return boost::core::isnormal( x )? fp_normal: fp_subnormal;
198 }
199 }
200
201 inline int fpclassify( double x )
202 {
203 switch( _fpclass( x ) )
204 {
205 case _FPCLASS_SNAN:
206 case _FPCLASS_QNAN:
207
208 return fp_nan;
209
210 case _FPCLASS_NINF:
211 case _FPCLASS_PINF:
212
213 return fp_infinite;
214
215 case _FPCLASS_NZ:
216 case _FPCLASS_PZ:
217
218 return fp_zero;
219
220 case _FPCLASS_ND:
221 case _FPCLASS_PD:
222
223 return fp_subnormal;
224
225 default:
226
227 return fp_normal;
228 }
229 }
230
231 inline int fpclassify( long double x )
232 {
233 return boost::core::fpclassify( static_cast<double>( x ) );
234 }
235
236 #else
237
238 using std::isfinite;
239 using std::isnan;
240 using std::isinf;
241 using std::isnormal;
242 using std::fpclassify;
243
244 int const fp_zero = FP_ZERO;
245 int const fp_subnormal = FP_SUBNORMAL;
246 int const fp_normal = FP_NORMAL;
247 int const fp_infinite = FP_INFINITE;
248 int const fp_nan = FP_NAN;
249
250 using std::signbit;
251
252 // std::copysign doesn't exist in libstdc++ under -std=c++03
253
254 #if !defined(__GNUC__)
255
256 template<class T> T copysign( T x, T y )
257 {
258 return std::copysign( x, y );
259 }
260
261 #else
262
263 namespace detail
264 {
265
266 // ::copysignl is unreliable, use the built-ins
267
268 inline float copysign_impl( float x, float y )
269 {
270 return __builtin_copysignf( x, y );
271 }
272
273 inline double copysign_impl( double x, double y )
274 {
275 return __builtin_copysign( x, y );
276 }
277
278 inline long double copysign_impl( long double x, long double y )
279 {
280 return __builtin_copysignl( x, y );
281 }
282
283 } // namespace detail
284
285 template<class T> T copysign( T x, T y )
286 {
287 return boost::core::detail::copysign_impl( x, y );
288 }
289
290 #endif // !defined(__GNUC__)
291 #endif // #if defined(_MSC_VER) && _MSC_VER < 1800
292
293 } // namespace core
294 } // namespace boost
295
296 #endif // defined(BOOST_CORE_USE_GENERIC_CMATH)
297
298 #endif // #ifndef BOOST_CORE_CMATH_HPP_INCLUDED