1// Copyright (c) 2006-7 John Maddock
2// Copyright (c) 2021 Matt Borland
3// Use, modification and distribution are subject to the
4// Boost Software License, Version 1.0. (See accompanying file
5// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6
7#ifndef BOOST_MATH_TOOLS_CONFIG_HPP
8#define BOOST_MATH_TOOLS_CONFIG_HPP
9
10#ifdef _MSC_VER
11#pragma once
12#endif
13
14#include <boost/math/tools/is_standalone.hpp>
15
16// Minimum language standard transition
17#ifdef _MSVC_LANG
18# if _MSVC_LANG < 201402L
19# pragma warning("The minimum language standard to use Boost.Math will be C++14 starting in July 2023 (Boost 1.82 release)");
20# endif
21#else
22# if __cplusplus < 201402L
23# warning "The minimum language standard to use Boost.Math will be C++14 starting in July 2023 (Boost 1.82 release)"
24# endif
25#endif
26
27#ifndef BOOST_MATH_STANDALONE
28#include <boost/config.hpp>
29
30#else // Things from boost/config that are required, and easy to replicate
31
32#define BOOST_PREVENT_MACRO_SUBSTITUTION
33#define BOOST_MATH_NO_REAL_CONCEPT_TESTS
34#define BOOST_MATH_NO_DISTRIBUTION_CONCEPT_TESTS
35#define BOOST_MATH_NO_LEXICAL_CAST
36
37// Since Boost.Multiprecision is in active development some tests do not fully cooperate yet.
38#define BOOST_MATH_NO_MP_TESTS
39
40#if (__cplusplus > 201400L || _MSVC_LANG > 201400L)
41#define BOOST_CXX14_CONSTEXPR constexpr
42#else
43#define BOOST_CXX14_CONSTEXPR
44#define BOOST_NO_CXX14_CONSTEXPR
45#endif // BOOST_CXX14_CONSTEXPR
46
47#if (__cplusplus > 201700L || _MSVC_LANG > 201700L)
48#define BOOST_IF_CONSTEXPR if constexpr
49
50// Clang on mac provides the execution header with none of the functionality. TODO: Check back on this
51// https://en.cppreference.com/w/cpp/compiler_support "Standardization of Parallelism TS"
52#if !__has_include(<execution>) || (defined(__APPLE__) && defined(__clang__))
53#define BOOST_NO_CXX17_HDR_EXECUTION
54#endif
55#else
56#define BOOST_IF_CONSTEXPR if
57#define BOOST_NO_CXX17_IF_CONSTEXPR
58#define BOOST_NO_CXX17_HDR_EXECUTION
59#endif
60
61#if __cpp_lib_gcd_lcm >= 201606L
62#define BOOST_MATH_HAS_CXX17_NUMERIC
63#endif
64
65#define BOOST_JOIN(X, Y) BOOST_DO_JOIN(X, Y)
66#define BOOST_DO_JOIN(X, Y) BOOST_DO_JOIN2(X,Y)
67#define BOOST_DO_JOIN2(X, Y) X##Y
68
69#define BOOST_STRINGIZE(X) BOOST_DO_STRINGIZE(X)
70#define BOOST_DO_STRINGIZE(X) #X
71
72#ifdef BOOST_DISABLE_THREADS // No threads, do nothing
73// Detect thread support via STL implementation
74#elif defined(__has_include)
75# if !__has_include(<thread>) || !__has_include(<mutex>) || !__has_include(<future>) || !__has_include(<atomic>)
76# define BOOST_DISABLE_THREADS
77# else
78# define BOOST_HAS_THREADS
79# endif
80#else
81# define BOOST_HAS_THREADS // The default assumption is that the machine has threads
82#endif // Thread Support
83
84#ifdef BOOST_DISABLE_THREADS
85# define BOOST_NO_CXX11_HDR_ATOMIC
86# define BOOST_NO_CXX11_HDR_FUTURE
87# define BOOST_NO_CXX11_HDR_THREAD
88# define BOOST_NO_CXX11_THREAD_LOCAL
89#endif // BOOST_DISABLE_THREADS
90
91#ifdef __GNUC__
92# if !defined(__EXCEPTIONS) && !defined(BOOST_NO_EXCEPTIONS)
93# define BOOST_NO_EXCEPTIONS
94# endif
95 //
96 // Make sure we have some std lib headers included so we can detect __GXX_RTTI:
97 //
98# include <algorithm> // for min and max
99# include <limits>
100# ifndef __GXX_RTTI
101# ifndef BOOST_NO_TYPEID
102# define BOOST_NO_TYPEID
103# endif
104# ifndef BOOST_NO_RTTI
105# define BOOST_NO_RTTI
106# endif
107# endif
108#endif
109
110#if !defined(BOOST_NOINLINE)
111# if defined(_MSC_VER)
112# define BOOST_NOINLINE __declspec(noinline)
113# elif defined(__GNUC__) && __GNUC__ > 3
114 // Clang also defines __GNUC__ (as 4)
115# if defined(__CUDACC__)
116 // nvcc doesn't always parse __noinline__,
117 // see: https://svn.boost.org/trac/boost/ticket/9392
118# define BOOST_NOINLINE __attribute__ ((noinline))
119# elif defined(__HIP__)
120 // See https://github.com/boostorg/config/issues/392
121# define BOOST_NOINLINE __attribute__ ((noinline))
122# else
123# define BOOST_NOINLINE __attribute__ ((__noinline__))
124# endif
125# else
126# define BOOST_NOINLINE
127# endif
128#endif
129
130#if !defined(BOOST_FORCEINLINE)
131# if defined(_MSC_VER)
132# define BOOST_FORCEINLINE __forceinline
133# elif defined(__GNUC__) && __GNUC__ > 3
134 // Clang also defines __GNUC__ (as 4)
135# define BOOST_FORCEINLINE inline __attribute__ ((__always_inline__))
136# else
137# define BOOST_FORCEINLINE inline
138# endif
139#endif
140
141#endif // BOOST_MATH_STANDALONE
142
143// Support compilers with P0024R2 implemented without linking TBB
144// https://en.cppreference.com/w/cpp/compiler_support
145#if !defined(BOOST_NO_CXX17_HDR_EXECUTION) && defined(BOOST_HAS_THREADS)
146# define BOOST_MATH_EXEC_COMPATIBLE
147#endif
148
149// Attributes from C++14 and newer
150#ifdef __has_cpp_attribute
151
152// C++17
153#if (__cplusplus >= 201703L || _MSVC_LANG >= 201703L)
154# if __has_cpp_attribute(maybe_unused)
155# define BOOST_MATH_MAYBE_UNUSED [[maybe_unused]]
156# endif
157#endif
158
159#endif // Standalone config
160
161// If attributes are not defined make sure we don't have compiler errors
162#ifndef BOOST_MATH_MAYBE_UNUSED
163# define BOOST_MATH_MAYBE_UNUSED
164#endif
165
166// C++23
167#if __cplusplus > 202002L || _MSVC_LANG > 202002L
168# if __GNUC__ >= 13
169 // libstdc++3 only defines to/from_chars for std::float128_t when one of these defines are set
170 // otherwise we're right out of luck...
171# if defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) || defined(_GLIBCXX_HAVE_FLOAT128_MATH)
172# include <cstring> // std::strlen is used with from_chars
173# include <charconv>
174# include <stdfloat>
175# define BOOST_MATH_USE_CHARCONV_FOR_CONVERSION
176#endif
177# endif
178#endif
179
180#include <algorithm> // for min and max
181#include <limits>
182#include <cmath>
183#include <climits>
184#include <cfloat>
185
186#include <boost/math/tools/user.hpp>
187
188#if (defined(__NetBSD__) || defined(__EMSCRIPTEN__)\
189 || (defined(__hppa) && !defined(__OpenBSD__)) || (defined(__NO_LONG_DOUBLE_MATH) && (DBL_MANT_DIG != LDBL_MANT_DIG))) \
190 && !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)
191//# define BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
192#endif
193
194#ifdef __IBMCPP__
195//
196// For reasons I don't understand, the tests with IMB's compiler all
197// pass at long double precision, but fail with real_concept, those tests
198// are disabled for now. (JM 2012).
199#ifndef BOOST_MATH_NO_REAL_CONCEPT_TESTS
200# define BOOST_MATH_NO_REAL_CONCEPT_TESTS
201#endif // BOOST_MATH_NO_REAL_CONCEPT_TESTS
202#endif
203#ifdef sun
204// Any use of __float128 in program startup code causes a segfault (tested JM 2015, Solaris 11).
205# define BOOST_MATH_DISABLE_FLOAT128
206#endif
207#ifdef __HAIKU__
208//
209// Not sure what's up with the math detection on Haiku, but linking fails with
210// float128 code enabled, and we don't have an implementation of __expl, so
211// disabling long double functions for now as well.
212# define BOOST_MATH_DISABLE_FLOAT128
213# define BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
214#endif
215#if (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) && ((LDBL_MANT_DIG == 106) || (__LDBL_MANT_DIG__ == 106)) && !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)
216//
217// Darwin's rather strange "double double" is rather hard to
218// support, it should be possible given enough effort though...
219//
220# define BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
221#endif
222#if !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) && (LDBL_MANT_DIG == 106) && (LDBL_MIN_EXP > DBL_MIN_EXP)
223//
224// Generic catch all case for gcc's "double-double" long double type.
225// We do not support this as it's not even remotely IEEE conforming:
226//
227# define BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
228#endif
229#if defined(unix) && defined(__INTEL_COMPILER) && (__INTEL_COMPILER <= 1000) && !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)
230//
231// Intel compiler prior to version 10 has sporadic problems
232// calling the long double overloads of the std lib math functions:
233// calling ::powl is OK, but std::pow(long double, long double)
234// may segfault depending upon the value of the arguments passed
235// and the specific Linux distribution.
236//
237// We'll be conservative and disable long double support for this compiler.
238//
239// Comment out this #define and try building the tests to determine whether
240// your Intel compiler version has this issue or not.
241//
242# define BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
243#endif
244#if defined(unix) && defined(__INTEL_COMPILER)
245//
246// Intel compiler has sporadic issues compiling std::fpclassify depending on
247// the exact OS version used. Use our own code for this as we know it works
248// well on Intel processors:
249//
250#define BOOST_MATH_DISABLE_STD_FPCLASSIFY
251#endif
252
253#if defined(_MSC_VER) && !defined(_WIN32_WCE)
254 // Better safe than sorry, our tests don't support hardware exceptions:
255# define BOOST_MATH_CONTROL_FP _control87(MCW_EM,MCW_EM)
256#endif
257
258#ifdef __IBMCPP__
259# define BOOST_MATH_NO_DEDUCED_FUNCTION_POINTERS
260#endif
261
262#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901))
263# define BOOST_MATH_USE_C99
264#endif
265
266#if (defined(__hpux) && !defined(__hppa))
267# define BOOST_MATH_USE_C99
268#endif
269
270#if defined(__GNUC__) && defined(_GLIBCXX_USE_C99)
271# define BOOST_MATH_USE_C99
272#endif
273
274#if defined(_LIBCPP_VERSION) && !defined(_MSC_VER)
275# define BOOST_MATH_USE_C99
276#endif
277
278#if defined(__CYGWIN__) || defined(__HP_aCC) || defined(__INTEL_COMPILER) \
279 || defined(BOOST_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY) \
280 || (defined(__GNUC__) && !defined(BOOST_MATH_USE_C99))\
281 || defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)
282# define BOOST_MATH_NO_NATIVE_LONG_DOUBLE_FP_CLASSIFY
283#endif
284
285#if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x590)
286
287namespace boost { namespace math { namespace tools { namespace detail {
288template <typename T>
289struct type {};
290
291template <typename T, T n>
292struct non_type {};
293}}}} // Namespace boost, math tools, detail
294
295# define BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(t) boost::math::tools::detail::type<t>* = 0
296# define BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(t) boost::math::tools::detail::type<t>*
297# define BOOST_MATH_EXPLICIT_TEMPLATE_NON_TYPE(t, v) boost::math::tools::detail::non_type<t, v>* = 0
298# define BOOST_MATH_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v) boost::math::tools::detail::non_type<t, v>*
299
300# define BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(t) \
301 , BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(t)
302# define BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(t) \
303 , BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(t)
304# define BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(t, v) \
305 , BOOST_MATH_EXPLICIT_TEMPLATE_NON_TYPE(t, v)
306# define BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v) \
307 , BOOST_MATH_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v)
308
309#else
310
311// no workaround needed: expand to nothing
312
313# define BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(t)
314# define BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(t)
315# define BOOST_MATH_EXPLICIT_TEMPLATE_NON_TYPE(t, v)
316# define BOOST_MATH_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v)
317
318# define BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(t)
319# define BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(t)
320# define BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(t, v)
321# define BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v)
322
323
324#endif // __SUNPRO_CC
325
326#if (defined(__SUNPRO_CC) || defined(__hppa) || defined(__GNUC__)) && !defined(BOOST_MATH_SMALL_CONSTANT)
327// Sun's compiler emits a hard error if a constant underflows,
328// as does aCC on PA-RISC, while gcc issues a large number of warnings:
329# define BOOST_MATH_SMALL_CONSTANT(x) 0.0
330#else
331# define BOOST_MATH_SMALL_CONSTANT(x) x
332#endif
333
334//
335// Tune performance options for specific compilers:
336//
337#ifdef _MSC_VER
338# define BOOST_MATH_POLY_METHOD 2
339#if _MSC_VER <= 1900
340# define BOOST_MATH_RATIONAL_METHOD 1
341#else
342# define BOOST_MATH_RATIONAL_METHOD 2
343#endif
344#if _MSC_VER > 1900
345# define BOOST_MATH_INT_TABLE_TYPE(RT, IT) RT
346# define BOOST_MATH_INT_VALUE_SUFFIX(RV, SUF) RV##.0L
347#endif
348
349#elif defined(__INTEL_COMPILER)
350# define BOOST_MATH_POLY_METHOD 2
351# define BOOST_MATH_RATIONAL_METHOD 1
352
353#elif defined(__GNUC__)
354#if __GNUC__ < 4
355# define BOOST_MATH_POLY_METHOD 3
356# define BOOST_MATH_RATIONAL_METHOD 3
357# define BOOST_MATH_INT_TABLE_TYPE(RT, IT) RT
358# define BOOST_MATH_INT_VALUE_SUFFIX(RV, SUF) RV##.0L
359#else
360# define BOOST_MATH_POLY_METHOD 3
361# define BOOST_MATH_RATIONAL_METHOD 3
362#endif
363
364#elif defined(__clang__)
365
366#if __clang__ > 6
367# define BOOST_MATH_POLY_METHOD 3
368# define BOOST_MATH_RATIONAL_METHOD 3
369# define BOOST_MATH_INT_TABLE_TYPE(RT, IT) RT
370# define BOOST_MATH_INT_VALUE_SUFFIX(RV, SUF) RV##.0L
371#endif
372
373#endif
374
375//
376// noexcept support:
377//
378#include <type_traits>
379#define BOOST_MATH_NOEXCEPT(T) noexcept(std::is_floating_point<T>::value)
380#define BOOST_MATH_IS_FLOAT(T) (std::is_floating_point<T>::value)
381
382//
383// The maximum order of polynomial that will be evaluated
384// via an unrolled specialisation:
385//
386#ifndef BOOST_MATH_MAX_POLY_ORDER
387# define BOOST_MATH_MAX_POLY_ORDER 20
388#endif
389//
390// Set the method used to evaluate polynomials and rationals:
391//
392#ifndef BOOST_MATH_POLY_METHOD
393# define BOOST_MATH_POLY_METHOD 2
394#endif
395#ifndef BOOST_MATH_RATIONAL_METHOD
396# define BOOST_MATH_RATIONAL_METHOD 1
397#endif
398//
399// decide whether to store constants as integers or reals:
400//
401#ifndef BOOST_MATH_INT_TABLE_TYPE
402# define BOOST_MATH_INT_TABLE_TYPE(RT, IT) IT
403#endif
404#ifndef BOOST_MATH_INT_VALUE_SUFFIX
405# define BOOST_MATH_INT_VALUE_SUFFIX(RV, SUF) RV##SUF
406#endif
407//
408// And then the actual configuration:
409//
410#if defined(BOOST_MATH_STANDALONE) && defined(_GLIBCXX_USE_FLOAT128) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) && !defined(__STRICT_ANSI__) \
411 && !defined(BOOST_MATH_DISABLE_FLOAT128) && !defined(BOOST_MATH_USE_FLOAT128)
412# define BOOST_MATH_USE_FLOAT128
413#elif defined(BOOST_HAS_FLOAT128) && !defined(BOOST_MATH_USE_FLOAT128)
414# define BOOST_MATH_USE_FLOAT128
415#endif
416#ifdef BOOST_MATH_USE_FLOAT128
417//
418// Only enable this when the compiler really is GCC as clang and probably
419// intel too don't support __float128 yet :-(
420//
421# if defined(__INTEL_COMPILER) && defined(__GNUC__)
422# if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6))
423# define BOOST_MATH_FLOAT128_TYPE __float128
424# endif
425# elif defined(__GNUC__)
426# define BOOST_MATH_FLOAT128_TYPE __float128
427# endif
428
429# ifndef BOOST_MATH_FLOAT128_TYPE
430# define BOOST_MATH_FLOAT128_TYPE _Quad
431# endif
432#endif
433//
434// Check for WinCE with no iostream support:
435//
436#if defined(_WIN32_WCE) && !defined(__SGI_STL_PORT)
437# define BOOST_MATH_NO_LEXICAL_CAST
438#endif
439
440//
441// Helper macro for controlling the FP behaviour:
442//
443#ifndef BOOST_MATH_CONTROL_FP
444# define BOOST_MATH_CONTROL_FP
445#endif
446//
447// Helper macro for using statements:
448//
449#define BOOST_MATH_STD_USING_CORE \
450 using std::abs;\
451 using std::acos;\
452 using std::cos;\
453 using std::fmod;\
454 using std::modf;\
455 using std::tan;\
456 using std::asin;\
457 using std::cosh;\
458 using std::frexp;\
459 using std::pow;\
460 using std::tanh;\
461 using std::atan;\
462 using std::exp;\
463 using std::ldexp;\
464 using std::sin;\
465 using std::atan2;\
466 using std::fabs;\
467 using std::log;\
468 using std::sinh;\
469 using std::ceil;\
470 using std::floor;\
471 using std::log10;\
472 using std::sqrt;
473
474#define BOOST_MATH_STD_USING BOOST_MATH_STD_USING_CORE
475
476namespace boost{ namespace math{
477namespace tools
478{
479
480template <class T>
481inline T max BOOST_PREVENT_MACRO_SUBSTITUTION(T a, T b, T c) BOOST_MATH_NOEXCEPT(T)
482{
483 return (std::max)((std::max)(a, b), c);
484}
485
486template <class T>
487inline T max BOOST_PREVENT_MACRO_SUBSTITUTION(T a, T b, T c, T d) BOOST_MATH_NOEXCEPT(T)
488{
489 return (std::max)((std::max)(a, b), (std::max)(c, d));
490}
491
492} // namespace tools
493
494template <class T>
495void suppress_unused_variable_warning(const T&) BOOST_MATH_NOEXCEPT(T)
496{
497}
498
499namespace detail{
500
501template <class T>
502struct is_integer_for_rounding
503{
504 static constexpr bool value = std::is_integral<T>::value || (std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::is_integer);
505};
506
507}
508
509}} // namespace boost namespace math
510
511#ifdef __GLIBC_PREREQ
512# if __GLIBC_PREREQ(2,14)
513# define BOOST_MATH_HAVE_FIXED_GLIBC
514# endif
515#endif
516
517#if ((defined(__linux__) && !defined(__UCLIBC__) && !defined(BOOST_MATH_HAVE_FIXED_GLIBC)) || defined(__QNX__) || defined(__IBMCPP__))
518//
519// This code was introduced in response to this glibc bug: http://sourceware.org/bugzilla/show_bug.cgi?id=2445
520// Basically powl and expl can return garbage when the result is small and certain exception flags are set
521// on entrance to these functions. This appears to have been fixed in Glibc 2.14 (May 2011).
522// Much more information in this message thread: https://groups.google.com/forum/#!topic/boost-list/ZT99wtIFlb4
523//
524
525#include <cfenv>
526
527# ifdef FE_ALL_EXCEPT
528
529namespace boost{ namespace math{
530 namespace detail
531 {
532 struct fpu_guard
533 {
534 fpu_guard()
535 {
536 fegetexceptflag(&m_flags, FE_ALL_EXCEPT);
537 feclearexcept(FE_ALL_EXCEPT);
538 }
539 ~fpu_guard()
540 {
541 fesetexceptflag(&m_flags, FE_ALL_EXCEPT);
542 }
543 private:
544 fexcept_t m_flags;
545 };
546
547 } // namespace detail
548 }} // namespaces
549
550# define BOOST_FPU_EXCEPTION_GUARD boost::math::detail::fpu_guard local_guard_object;
551# define BOOST_MATH_INSTRUMENT_FPU do{ fexcept_t cpu_flags; fegetexceptflag(&cpu_flags, FE_ALL_EXCEPT); BOOST_MATH_INSTRUMENT_VARIABLE(cpu_flags); } while(0);
552
553# else
554
555# define BOOST_FPU_EXCEPTION_GUARD
556# define BOOST_MATH_INSTRUMENT_FPU
557
558# endif
559
560#else // All other platforms.
561# define BOOST_FPU_EXCEPTION_GUARD
562# define BOOST_MATH_INSTRUMENT_FPU
563#endif
564
565#ifdef BOOST_MATH_INSTRUMENT
566
567# include <iostream>
568# include <iomanip>
569# include <typeinfo>
570
571# define BOOST_MATH_INSTRUMENT_CODE(x) \
572 std::cout << std::setprecision(35) << __FILE__ << ":" << __LINE__ << " " << x << std::endl;
573# define BOOST_MATH_INSTRUMENT_VARIABLE(name) BOOST_MATH_INSTRUMENT_CODE(#name << " = " << name)
574
575#else
576
577# define BOOST_MATH_INSTRUMENT_CODE(x)
578# define BOOST_MATH_INSTRUMENT_VARIABLE(name)
579
580#endif
581
582//
583// Thread local storage:
584//
585#ifndef BOOST_DISABLE_THREADS
586# define BOOST_MATH_THREAD_LOCAL thread_local
587#else
588# define BOOST_MATH_THREAD_LOCAL
589#endif
590
591//
592// Some mingw flavours have issues with thread_local and types with non-trivial destructors
593// See https://sourceforge.net/p/mingw-w64/bugs/527/
594//
595#if (defined(__MINGW32__) && (__GNUC__ < 9) && !defined(__clang__))
596# define BOOST_MATH_NO_THREAD_LOCAL_WITH_NON_TRIVIAL_TYPES
597#endif
598
599
600//
601// Can we have constexpr tables?
602//
603#if (!defined(BOOST_NO_CXX14_CONSTEXPR)) || (defined(_MSC_VER) && _MSC_VER >= 1910)
604#define BOOST_MATH_HAVE_CONSTEXPR_TABLES
605#define BOOST_MATH_CONSTEXPR_TABLE_FUNCTION constexpr
606#else
607#define BOOST_MATH_CONSTEXPR_TABLE_FUNCTION
608#endif
609
610
611#endif // BOOST_MATH_TOOLS_CONFIG_HPP
612
613
614
615
616

source code of include/boost/math/tools/config.hpp