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/architecture/x86.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 understand, 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 | #if BOOST_MSVC <= 1900 |
189 | # define BOOST_MATH_RATIONAL_METHOD 1 |
190 | #else |
191 | # define BOOST_MATH_RATIONAL_METHOD 2 |
192 | #endif |
193 | #if BOOST_MSVC > 1900 |
194 | # define BOOST_MATH_INT_TABLE_TYPE(RT, IT) RT |
195 | # define BOOST_MATH_INT_VALUE_SUFFIX(RV, SUF) RV##.0L |
196 | #endif |
197 | |
198 | #elif defined(BOOST_INTEL) |
199 | # define BOOST_MATH_POLY_METHOD 2 |
200 | # define BOOST_MATH_RATIONAL_METHOD 1 |
201 | |
202 | #elif defined(__GNUC__) |
203 | #if __GNUC__ < 4 |
204 | # define BOOST_MATH_POLY_METHOD 3 |
205 | # define BOOST_MATH_RATIONAL_METHOD 3 |
206 | # define BOOST_MATH_INT_TABLE_TYPE(RT, IT) RT |
207 | # define BOOST_MATH_INT_VALUE_SUFFIX(RV, SUF) RV##.0L |
208 | #else |
209 | # define BOOST_MATH_POLY_METHOD 3 |
210 | # define BOOST_MATH_RATIONAL_METHOD 3 |
211 | #endif |
212 | |
213 | #elif defined(__clang__) |
214 | |
215 | #if __clang__ > 6 |
216 | # define BOOST_MATH_POLY_METHOD 3 |
217 | # define BOOST_MATH_RATIONAL_METHOD 3 |
218 | # define BOOST_MATH_INT_TABLE_TYPE(RT, IT) RT |
219 | # define BOOST_MATH_INT_VALUE_SUFFIX(RV, SUF) RV##.0L |
220 | #endif |
221 | |
222 | #endif |
223 | |
224 | #if defined(BOOST_NO_LONG_LONG) && !defined(BOOST_MATH_INT_TABLE_TYPE) |
225 | # define BOOST_MATH_INT_TABLE_TYPE(RT, IT) RT |
226 | # define BOOST_MATH_INT_VALUE_SUFFIX(RV, SUF) RV##.0L |
227 | #endif |
228 | |
229 | // |
230 | // constexpr support, early GCC implementations can't cope so disable |
231 | // constexpr for them: |
232 | // |
233 | #if !defined(__clang__) && defined(__GNUC__) |
234 | #if (__GNUC__ * 100 + __GNUC_MINOR__) < 490 |
235 | # define BOOST_MATH_DISABLE_CONSTEXPR |
236 | #endif |
237 | #endif |
238 | |
239 | #ifdef BOOST_MATH_DISABLE_CONSTEXPR |
240 | # define BOOST_MATH_CONSTEXPR |
241 | #else |
242 | # define BOOST_MATH_CONSTEXPR BOOST_CONSTEXPR |
243 | #endif |
244 | |
245 | // |
246 | // noexcept support: |
247 | // |
248 | #ifndef BOOST_NO_CXX11_NOEXCEPT |
249 | #ifndef BOOST_NO_CXX11_HDR_TYPE_TRAITS |
250 | #include <type_traits> |
251 | # define BOOST_MATH_NOEXCEPT(T) noexcept(std::is_floating_point<T>::value) |
252 | # define BOOST_MATH_IS_FLOAT(T) (std::is_floating_point<T>::value) |
253 | #else |
254 | #include <boost/type_traits/is_floating_point.hpp> |
255 | # define BOOST_MATH_NOEXCEPT(T) noexcept(boost::is_floating_point<T>::value) |
256 | # define BOOST_MATH_IS_FLOAT(T) (boost::is_floating_point<T>::value) |
257 | #endif |
258 | #else |
259 | # define BOOST_MATH_NOEXCEPT(T) |
260 | # define BOOST_MATH_IS_FLOAT(T) false |
261 | #endif |
262 | |
263 | // |
264 | // The maximum order of polynomial that will be evaluated |
265 | // via an unrolled specialisation: |
266 | // |
267 | #ifndef BOOST_MATH_MAX_POLY_ORDER |
268 | # define BOOST_MATH_MAX_POLY_ORDER 20 |
269 | #endif |
270 | // |
271 | // Set the method used to evaluate polynomials and rationals: |
272 | // |
273 | #ifndef BOOST_MATH_POLY_METHOD |
274 | # define BOOST_MATH_POLY_METHOD 2 |
275 | #endif |
276 | #ifndef BOOST_MATH_RATIONAL_METHOD |
277 | # define BOOST_MATH_RATIONAL_METHOD 1 |
278 | #endif |
279 | // |
280 | // decide whether to store constants as integers or reals: |
281 | // |
282 | #ifndef BOOST_MATH_INT_TABLE_TYPE |
283 | # define BOOST_MATH_INT_TABLE_TYPE(RT, IT) IT |
284 | #endif |
285 | #ifndef BOOST_MATH_INT_VALUE_SUFFIX |
286 | # define BOOST_MATH_INT_VALUE_SUFFIX(RV, SUF) RV##SUF |
287 | #endif |
288 | // |
289 | // And then the actual configuration: |
290 | // |
291 | #if defined(_GLIBCXX_USE_FLOAT128) && defined(BOOST_GCC) && !defined(__STRICT_ANSI__) \ |
292 | && !defined(BOOST_MATH_DISABLE_FLOAT128) || defined(BOOST_MATH_USE_FLOAT128) |
293 | // |
294 | // Only enable this when the compiler really is GCC as clang and probably |
295 | // intel too don't support __float128 yet :-( |
296 | // |
297 | #ifndef BOOST_MATH_USE_FLOAT128 |
298 | # define BOOST_MATH_USE_FLOAT128 |
299 | #endif |
300 | |
301 | # if defined(BOOST_INTEL) && defined(BOOST_INTEL_CXX_VERSION) && (BOOST_INTEL_CXX_VERSION >= 1310) && defined(__GNUC__) |
302 | # if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) |
303 | # define BOOST_MATH_FLOAT128_TYPE __float128 |
304 | # endif |
305 | # elif defined(__GNUC__) |
306 | # define BOOST_MATH_FLOAT128_TYPE __float128 |
307 | # endif |
308 | |
309 | # ifndef BOOST_MATH_FLOAT128_TYPE |
310 | # define BOOST_MATH_FLOAT128_TYPE _Quad |
311 | # endif |
312 | #endif |
313 | // |
314 | // Check for WinCE with no iostream support: |
315 | // |
316 | #if defined(_WIN32_WCE) && !defined(__SGI_STL_PORT) |
317 | # define BOOST_MATH_NO_LEXICAL_CAST |
318 | #endif |
319 | |
320 | // |
321 | // Helper macro for controlling the FP behaviour: |
322 | // |
323 | #ifndef BOOST_MATH_CONTROL_FP |
324 | # define BOOST_MATH_CONTROL_FP |
325 | #endif |
326 | // |
327 | // Helper macro for using statements: |
328 | // |
329 | #define BOOST_MATH_STD_USING_CORE \ |
330 | using std::abs;\ |
331 | using std::acos;\ |
332 | using std::cos;\ |
333 | using std::fmod;\ |
334 | using std::modf;\ |
335 | using std::tan;\ |
336 | using std::asin;\ |
337 | using std::cosh;\ |
338 | using std::frexp;\ |
339 | using std::pow;\ |
340 | using std::tanh;\ |
341 | using std::atan;\ |
342 | using std::exp;\ |
343 | using std::ldexp;\ |
344 | using std::sin;\ |
345 | using std::atan2;\ |
346 | using std::fabs;\ |
347 | using std::log;\ |
348 | using std::sinh;\ |
349 | using std::ceil;\ |
350 | using std::floor;\ |
351 | using std::log10;\ |
352 | using std::sqrt; |
353 | |
354 | #define BOOST_MATH_STD_USING BOOST_MATH_STD_USING_CORE |
355 | |
356 | namespace boost{ namespace math{ |
357 | namespace tools |
358 | { |
359 | |
360 | template <class T> |
361 | inline T max BOOST_PREVENT_MACRO_SUBSTITUTION(T a, T b, T c) BOOST_MATH_NOEXCEPT(T) |
362 | { |
363 | return (std::max)((std::max)(a, b), c); |
364 | } |
365 | |
366 | template <class T> |
367 | inline T max BOOST_PREVENT_MACRO_SUBSTITUTION(T a, T b, T c, T d) BOOST_MATH_NOEXCEPT(T) |
368 | { |
369 | return (std::max)((std::max)(a, b), (std::max)(c, d)); |
370 | } |
371 | |
372 | } // namespace tools |
373 | |
374 | template <class T> |
375 | void suppress_unused_variable_warning(const T&) BOOST_MATH_NOEXCEPT(T) |
376 | { |
377 | } |
378 | |
379 | namespace detail{ |
380 | |
381 | template <class T> |
382 | struct is_integer_for_rounding |
383 | { |
384 | static const bool value = boost::is_integral<T>::value |
385 | #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS |
386 | || (std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::is_integer) |
387 | #endif |
388 | ; |
389 | }; |
390 | |
391 | } |
392 | |
393 | }} // namespace boost namespace math |
394 | |
395 | #ifdef __GLIBC_PREREQ |
396 | # if __GLIBC_PREREQ(2,14) |
397 | # define BOOST_MATH_HAVE_FIXED_GLIBC |
398 | # endif |
399 | #endif |
400 | |
401 | #if ((defined(__linux__) && !defined(__UCLIBC__) && !defined(BOOST_MATH_HAVE_FIXED_GLIBC)) || defined(__QNX__) || defined(__IBMCPP__)) && !defined(BOOST_NO_FENV_H) |
402 | // |
403 | // This code was introduced in response to this glibc bug: http://sourceware.org/bugzilla/show_bug.cgi?id=2445 |
404 | // Basically powl and expl can return garbage when the result is small and certain exception flags are set |
405 | // on entrance to these functions. This appears to have been fixed in Glibc 2.14 (May 2011). |
406 | // Much more information in this message thread: https://groups.google.com/forum/#!topic/boost-list/ZT99wtIFlb4 |
407 | // |
408 | |
409 | #include <boost/detail/fenv.hpp> |
410 | |
411 | # ifdef FE_ALL_EXCEPT |
412 | |
413 | namespace boost{ namespace math{ |
414 | namespace detail |
415 | { |
416 | struct fpu_guard |
417 | { |
418 | fpu_guard() |
419 | { |
420 | fegetexceptflag(&m_flags, FE_ALL_EXCEPT); |
421 | feclearexcept(FE_ALL_EXCEPT); |
422 | } |
423 | ~fpu_guard() |
424 | { |
425 | fesetexceptflag(&m_flags, FE_ALL_EXCEPT); |
426 | } |
427 | private: |
428 | fexcept_t m_flags; |
429 | }; |
430 | |
431 | } // namespace detail |
432 | }} // namespaces |
433 | |
434 | # define BOOST_FPU_EXCEPTION_GUARD boost::math::detail::fpu_guard local_guard_object; |
435 | # define BOOST_MATH_INSTRUMENT_FPU do{ fexcept_t cpu_flags; fegetexceptflag(&cpu_flags, FE_ALL_EXCEPT); BOOST_MATH_INSTRUMENT_VARIABLE(cpu_flags); } while(0); |
436 | |
437 | # else |
438 | |
439 | # define BOOST_FPU_EXCEPTION_GUARD |
440 | # define BOOST_MATH_INSTRUMENT_FPU |
441 | |
442 | # endif |
443 | |
444 | #else // All other platforms. |
445 | # define BOOST_FPU_EXCEPTION_GUARD |
446 | # define BOOST_MATH_INSTRUMENT_FPU |
447 | #endif |
448 | |
449 | #ifdef BOOST_MATH_INSTRUMENT |
450 | |
451 | # include <iostream> |
452 | # include <iomanip> |
453 | # include <typeinfo> |
454 | |
455 | # define BOOST_MATH_INSTRUMENT_CODE(x) \ |
456 | std::cout << std::setprecision(35) << __FILE__ << ":" << __LINE__ << " " << x << std::endl; |
457 | # define BOOST_MATH_INSTRUMENT_VARIABLE(name) BOOST_MATH_INSTRUMENT_CODE(BOOST_STRINGIZE(name) << " = " << name) |
458 | |
459 | #else |
460 | |
461 | # define BOOST_MATH_INSTRUMENT_CODE(x) |
462 | # define BOOST_MATH_INSTRUMENT_VARIABLE(name) |
463 | |
464 | #endif |
465 | |
466 | // |
467 | // Thread local storage: |
468 | // |
469 | #if !defined(BOOST_NO_CXX11_THREAD_LOCAL) && !defined(BOOST_INTEL) |
470 | # define BOOST_MATH_THREAD_LOCAL thread_local |
471 | #else |
472 | # define BOOST_MATH_THREAD_LOCAL |
473 | #endif |
474 | |
475 | // |
476 | // Can we have constexpr tables? |
477 | // |
478 | #if (!defined(BOOST_NO_CXX11_HDR_ARRAY) && !defined(BOOST_NO_CXX14_CONSTEXPR)) || BOOST_WORKAROUND(BOOST_MSVC, >= 1910) |
479 | #define BOOST_MATH_HAVE_CONSTEXPR_TABLES |
480 | #define BOOST_MATH_CONSTEXPR_TABLE_FUNCTION constexpr |
481 | #else |
482 | #define BOOST_MATH_CONSTEXPR_TABLE_FUNCTION |
483 | #endif |
484 | |
485 | |
486 | #endif // BOOST_MATH_TOOLS_CONFIG_HPP |
487 | |
488 | |
489 | |
490 | |
491 | |