1 | // Copyright (c) 2006-7 John Maddock |
2 | // Use, modification and distribution are subject to the |
3 | // Boost Software License, Version 1.0. (See accompanying file |
4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
5 | |
6 | #ifndef BOOST_MATH_TOOLS_CONFIG_HPP |
7 | #define BOOST_MATH_TOOLS_CONFIG_HPP |
8 | |
9 | #ifdef _MSC_VER |
10 | #pragma once |
11 | #endif |
12 | |
13 | #include <boost/config.hpp> |
14 | #include <boost/predef.h> |
15 | #include <boost/cstdint.hpp> // for boost::uintmax_t |
16 | #include <boost/detail/workaround.hpp> |
17 | #include <boost/type_traits/is_integral.hpp> |
18 | #include <algorithm> // for min and max |
19 | #include <boost/config/no_tr1/cmath.hpp> |
20 | #include <climits> |
21 | #include <cfloat> |
22 | #if (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) |
23 | # include <math.h> |
24 | #endif |
25 | #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS |
26 | # include <limits> |
27 | #endif |
28 | |
29 | #include <boost/math/tools/user.hpp> |
30 | |
31 | #if (defined(__CYGWIN__) || defined(__FreeBSD__) || defined(__NetBSD__) \ |
32 | || (defined(__hppa) && !defined(__OpenBSD__) && !defined(__linux__)) \ |
33 | || (defined(__NO_LONG_DOUBLE_MATH) && (DBL_MANT_DIG != LDBL_MANT_DIG))) \ |
34 | && !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) |
35 | # define BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS |
36 | #endif |
37 | #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) |
38 | // |
39 | // Borland post 5.8.2 uses Dinkumware's std C lib which |
40 | // doesn't have true long double precision. Earlier |
41 | // versions are problematic too: |
42 | // |
43 | # define BOOST_MATH_NO_REAL_CONCEPT_TESTS |
44 | # define BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS |
45 | # define BOOST_MATH_CONTROL_FP _control87(MCW_EM,MCW_EM) |
46 | # include <float.h> |
47 | #endif |
48 | #ifdef __IBMCPP__ |
49 | // |
50 | // For reasons I don't unserstand, the tests with IMB's compiler all |
51 | // pass at long double precision, but fail with real_concept, those tests |
52 | // are disabled for now. (JM 2012). |
53 | # define BOOST_MATH_NO_REAL_CONCEPT_TESTS |
54 | #endif |
55 | #ifdef sun |
56 | // Any use of __float128 in program startup code causes a segfault (tested JM 2015, Solaris 11). |
57 | # define BOOST_MATH_DISABLE_FLOAT128 |
58 | #endif |
59 | #ifdef __HAIKU__ |
60 | // |
61 | // Not sure what's up with the math detection on Haiku, but linking fails with |
62 | // float128 code enabled, and we don't have an implementation of __expl, so |
63 | // disabling long double functions for now as well. |
64 | # define BOOST_MATH_DISABLE_FLOAT128 |
65 | # define BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS |
66 | #endif |
67 | #if (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) && ((LDBL_MANT_DIG == 106) || (__LDBL_MANT_DIG__ == 106)) && !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) |
68 | // |
69 | // Darwin's rather strange "double double" is rather hard to |
70 | // support, it should be possible given enough effort though... |
71 | // |
72 | # define BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS |
73 | #endif |
74 | #if defined(unix) && defined(__INTEL_COMPILER) && (__INTEL_COMPILER <= 1000) && !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) |
75 | // |
76 | // Intel compiler prior to version 10 has sporadic problems |
77 | // calling the long double overloads of the std lib math functions: |
78 | // calling ::powl is OK, but std::pow(long double, long double) |
79 | // may segfault depending upon the value of the arguments passed |
80 | // and the specific Linux distribution. |
81 | // |
82 | // We'll be conservative and disable long double support for this compiler. |
83 | // |
84 | // Comment out this #define and try building the tests to determine whether |
85 | // your Intel compiler version has this issue or not. |
86 | // |
87 | # define BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS |
88 | #endif |
89 | #if defined(unix) && defined(__INTEL_COMPILER) |
90 | // |
91 | // Intel compiler has sporadic issues compiling std::fpclassify depending on |
92 | // the exact OS version used. Use our own code for this as we know it works |
93 | // well on Intel processors: |
94 | // |
95 | #define BOOST_MATH_DISABLE_STD_FPCLASSIFY |
96 | #endif |
97 | |
98 | #if defined(BOOST_MSVC) && !defined(_WIN32_WCE) |
99 | // Better safe than sorry, our tests don't support hardware exceptions: |
100 | # define BOOST_MATH_CONTROL_FP _control87(MCW_EM,MCW_EM) |
101 | #endif |
102 | |
103 | #ifdef __IBMCPP__ |
104 | # define BOOST_MATH_NO_DEDUCED_FUNCTION_POINTERS |
105 | #endif |
106 | |
107 | #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)) |
108 | # define BOOST_MATH_USE_C99 |
109 | #endif |
110 | |
111 | #if (defined(__hpux) && !defined(__hppa)) |
112 | # define BOOST_MATH_USE_C99 |
113 | #endif |
114 | |
115 | #if defined(__GNUC__) && defined(_GLIBCXX_USE_C99) |
116 | # define BOOST_MATH_USE_C99 |
117 | #endif |
118 | |
119 | #if defined(_LIBCPP_VERSION) && !defined(_MSC_VER) |
120 | # define BOOST_MATH_USE_C99 |
121 | #endif |
122 | |
123 | #if defined(__CYGWIN__) || defined(__HP_aCC) || defined(BOOST_INTEL) \ |
124 | || defined(BOOST_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY) \ |
125 | || (defined(__GNUC__) && !defined(BOOST_MATH_USE_C99))\ |
126 | || defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) |
127 | # define BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY |
128 | #endif |
129 | |
130 | #if BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) |
131 | |
132 | # include "boost/type.hpp" |
133 | # include "boost/non_type.hpp" |
134 | |
135 | # define BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(t) boost::type<t>* = 0 |
136 | # define BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(t) boost::type<t>* |
137 | # define BOOST_MATH_EXPLICIT_TEMPLATE_NON_TYPE(t, v) boost::non_type<t, v>* = 0 |
138 | # define BOOST_MATH_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v) boost::non_type<t, v>* |
139 | |
140 | # define BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(t) \ |
141 | , BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(t) |
142 | # define BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(t) \ |
143 | , BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(t) |
144 | # define BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(t, v) \ |
145 | , BOOST_MATH_EXPLICIT_TEMPLATE_NON_TYPE(t, v) |
146 | # define BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v) \ |
147 | , BOOST_MATH_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v) |
148 | |
149 | #else |
150 | |
151 | // no workaround needed: expand to nothing |
152 | |
153 | # define BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(t) |
154 | # define BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(t) |
155 | # define BOOST_MATH_EXPLICIT_TEMPLATE_NON_TYPE(t, v) |
156 | # define BOOST_MATH_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v) |
157 | |
158 | # define BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(t) |
159 | # define BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(t) |
160 | # define BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(t, v) |
161 | # define BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v) |
162 | |
163 | |
164 | #endif // __SUNPRO_CC |
165 | |
166 | #if (defined(__SUNPRO_CC) || defined(__hppa) || defined(__GNUC__)) && !defined(BOOST_MATH_SMALL_CONSTANT) |
167 | // Sun's compiler emits a hard error if a constant underflows, |
168 | // as does aCC on PA-RISC, while gcc issues a large number of warnings: |
169 | # define BOOST_MATH_SMALL_CONSTANT(x) 0.0 |
170 | #else |
171 | # define BOOST_MATH_SMALL_CONSTANT(x) x |
172 | #endif |
173 | |
174 | |
175 | #if BOOST_WORKAROUND(BOOST_MSVC, < 1400) |
176 | // |
177 | // Define if constants too large for a float cause "bad" |
178 | // values to be stored in the data, rather than infinity |
179 | // or a suitably large value. |
180 | // |
181 | # define BOOST_MATH_BUGGY_LARGE_FLOAT_CONSTANTS |
182 | #endif |
183 | // |
184 | // Tune performance options for specific compilers: |
185 | // |
186 | #ifdef BOOST_MSVC |
187 | # define BOOST_MATH_POLY_METHOD 2 |
188 | # define BOOST_MATH_RATIONAL_METHOD 1 |
189 | #elif defined(BOOST_INTEL) |
190 | # define BOOST_MATH_POLY_METHOD 2 |
191 | # define BOOST_MATH_RATIONAL_METHOD 1 |
192 | #elif defined(__GNUC__) |
193 | #if __GNUC__ < 4 |
194 | # define BOOST_MATH_POLY_METHOD 3 |
195 | # define BOOST_MATH_RATIONAL_METHOD 3 |
196 | # define BOOST_MATH_INT_TABLE_TYPE(RT, IT) RT |
197 | # define BOOST_MATH_INT_VALUE_SUFFIX(RV, SUF) RV##.0L |
198 | #else |
199 | # define BOOST_MATH_POLY_METHOD 3 |
200 | # define BOOST_MATH_RATIONAL_METHOD 1 |
201 | #endif |
202 | #endif |
203 | |
204 | #if defined(BOOST_NO_LONG_LONG) && !defined(BOOST_MATH_INT_TABLE_TYPE) |
205 | # define BOOST_MATH_INT_TABLE_TYPE(RT, IT) RT |
206 | # define BOOST_MATH_INT_VALUE_SUFFIX(RV, SUF) RV##.0L |
207 | #endif |
208 | |
209 | // |
210 | // constexpr support, early GCC implementations can't cope so disable |
211 | // constexpr for them: |
212 | // |
213 | #if !defined(__clang) && defined(__GNUC__) |
214 | #if (__GNUC__ * 100 + __GNUC_MINOR__) < 490 |
215 | # define BOOST_MATH_DISABLE_CONSTEXPR |
216 | #endif |
217 | #endif |
218 | |
219 | #ifdef BOOST_MATH_DISABLE_CONSTEXPR |
220 | # define BOOST_MATH_CONSTEXPR |
221 | #else |
222 | # define BOOST_MATH_CONSTEXPR BOOST_CONSTEXPR |
223 | #endif |
224 | |
225 | // |
226 | // noexcept support: |
227 | // |
228 | #ifndef BOOST_NO_CXX11_NOEXCEPT |
229 | #ifndef BOOST_NO_CXX11_HDR_TYPE_TRAITS |
230 | #include <type_traits> |
231 | # define BOOST_MATH_NOEXCEPT(T) noexcept(std::is_floating_point<T>::value) |
232 | # define BOOST_MATH_IS_FLOAT(T) (std::is_floating_point<T>::value) |
233 | #else |
234 | #include <boost/type_traits/is_floating_point.hpp> |
235 | # define BOOST_MATH_NOEXCEPT(T) noexcept(boost::is_floating_point<T>::value) |
236 | # define BOOST_MATH_IS_FLOAT(T) (boost::is_floating_point<T>::value) |
237 | #endif |
238 | #else |
239 | # define BOOST_MATH_NOEXCEPT(T) |
240 | # define BOOST_MATH_IS_FLOAT(T) false |
241 | #endif |
242 | |
243 | // |
244 | // The maximum order of polynomial that will be evaluated |
245 | // via an unrolled specialisation: |
246 | // |
247 | #ifndef BOOST_MATH_MAX_POLY_ORDER |
248 | # define BOOST_MATH_MAX_POLY_ORDER 20 |
249 | #endif |
250 | // |
251 | // Set the method used to evaluate polynomials and rationals: |
252 | // |
253 | #ifndef BOOST_MATH_POLY_METHOD |
254 | # define BOOST_MATH_POLY_METHOD 2 |
255 | #endif |
256 | #ifndef BOOST_MATH_RATIONAL_METHOD |
257 | # define BOOST_MATH_RATIONAL_METHOD 1 |
258 | #endif |
259 | // |
260 | // decide whether to store constants as integers or reals: |
261 | // |
262 | #ifndef BOOST_MATH_INT_TABLE_TYPE |
263 | # define BOOST_MATH_INT_TABLE_TYPE(RT, IT) IT |
264 | #endif |
265 | #ifndef BOOST_MATH_INT_VALUE_SUFFIX |
266 | # define BOOST_MATH_INT_VALUE_SUFFIX(RV, SUF) RV##SUF |
267 | #endif |
268 | // |
269 | // And then the actual configuration: |
270 | // |
271 | #if defined(_GLIBCXX_USE_FLOAT128) && defined(BOOST_GCC) && !defined(__STRICT_ANSI__) \ |
272 | && !defined(BOOST_MATH_DISABLE_FLOAT128) || defined(BOOST_MATH_USE_FLOAT128) |
273 | // |
274 | // Only enable this when the compiler really is GCC as clang and probably |
275 | // intel too don't support __float128 yet :-( |
276 | // |
277 | #ifndef BOOST_MATH_USE_FLOAT128 |
278 | # define BOOST_MATH_USE_FLOAT128 |
279 | #endif |
280 | |
281 | # if defined(BOOST_INTEL) && defined(BOOST_INTEL_CXX_VERSION) && (BOOST_INTEL_CXX_VERSION >= 1310) && defined(__GNUC__) |
282 | # if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) |
283 | # define BOOST_MATH_FLOAT128_TYPE __float128 |
284 | # endif |
285 | # elif defined(__GNUC__) |
286 | # define BOOST_MATH_FLOAT128_TYPE __float128 |
287 | # endif |
288 | |
289 | # ifndef BOOST_MATH_FLOAT128_TYPE |
290 | # define BOOST_MATH_FLOAT128_TYPE _Quad |
291 | # endif |
292 | #endif |
293 | // |
294 | // Check for WinCE with no iostream support: |
295 | // |
296 | #if defined(_WIN32_WCE) && !defined(__SGI_STL_PORT) |
297 | # define BOOST_MATH_NO_LEXICAL_CAST |
298 | #endif |
299 | |
300 | // |
301 | // Helper macro for controlling the FP behaviour: |
302 | // |
303 | #ifndef BOOST_MATH_CONTROL_FP |
304 | # define BOOST_MATH_CONTROL_FP |
305 | #endif |
306 | // |
307 | // Helper macro for using statements: |
308 | // |
309 | #define BOOST_MATH_STD_USING_CORE \ |
310 | using std::abs;\ |
311 | using std::acos;\ |
312 | using std::cos;\ |
313 | using std::fmod;\ |
314 | using std::modf;\ |
315 | using std::tan;\ |
316 | using std::asin;\ |
317 | using std::cosh;\ |
318 | using std::frexp;\ |
319 | using std::pow;\ |
320 | using std::tanh;\ |
321 | using std::atan;\ |
322 | using std::exp;\ |
323 | using std::ldexp;\ |
324 | using std::sin;\ |
325 | using std::atan2;\ |
326 | using std::fabs;\ |
327 | using std::log;\ |
328 | using std::sinh;\ |
329 | using std::ceil;\ |
330 | using std::floor;\ |
331 | using std::log10;\ |
332 | using std::sqrt; |
333 | |
334 | #define BOOST_MATH_STD_USING BOOST_MATH_STD_USING_CORE |
335 | |
336 | namespace boost{ namespace math{ |
337 | namespace tools |
338 | { |
339 | |
340 | template <class T> |
341 | inline T max BOOST_PREVENT_MACRO_SUBSTITUTION(T a, T b, T c) BOOST_MATH_NOEXCEPT(T) |
342 | { |
343 | return (std::max)((std::max)(a, b), c); |
344 | } |
345 | |
346 | template <class T> |
347 | inline T max BOOST_PREVENT_MACRO_SUBSTITUTION(T a, T b, T c, T d) BOOST_MATH_NOEXCEPT(T) |
348 | { |
349 | return (std::max)((std::max)(a, b), (std::max)(c, d)); |
350 | } |
351 | |
352 | } // namespace tools |
353 | |
354 | template <class T> |
355 | void suppress_unused_variable_warning(const T&) BOOST_MATH_NOEXCEPT(T) |
356 | { |
357 | } |
358 | |
359 | namespace detail{ |
360 | |
361 | template <class T> |
362 | struct is_integer_for_rounding |
363 | { |
364 | static const bool value = boost::is_integral<T>::value |
365 | #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS |
366 | || (std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::is_integer) |
367 | #endif |
368 | ; |
369 | }; |
370 | |
371 | } |
372 | |
373 | }} // namespace boost namespace math |
374 | |
375 | #ifdef __GLIBC_PREREQ |
376 | # if __GLIBC_PREREQ(2,14) |
377 | # define BOOST_MATH_HAVE_FIXED_GLIBC |
378 | # endif |
379 | #endif |
380 | |
381 | #if ((defined(__linux__) && !defined(__UCLIBC__) && !defined(BOOST_MATH_HAVE_FIXED_GLIBC)) || defined(__QNX__) || defined(__IBMCPP__)) && !defined(BOOST_NO_FENV_H) |
382 | // |
383 | // This code was introduced in response to this glibc bug: http://sourceware.org/bugzilla/show_bug.cgi?id=2445 |
384 | // Basically powl and expl can return garbage when the result is small and certain exception flags are set |
385 | // on entrance to these functions. This appears to have been fixed in Glibc 2.14 (May 2011). |
386 | // Much more information in this message thread: https://groups.google.com/forum/#!topic/boost-list/ZT99wtIFlb4 |
387 | // |
388 | |
389 | #include <boost/detail/fenv.hpp> |
390 | |
391 | # ifdef FE_ALL_EXCEPT |
392 | |
393 | namespace boost{ namespace math{ |
394 | namespace detail |
395 | { |
396 | struct fpu_guard |
397 | { |
398 | fpu_guard() |
399 | { |
400 | fegetexceptflag(&m_flags, FE_ALL_EXCEPT); |
401 | feclearexcept(FE_ALL_EXCEPT); |
402 | } |
403 | ~fpu_guard() |
404 | { |
405 | fesetexceptflag(&m_flags, FE_ALL_EXCEPT); |
406 | } |
407 | private: |
408 | fexcept_t m_flags; |
409 | }; |
410 | |
411 | } // namespace detail |
412 | }} // namespaces |
413 | |
414 | # define BOOST_FPU_EXCEPTION_GUARD boost::math::detail::fpu_guard local_guard_object; |
415 | # define BOOST_MATH_INSTRUMENT_FPU do{ fexcept_t cpu_flags; fegetexceptflag(&cpu_flags, FE_ALL_EXCEPT); BOOST_MATH_INSTRUMENT_VARIABLE(cpu_flags); } while(0); |
416 | |
417 | # else |
418 | |
419 | # define BOOST_FPU_EXCEPTION_GUARD |
420 | # define BOOST_MATH_INSTRUMENT_FPU |
421 | |
422 | # endif |
423 | |
424 | #else // All other platforms. |
425 | # define BOOST_FPU_EXCEPTION_GUARD |
426 | # define BOOST_MATH_INSTRUMENT_FPU |
427 | #endif |
428 | |
429 | #ifdef BOOST_MATH_INSTRUMENT |
430 | |
431 | # include <iostream> |
432 | # include <iomanip> |
433 | # include <typeinfo> |
434 | |
435 | # define BOOST_MATH_INSTRUMENT_CODE(x) \ |
436 | std::cout << std::setprecision(35) << __FILE__ << ":" << __LINE__ << " " << x << std::endl; |
437 | # define BOOST_MATH_INSTRUMENT_VARIABLE(name) BOOST_MATH_INSTRUMENT_CODE(BOOST_STRINGIZE(name) << " = " << name) |
438 | |
439 | #else |
440 | |
441 | # define BOOST_MATH_INSTRUMENT_CODE(x) |
442 | # define BOOST_MATH_INSTRUMENT_VARIABLE(name) |
443 | |
444 | #endif |
445 | |
446 | // |
447 | // Thread local storage: |
448 | // |
449 | #if !defined(BOOST_NO_CXX11_THREAD_LOCAL) && !defined(BOOST_INTEL) |
450 | # define BOOST_MATH_THREAD_LOCAL thread_local |
451 | #else |
452 | # define BOOST_MATH_THREAD_LOCAL |
453 | #endif |
454 | |
455 | #endif // BOOST_MATH_TOOLS_CONFIG_HPP |
456 | |
457 | |
458 | |
459 | |
460 | |