1// Copyright John Maddock 2007.
2// Copyright Matt Borland 2021.
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_POLICY_HPP
8#define BOOST_MATH_POLICY_HPP
9
10#include <boost/math/tools/config.hpp>
11#include <boost/math/tools/mp.hpp>
12#include <limits>
13#include <type_traits>
14#include <cmath>
15#include <cstdint>
16#include <cstddef>
17
18namespace boost{ namespace math{
19
20namespace mp = tools::meta_programming;
21
22namespace tools{
23
24template <class T>
25constexpr int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept;
26template <class T>
27constexpr T epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(std::is_floating_point<T>::value);
28
29}
30
31namespace policies{
32
33//
34// Define macros for our default policies, if they're not defined already:
35//
36// Special cases for exceptions disabled first:
37//
38#ifdef BOOST_MATH_NO_EXCEPTIONS
39# ifndef BOOST_MATH_DOMAIN_ERROR_POLICY
40# define BOOST_MATH_DOMAIN_ERROR_POLICY errno_on_error
41# endif
42# ifndef BOOST_MATH_POLE_ERROR_POLICY
43# define BOOST_MATH_POLE_ERROR_POLICY errno_on_error
44# endif
45# ifndef BOOST_MATH_OVERFLOW_ERROR_POLICY
46# define BOOST_MATH_OVERFLOW_ERROR_POLICY errno_on_error
47# endif
48# ifndef BOOST_MATH_EVALUATION_ERROR_POLICY
49# define BOOST_MATH_EVALUATION_ERROR_POLICY errno_on_error
50# endif
51# ifndef BOOST_MATH_ROUNDING_ERROR_POLICY
52# define BOOST_MATH_ROUNDING_ERROR_POLICY errno_on_error
53# endif
54#endif
55//
56// Then the regular cases:
57//
58#ifndef BOOST_MATH_DOMAIN_ERROR_POLICY
59#define BOOST_MATH_DOMAIN_ERROR_POLICY throw_on_error
60#endif
61#ifndef BOOST_MATH_POLE_ERROR_POLICY
62#define BOOST_MATH_POLE_ERROR_POLICY throw_on_error
63#endif
64#ifndef BOOST_MATH_OVERFLOW_ERROR_POLICY
65#define BOOST_MATH_OVERFLOW_ERROR_POLICY throw_on_error
66#endif
67#ifndef BOOST_MATH_EVALUATION_ERROR_POLICY
68#define BOOST_MATH_EVALUATION_ERROR_POLICY throw_on_error
69#endif
70#ifndef BOOST_MATH_ROUNDING_ERROR_POLICY
71#define BOOST_MATH_ROUNDING_ERROR_POLICY throw_on_error
72#endif
73#ifndef BOOST_MATH_UNDERFLOW_ERROR_POLICY
74#define BOOST_MATH_UNDERFLOW_ERROR_POLICY ignore_error
75#endif
76#ifndef BOOST_MATH_DENORM_ERROR_POLICY
77#define BOOST_MATH_DENORM_ERROR_POLICY ignore_error
78#endif
79#ifndef BOOST_MATH_INDETERMINATE_RESULT_ERROR_POLICY
80#define BOOST_MATH_INDETERMINATE_RESULT_ERROR_POLICY ignore_error
81#endif
82#ifndef BOOST_MATH_DIGITS10_POLICY
83#define BOOST_MATH_DIGITS10_POLICY 0
84#endif
85#ifndef BOOST_MATH_PROMOTE_FLOAT_POLICY
86#define BOOST_MATH_PROMOTE_FLOAT_POLICY true
87#endif
88#ifndef BOOST_MATH_PROMOTE_DOUBLE_POLICY
89#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
90#define BOOST_MATH_PROMOTE_DOUBLE_POLICY false
91#else
92#define BOOST_MATH_PROMOTE_DOUBLE_POLICY true
93#endif
94#endif
95#ifndef BOOST_MATH_DISCRETE_QUANTILE_POLICY
96#define BOOST_MATH_DISCRETE_QUANTILE_POLICY integer_round_outwards
97#endif
98#ifndef BOOST_MATH_ASSERT_UNDEFINED_POLICY
99#define BOOST_MATH_ASSERT_UNDEFINED_POLICY true
100#endif
101#ifndef BOOST_MATH_MAX_SERIES_ITERATION_POLICY
102#define BOOST_MATH_MAX_SERIES_ITERATION_POLICY 1000000
103#endif
104#ifndef BOOST_MATH_MAX_ROOT_ITERATION_POLICY
105#define BOOST_MATH_MAX_ROOT_ITERATION_POLICY 200
106#endif
107
108#define BOOST_MATH_META_INT(Type, name, Default) \
109 template <Type N = Default> \
110 class name : public std::integral_constant<int, N>{}; \
111 \
112 namespace detail{ \
113 template <Type N> \
114 char test_is_valid_arg(const name<N>* = nullptr); \
115 char test_is_default_arg(const name<Default>* = nullptr); \
116 \
117 template <typename T> \
118 class is_##name##_imp \
119 { \
120 private: \
121 template <Type N> \
122 static char test(const name<N>* = nullptr); \
123 static double test(...); \
124 public: \
125 static constexpr bool value = sizeof(test(static_cast<T*>(nullptr))) == sizeof(char); \
126 }; \
127 } \
128 \
129 template <typename T> \
130 class is_##name \
131 { \
132 public: \
133 static constexpr bool value = boost::math::policies::detail::is_##name##_imp<T>::value; \
134 using type = std::integral_constant<bool, value>; \
135 };
136
137#define BOOST_MATH_META_BOOL(name, Default) \
138 template <bool N = Default> \
139 class name : public std::integral_constant<bool, N>{}; \
140 \
141 namespace detail{ \
142 template <bool N> \
143 char test_is_valid_arg(const name<N>* = nullptr); \
144 char test_is_default_arg(const name<Default>* = nullptr); \
145 \
146 template <typename T> \
147 class is_##name##_imp \
148 { \
149 private: \
150 template <bool N> \
151 static char test(const name<N>* = nullptr); \
152 static double test(...); \
153 public: \
154 static constexpr bool value = sizeof(test(static_cast<T*>(nullptr))) == sizeof(char); \
155 }; \
156 } \
157 \
158 template <typename T> \
159 class is_##name \
160 { \
161 public: \
162 static constexpr bool value = boost::math::policies::detail::is_##name##_imp<T>::value; \
163 using type = std::integral_constant<bool, value>; \
164 };
165
166//
167// Begin by defining policy types for error handling:
168//
169enum error_policy_type
170{
171 throw_on_error = 0,
172 errno_on_error = 1,
173 ignore_error = 2,
174 user_error = 3
175};
176
177BOOST_MATH_META_INT(error_policy_type, domain_error, BOOST_MATH_DOMAIN_ERROR_POLICY)
178BOOST_MATH_META_INT(error_policy_type, pole_error, BOOST_MATH_POLE_ERROR_POLICY)
179BOOST_MATH_META_INT(error_policy_type, overflow_error, BOOST_MATH_OVERFLOW_ERROR_POLICY)
180BOOST_MATH_META_INT(error_policy_type, underflow_error, BOOST_MATH_UNDERFLOW_ERROR_POLICY)
181BOOST_MATH_META_INT(error_policy_type, denorm_error, BOOST_MATH_DENORM_ERROR_POLICY)
182BOOST_MATH_META_INT(error_policy_type, evaluation_error, BOOST_MATH_EVALUATION_ERROR_POLICY)
183BOOST_MATH_META_INT(error_policy_type, rounding_error, BOOST_MATH_ROUNDING_ERROR_POLICY)
184BOOST_MATH_META_INT(error_policy_type, indeterminate_result_error, BOOST_MATH_INDETERMINATE_RESULT_ERROR_POLICY)
185
186//
187// Policy types for internal promotion:
188//
189BOOST_MATH_META_BOOL(promote_float, BOOST_MATH_PROMOTE_FLOAT_POLICY)
190BOOST_MATH_META_BOOL(promote_double, BOOST_MATH_PROMOTE_DOUBLE_POLICY)
191BOOST_MATH_META_BOOL(assert_undefined, BOOST_MATH_ASSERT_UNDEFINED_POLICY)
192//
193// Policy types for discrete quantiles:
194//
195enum discrete_quantile_policy_type
196{
197 real,
198 integer_round_outwards,
199 integer_round_inwards,
200 integer_round_down,
201 integer_round_up,
202 integer_round_nearest
203};
204
205BOOST_MATH_META_INT(discrete_quantile_policy_type, discrete_quantile, BOOST_MATH_DISCRETE_QUANTILE_POLICY)
206//
207// Precision:
208//
209BOOST_MATH_META_INT(int, digits10, BOOST_MATH_DIGITS10_POLICY)
210BOOST_MATH_META_INT(int, digits2, 0)
211//
212// Iterations:
213//
214BOOST_MATH_META_INT(unsigned long, max_series_iterations, BOOST_MATH_MAX_SERIES_ITERATION_POLICY)
215BOOST_MATH_META_INT(unsigned long, max_root_iterations, BOOST_MATH_MAX_ROOT_ITERATION_POLICY)
216//
217// Define the names for each possible policy:
218//
219#define BOOST_MATH_PARAMETER(name)\
220 BOOST_PARAMETER_TEMPLATE_KEYWORD(name##_name)\
221 BOOST_PARAMETER_NAME(name##_name)
222
223struct default_policy{};
224
225namespace detail{
226//
227// Trait to work out bits precision from digits10 and digits2:
228//
229template <class Digits10, class Digits2>
230struct precision
231{
232 //
233 // Now work out the precision:
234 //
235 using digits2_type = typename std::conditional<
236 (Digits10::value == 0),
237 digits2<0>,
238 digits2<((Digits10::value + 1) * 1000L) / 301L>
239 >::type;
240public:
241#ifdef BOOST_BORLANDC
242 using type = typename std::conditional<
243 (Digits2::value > ::boost::math::policies::detail::precision<Digits10,Digits2>::digits2_type::value),
244 Digits2, digits2_type>::type;
245#else
246 using type = typename std::conditional<
247 (Digits2::value > digits2_type::value),
248 Digits2, digits2_type>::type;
249#endif
250};
251
252double test_is_valid_arg(...);
253double test_is_default_arg(...);
254char test_is_valid_arg(const default_policy*);
255char test_is_default_arg(const default_policy*);
256
257template <typename T>
258class is_valid_policy_imp
259{
260public:
261 static constexpr bool value = sizeof(boost::math::policies::detail::test_is_valid_arg(static_cast<T*>(nullptr))) == sizeof(char);
262};
263
264template <typename T>
265class is_valid_policy
266{
267public:
268 static constexpr bool value = boost::math::policies::detail::is_valid_policy_imp<T>::value;
269};
270
271template <typename T>
272class is_default_policy_imp
273{
274public:
275 static constexpr bool value = sizeof(boost::math::policies::detail::test_is_default_arg(static_cast<T*>(nullptr))) == sizeof(char);
276};
277
278template <typename T>
279class is_default_policy
280{
281public:
282 static constexpr bool value = boost::math::policies::detail::is_default_policy_imp<T>::value;
283 using type = std::integral_constant<bool, value>;
284
285 template <typename U>
286 struct apply
287 {
288 using type = is_default_policy<U>;
289 };
290};
291
292template <class Seq, class T, std::size_t N>
293struct append_N
294{
295 using type = typename append_N<mp::mp_push_back<Seq, T>, T, N-1>::type;
296};
297
298template <class Seq, class T>
299struct append_N<Seq, T, 0>
300{
301 using type = Seq;
302};
303
304//
305// Traits class to work out what template parameters our default
306// policy<> class will have when modified for forwarding:
307//
308template <bool f, bool d>
309struct default_args
310{
311 typedef promote_float<false> arg1;
312 typedef promote_double<false> arg2;
313};
314
315template <>
316struct default_args<false, false>
317{
318 typedef default_policy arg1;
319 typedef default_policy arg2;
320};
321
322template <>
323struct default_args<true, false>
324{
325 typedef promote_float<false> arg1;
326 typedef default_policy arg2;
327};
328
329template <>
330struct default_args<false, true>
331{
332 typedef promote_double<false> arg1;
333 typedef default_policy arg2;
334};
335
336typedef default_args<BOOST_MATH_PROMOTE_FLOAT_POLICY, BOOST_MATH_PROMOTE_DOUBLE_POLICY>::arg1 forwarding_arg1;
337typedef default_args<BOOST_MATH_PROMOTE_FLOAT_POLICY, BOOST_MATH_PROMOTE_DOUBLE_POLICY>::arg2 forwarding_arg2;
338
339} // detail
340
341//
342// Now define the policy type with enough arguments to handle all
343// the policies:
344//
345template <typename A1 = default_policy,
346 typename A2 = default_policy,
347 typename A3 = default_policy,
348 typename A4 = default_policy,
349 typename A5 = default_policy,
350 typename A6 = default_policy,
351 typename A7 = default_policy,
352 typename A8 = default_policy,
353 typename A9 = default_policy,
354 typename A10 = default_policy,
355 typename A11 = default_policy,
356 typename A12 = default_policy,
357 typename A13 = default_policy>
358class policy
359{
360private:
361 //
362 // Validate all our arguments:
363 //
364 static_assert(::boost::math::policies::detail::is_valid_policy<A1>::value, "::boost::math::policies::detail::is_valid_policy<A1>::value");
365 static_assert(::boost::math::policies::detail::is_valid_policy<A2>::value, "::boost::math::policies::detail::is_valid_policy<A2>::value");
366 static_assert(::boost::math::policies::detail::is_valid_policy<A3>::value, "::boost::math::policies::detail::is_valid_policy<A3>::value");
367 static_assert(::boost::math::policies::detail::is_valid_policy<A4>::value, "::boost::math::policies::detail::is_valid_policy<A4>::value");
368 static_assert(::boost::math::policies::detail::is_valid_policy<A5>::value, "::boost::math::policies::detail::is_valid_policy<A5>::value");
369 static_assert(::boost::math::policies::detail::is_valid_policy<A6>::value, "::boost::math::policies::detail::is_valid_policy<A6>::value");
370 static_assert(::boost::math::policies::detail::is_valid_policy<A7>::value, "::boost::math::policies::detail::is_valid_policy<A7>::value");
371 static_assert(::boost::math::policies::detail::is_valid_policy<A8>::value, "::boost::math::policies::detail::is_valid_policy<A8>::value");
372 static_assert(::boost::math::policies::detail::is_valid_policy<A9>::value, "::boost::math::policies::detail::is_valid_policy<A9>::value");
373 static_assert(::boost::math::policies::detail::is_valid_policy<A10>::value, "::boost::math::policies::detail::is_valid_policy<A10>::value");
374 static_assert(::boost::math::policies::detail::is_valid_policy<A11>::value, "::boost::math::policies::detail::is_valid_policy<A11>::value");
375 static_assert(::boost::math::policies::detail::is_valid_policy<A12>::value, "::boost::math::policies::detail::is_valid_policy<A12>::value");
376 static_assert(::boost::math::policies::detail::is_valid_policy<A13>::value, "::boost::math::policies::detail::is_valid_policy<A13>::value");
377 //
378 // Typelist of the arguments:
379 //
380 using arg_list = mp::mp_list<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13>;
381 static constexpr std::size_t arg_list_size = mp::mp_size<arg_list>::value;
382
383 template<typename A, typename B, bool b>
384 struct pick_arg
385 {
386 using type = A;
387 };
388
389 template<typename A, typename B>
390 struct pick_arg<A, B, false>
391 {
392 using type = mp::mp_at<arg_list, B>;
393 };
394
395 template<typename Fn, typename Default>
396 class arg_type
397 {
398 private:
399 using index = mp::mp_find_if_q<arg_list, Fn>;
400 static constexpr bool end = (index::value >= arg_list_size);
401 public:
402 using type = typename pick_arg<Default, index, end>::type;
403 };
404
405 // Work out the base 2 and 10 precisions to calculate the public precision_type:
406 using digits10_type = typename arg_type<mp::mp_quote_trait<is_digits10>, digits10<>>::type;
407 using bits_precision_type = typename arg_type<mp::mp_quote_trait<is_digits2>, digits2<>>::type;
408
409public:
410
411 // Error Types:
412 using domain_error_type = typename arg_type<mp::mp_quote_trait<is_domain_error>, domain_error<>>::type;
413 using pole_error_type = typename arg_type<mp::mp_quote_trait<is_pole_error>, pole_error<>>::type;
414 using overflow_error_type = typename arg_type<mp::mp_quote_trait<is_overflow_error>, overflow_error<>>::type;
415 using underflow_error_type = typename arg_type<mp::mp_quote_trait<is_underflow_error>, underflow_error<>>::type;
416 using denorm_error_type = typename arg_type<mp::mp_quote_trait<is_denorm_error>, denorm_error<>>::type;
417 using evaluation_error_type = typename arg_type<mp::mp_quote_trait<is_evaluation_error>, evaluation_error<>>::type;
418 using rounding_error_type = typename arg_type<mp::mp_quote_trait<is_rounding_error>, rounding_error<>>::type;
419 using indeterminate_result_error_type = typename arg_type<mp::mp_quote_trait<is_indeterminate_result_error>, indeterminate_result_error<>>::type;
420
421 // Precision:
422 using precision_type = typename detail::precision<digits10_type, bits_precision_type>::type;
423
424 // Internal promotion:
425 using promote_float_type = typename arg_type<mp::mp_quote_trait<is_promote_float>, promote_float<>>::type;
426 using promote_double_type = typename arg_type<mp::mp_quote_trait<is_promote_double>, promote_double<>>::type;
427
428 // Discrete quantiles:
429 using discrete_quantile_type = typename arg_type<mp::mp_quote_trait<is_discrete_quantile>, discrete_quantile<>>::type;
430
431 // Mathematically undefined properties:
432 using assert_undefined_type = typename arg_type<mp::mp_quote_trait<is_assert_undefined>, assert_undefined<>>::type;
433
434 // Max iterations:
435 using max_series_iterations_type = typename arg_type<mp::mp_quote_trait<is_max_series_iterations>, max_series_iterations<>>::type;
436 using max_root_iterations_type = typename arg_type<mp::mp_quote_trait<is_max_root_iterations>, max_root_iterations<>>::type;
437};
438
439//
440// These full specializations are defined to reduce the amount of
441// template instantiations that have to take place when using the default
442// policies, they have quite a large impact on compile times:
443//
444template <>
445class policy<default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy>
446{
447public:
448 using domain_error_type = domain_error<>;
449 using pole_error_type = pole_error<>;
450 using overflow_error_type = overflow_error<>;
451 using underflow_error_type = underflow_error<>;
452 using denorm_error_type = denorm_error<>;
453 using evaluation_error_type = evaluation_error<>;
454 using rounding_error_type = rounding_error<>;
455 using indeterminate_result_error_type = indeterminate_result_error<>;
456#if BOOST_MATH_DIGITS10_POLICY == 0
457 using precision_type = digits2<>;
458#else
459 using precision_type = detail::precision<digits10<>, digits2<>>::type;
460#endif
461 using promote_float_type = promote_float<>;
462 using promote_double_type = promote_double<>;
463 using discrete_quantile_type = discrete_quantile<>;
464 using assert_undefined_type = assert_undefined<>;
465 using max_series_iterations_type = max_series_iterations<>;
466 using max_root_iterations_type = max_root_iterations<>;
467};
468
469template <>
470struct policy<detail::forwarding_arg1, detail::forwarding_arg2, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy>
471{
472public:
473 using domain_error_type = domain_error<>;
474 using pole_error_type = pole_error<>;
475 using overflow_error_type = overflow_error<>;
476 using underflow_error_type = underflow_error<>;
477 using denorm_error_type = denorm_error<>;
478 using evaluation_error_type = evaluation_error<>;
479 using rounding_error_type = rounding_error<>;
480 using indeterminate_result_error_type = indeterminate_result_error<>;
481#if BOOST_MATH_DIGITS10_POLICY == 0
482 using precision_type = digits2<>;
483#else
484 using precision_type = detail::precision<digits10<>, digits2<>>::type;
485#endif
486 using promote_float_type = promote_float<false>;
487 using promote_double_type = promote_double<false>;
488 using discrete_quantile_type = discrete_quantile<>;
489 using assert_undefined_type = assert_undefined<>;
490 using max_series_iterations_type = max_series_iterations<>;
491 using max_root_iterations_type = max_root_iterations<>;
492};
493
494template <typename Policy,
495 typename A1 = default_policy,
496 typename A2 = default_policy,
497 typename A3 = default_policy,
498 typename A4 = default_policy,
499 typename A5 = default_policy,
500 typename A6 = default_policy,
501 typename A7 = default_policy,
502 typename A8 = default_policy,
503 typename A9 = default_policy,
504 typename A10 = default_policy,
505 typename A11 = default_policy,
506 typename A12 = default_policy,
507 typename A13 = default_policy>
508class normalise
509{
510private:
511 using arg_list = mp::mp_list<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13>;
512 static constexpr std::size_t arg_list_size = mp::mp_size<arg_list>::value;
513
514 template<typename A, typename B, bool b>
515 struct pick_arg
516 {
517 using type = A;
518 };
519
520 template<typename A, typename B>
521 struct pick_arg<A, B, false>
522 {
523 using type = mp::mp_at<arg_list, B>;
524 };
525
526 template<typename Fn, typename Default>
527 class arg_type
528 {
529 private:
530 using index = mp::mp_find_if_q<arg_list, Fn>;
531 static constexpr bool end = (index::value >= arg_list_size);
532 public:
533 using type = typename pick_arg<Default, index, end>::type;
534 };
535
536 // Error types:
537 using domain_error_type = typename arg_type<mp::mp_quote_trait<is_domain_error>, typename Policy::domain_error_type>::type;
538 using pole_error_type = typename arg_type<mp::mp_quote_trait<is_pole_error>, typename Policy::pole_error_type>::type;
539 using overflow_error_type = typename arg_type<mp::mp_quote_trait<is_overflow_error>, typename Policy::overflow_error_type>::type;
540 using underflow_error_type = typename arg_type<mp::mp_quote_trait<is_underflow_error>, typename Policy::underflow_error_type>::type;
541 using denorm_error_type = typename arg_type<mp::mp_quote_trait<is_denorm_error>, typename Policy::denorm_error_type>::type;
542 using evaluation_error_type = typename arg_type<mp::mp_quote_trait<is_evaluation_error>, typename Policy::evaluation_error_type>::type;
543 using rounding_error_type = typename arg_type<mp::mp_quote_trait<is_rounding_error>, typename Policy::rounding_error_type>::type;
544 using indeterminate_result_error_type = typename arg_type<mp::mp_quote_trait<is_indeterminate_result_error>, typename Policy::indeterminate_result_error_type>::type;
545
546 // Precision:
547 using digits10_type = typename arg_type<mp::mp_quote_trait<is_digits10>, digits10<>>::type;
548 using bits_precision_type = typename arg_type<mp::mp_quote_trait<is_digits2>, typename Policy::precision_type>::type;
549 using precision_type = typename detail::precision<digits10_type, bits_precision_type>::type;
550
551 // Internal promotion:
552 using promote_float_type = typename arg_type<mp::mp_quote_trait<is_promote_float>, typename Policy::promote_float_type>::type;
553 using promote_double_type = typename arg_type<mp::mp_quote_trait<is_promote_double>, typename Policy::promote_double_type>::type;
554
555 // Discrete quantiles:
556 using discrete_quantile_type = typename arg_type<mp::mp_quote_trait<is_discrete_quantile>, typename Policy::discrete_quantile_type>::type;
557
558 // Mathematically undefined properties:
559 using assert_undefined_type = typename arg_type<mp::mp_quote_trait<is_assert_undefined>, typename Policy::assert_undefined_type>::type;
560
561 // Max iterations:
562 using max_series_iterations_type = typename arg_type<mp::mp_quote_trait<is_max_series_iterations>, typename Policy::max_series_iterations_type>::type;
563 using max_root_iterations_type = typename arg_type<mp::mp_quote_trait<is_max_root_iterations>, typename Policy::max_root_iterations_type>::type;
564
565 // Define a typelist of the policies:
566 using result_list = mp::mp_list<
567 domain_error_type,
568 pole_error_type,
569 overflow_error_type,
570 underflow_error_type,
571 denorm_error_type,
572 evaluation_error_type,
573 rounding_error_type,
574 indeterminate_result_error_type,
575 precision_type,
576 promote_float_type,
577 promote_double_type,
578 discrete_quantile_type,
579 assert_undefined_type,
580 max_series_iterations_type,
581 max_root_iterations_type>;
582
583 // Remove all the policies that are the same as the default:
584 using fn = mp::mp_quote_trait<detail::is_default_policy>;
585 using reduced_list = mp::mp_remove_if_q<result_list, fn>;
586
587 // Pad out the list with defaults:
588 using result_type = typename detail::append_N<reduced_list, default_policy, (14UL - mp::mp_size<reduced_list>::value)>::type;
589
590public:
591 using type = policy<
592 mp::mp_at_c<result_type, 0>,
593 mp::mp_at_c<result_type, 1>,
594 mp::mp_at_c<result_type, 2>,
595 mp::mp_at_c<result_type, 3>,
596 mp::mp_at_c<result_type, 4>,
597 mp::mp_at_c<result_type, 5>,
598 mp::mp_at_c<result_type, 6>,
599 mp::mp_at_c<result_type, 7>,
600 mp::mp_at_c<result_type, 8>,
601 mp::mp_at_c<result_type, 9>,
602 mp::mp_at_c<result_type, 10>,
603 mp::mp_at_c<result_type, 11>,
604 mp::mp_at_c<result_type, 12>
605 >;
606};
607
608// Full specialisation to speed up compilation of the common case:
609template <>
610struct normalise<policy<>,
611 promote_float<false>,
612 promote_double<false>,
613 discrete_quantile<>,
614 assert_undefined<>,
615 default_policy,
616 default_policy,
617 default_policy,
618 default_policy,
619 default_policy,
620 default_policy,
621 default_policy>
622{
623 using type = policy<detail::forwarding_arg1, detail::forwarding_arg2>;
624};
625
626template <>
627struct normalise<policy<detail::forwarding_arg1, detail::forwarding_arg2>,
628 promote_float<false>,
629 promote_double<false>,
630 discrete_quantile<>,
631 assert_undefined<>,
632 default_policy,
633 default_policy,
634 default_policy,
635 default_policy,
636 default_policy,
637 default_policy,
638 default_policy>
639{
640 using type = policy<detail::forwarding_arg1, detail::forwarding_arg2>;
641};
642
643inline constexpr policy<> make_policy() noexcept
644{ return {}; }
645
646template <class A1>
647inline constexpr typename normalise<policy<>, A1>::type make_policy(const A1&) noexcept
648{
649 typedef typename normalise<policy<>, A1>::type result_type;
650 return result_type();
651}
652
653template <class A1, class A2>
654inline constexpr typename normalise<policy<>, A1, A2>::type make_policy(const A1&, const A2&) noexcept
655{
656 typedef typename normalise<policy<>, A1, A2>::type result_type;
657 return result_type();
658}
659
660template <class A1, class A2, class A3>
661inline constexpr typename normalise<policy<>, A1, A2, A3>::type make_policy(const A1&, const A2&, const A3&) noexcept
662{
663 typedef typename normalise<policy<>, A1, A2, A3>::type result_type;
664 return result_type();
665}
666
667template <class A1, class A2, class A3, class A4>
668inline constexpr typename normalise<policy<>, A1, A2, A3, A4>::type make_policy(const A1&, const A2&, const A3&, const A4&) noexcept
669{
670 typedef typename normalise<policy<>, A1, A2, A3, A4>::type result_type;
671 return result_type();
672}
673
674template <class A1, class A2, class A3, class A4, class A5>
675inline constexpr typename normalise<policy<>, A1, A2, A3, A4, A5>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&) noexcept
676{
677 typedef typename normalise<policy<>, A1, A2, A3, A4, A5>::type result_type;
678 return result_type();
679}
680
681template <class A1, class A2, class A3, class A4, class A5, class A6>
682inline constexpr typename normalise<policy<>, A1, A2, A3, A4, A5, A6>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&) noexcept
683{
684 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6>::type result_type;
685 return result_type();
686}
687
688template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
689inline constexpr typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&) noexcept
690{
691 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7>::type result_type;
692 return result_type();
693}
694
695template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
696inline constexpr typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&) noexcept
697{
698 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8>::type result_type;
699 return result_type();
700}
701
702template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
703inline constexpr typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&, const A9&) noexcept
704{
705 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9>::type result_type;
706 return result_type();
707}
708
709template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
710inline constexpr typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&, const A9&, const A10&) noexcept
711{
712 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>::type result_type;
713 return result_type();
714}
715
716template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10, class A11>
717inline constexpr typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&, const A9&, const A10&, const A11&) noexcept
718{
719 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11>::type result_type;
720 return result_type();
721}
722
723//
724// Traits class to handle internal promotion:
725//
726template <class Real, class Policy>
727struct evaluation
728{
729 typedef Real type;
730};
731
732template <class Policy>
733struct evaluation<float, Policy>
734{
735 using type = typename std::conditional<Policy::promote_float_type::value, double, float>::type;
736};
737
738template <class Policy>
739struct evaluation<double, Policy>
740{
741 using type = typename std::conditional<Policy::promote_double_type::value, long double, double>::type;
742};
743
744template <class Real, class Policy>
745struct precision
746{
747 static_assert((std::numeric_limits<Real>::radix == 2) || ((std::numeric_limits<Real>::is_specialized == 0) || (std::numeric_limits<Real>::digits == 0)),
748 "(std::numeric_limits<Real>::radix == 2) || ((std::numeric_limits<Real>::is_specialized == 0) || (std::numeric_limits<Real>::digits == 0))");
749#ifndef BOOST_BORLANDC
750 using precision_type = typename Policy::precision_type;
751 using type = typename std::conditional<
752 ((std::numeric_limits<Real>::is_specialized == 0) || (std::numeric_limits<Real>::digits == 0)),
753 // Possibly unknown precision:
754 precision_type,
755 typename std::conditional<
756 ((std::numeric_limits<Real>::digits <= precision_type::value)
757 || (Policy::precision_type::value <= 0)),
758 // Default case, full precision for RealType:
759 digits2< std::numeric_limits<Real>::digits>,
760 // User customised precision:
761 precision_type
762 >::type
763 >::type;
764#else
765 using precision_type = typename Policy::precision_type;
766 using digits_t = std::integral_constant<int, std::numeric_limits<Real>::digits>;
767 using spec_t = std::integral_constant<bool, std::numeric_limits<Real>::is_specialized>;
768 using type = typename std::conditional<
769 (spec_t::value == true std::true_type || digits_t::value == 0),
770 // Possibly unknown precision:
771 precision_type,
772 typename std::conditional<
773 (digits_t::value <= precision_type::value || precision_type::value <= 0),
774 // Default case, full precision for RealType:
775 digits2< std::numeric_limits<Real>::digits>,
776 // User customised precision:
777 precision_type
778 >::type
779 >::type;
780#endif
781};
782
783#ifdef BOOST_MATH_USE_FLOAT128
784
785template <class Policy>
786struct precision<BOOST_MATH_FLOAT128_TYPE, Policy>
787{
788 typedef std::integral_constant<int, 113> type;
789};
790
791#endif
792
793namespace detail{
794
795template <class T, class Policy>
796inline constexpr int digits_imp(std::true_type const&) noexcept
797{
798 static_assert( std::numeric_limits<T>::is_specialized, "std::numeric_limits<T>::is_specialized");
799 typedef typename boost::math::policies::precision<T, Policy>::type p_t;
800 return p_t::value;
801}
802
803template <class T, class Policy>
804inline constexpr int digits_imp(std::false_type const&) noexcept
805{
806 return tools::digits<T>();
807}
808
809} // namespace detail
810
811template <class T, class Policy>
812inline constexpr int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept
813{
814 typedef std::integral_constant<bool, std::numeric_limits<T>::is_specialized > tag_type;
815 return detail::digits_imp<T, Policy>(tag_type());
816}
817template <class T, class Policy>
818inline constexpr int digits_base10(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept
819{
820 return boost::math::policies::digits<T, Policy>() * 301 / 1000L;
821}
822
823template <class Policy>
824inline constexpr unsigned long get_max_series_iterations() noexcept
825{
826 typedef typename Policy::max_series_iterations_type iter_type;
827 return iter_type::value;
828}
829
830template <class Policy>
831inline constexpr unsigned long get_max_root_iterations() noexcept
832{
833 typedef typename Policy::max_root_iterations_type iter_type;
834 return iter_type::value;
835}
836
837namespace detail{
838
839template <class T, class Digits, class Small, class Default>
840struct series_factor_calc
841{
842 static T get() noexcept(std::is_floating_point<T>::value)
843 {
844 return ldexp(T(1.0), 1 - Digits::value);
845 }
846};
847
848template <class T, class Digits>
849struct series_factor_calc<T, Digits, std::true_type, std::true_type>
850{
851 static constexpr T get() noexcept(std::is_floating_point<T>::value)
852 {
853 return boost::math::tools::epsilon<T>();
854 }
855};
856template <class T, class Digits>
857struct series_factor_calc<T, Digits, std::true_type, std::false_type>
858{
859 static constexpr T get() noexcept(std::is_floating_point<T>::value)
860 {
861 return 1 / static_cast<T>(static_cast<std::uintmax_t>(1u) << (Digits::value - 1));
862 }
863};
864template <class T, class Digits>
865struct series_factor_calc<T, Digits, std::false_type, std::true_type>
866{
867 static constexpr T get() noexcept(std::is_floating_point<T>::value)
868 {
869 return boost::math::tools::epsilon<T>();
870 }
871};
872
873template <class T, class Policy>
874inline constexpr T get_epsilon_imp(std::true_type const&) noexcept(std::is_floating_point<T>::value)
875{
876 static_assert(std::numeric_limits<T>::is_specialized, "std::numeric_limits<T>::is_specialized");
877 static_assert(std::numeric_limits<T>::radix == 2, "std::numeric_limits<T>::radix == 2");
878
879 typedef typename boost::math::policies::precision<T, Policy>::type p_t;
880 typedef std::integral_constant<bool, p_t::value <= std::numeric_limits<std::uintmax_t>::digits> is_small_int;
881 typedef std::integral_constant<bool, p_t::value >= std::numeric_limits<T>::digits> is_default_value;
882 return series_factor_calc<T, p_t, is_small_int, is_default_value>::get();
883}
884
885template <class T, class Policy>
886inline constexpr T get_epsilon_imp(std::false_type const&) noexcept(std::is_floating_point<T>::value)
887{
888 return tools::epsilon<T>();
889}
890
891} // namespace detail
892
893template <class T, class Policy>
894inline constexpr T get_epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(std::is_floating_point<T>::value)
895{
896 typedef std::integral_constant<bool, (std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::radix == 2)) > tag_type;
897 return detail::get_epsilon_imp<T, Policy>(tag_type());
898}
899
900namespace detail{
901
902template <class A1,
903 class A2,
904 class A3,
905 class A4,
906 class A5,
907 class A6,
908 class A7,
909 class A8,
910 class A9,
911 class A10,
912 class A11>
913char test_is_policy(const policy<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11>*);
914double test_is_policy(...);
915
916template <typename P>
917class is_policy_imp
918{
919public:
920 static constexpr bool value = (sizeof(::boost::math::policies::detail::test_is_policy(static_cast<P*>(nullptr))) == sizeof(char));
921};
922
923}
924
925template <typename P>
926class is_policy
927{
928public:
929 static constexpr bool value = boost::math::policies::detail::is_policy_imp<P>::value;
930 using type = std::integral_constant<bool, value>;
931};
932
933//
934// Helper traits class for distribution error handling:
935//
936template <class Policy>
937struct constructor_error_check
938{
939 using domain_error_type = typename Policy::domain_error_type;
940 using type = typename std::conditional<
941 (domain_error_type::value == throw_on_error) || (domain_error_type::value == user_error) || (domain_error_type::value == errno_on_error),
942 std::true_type,
943 std::false_type>::type;
944};
945
946template <class Policy>
947struct method_error_check
948{
949 using domain_error_type = typename Policy::domain_error_type;
950 using type = typename std::conditional<
951 (domain_error_type::value == throw_on_error),
952 std::false_type,
953 std::true_type>::type;
954};
955//
956// Does the Policy ever throw on error?
957//
958template <class Policy>
959struct is_noexcept_error_policy
960{
961 typedef typename Policy::domain_error_type t1;
962 typedef typename Policy::pole_error_type t2;
963 typedef typename Policy::overflow_error_type t3;
964 typedef typename Policy::underflow_error_type t4;
965 typedef typename Policy::denorm_error_type t5;
966 typedef typename Policy::evaluation_error_type t6;
967 typedef typename Policy::rounding_error_type t7;
968 typedef typename Policy::indeterminate_result_error_type t8;
969
970 static constexpr bool value =
971 ((t1::value != throw_on_error) && (t1::value != user_error)
972 && (t2::value != throw_on_error) && (t2::value != user_error)
973 && (t3::value != throw_on_error) && (t3::value != user_error)
974 && (t4::value != throw_on_error) && (t4::value != user_error)
975 && (t5::value != throw_on_error) && (t5::value != user_error)
976 && (t6::value != throw_on_error) && (t6::value != user_error)
977 && (t7::value != throw_on_error) && (t7::value != user_error)
978 && (t8::value != throw_on_error) && (t8::value != user_error));
979};
980
981}}} // namespaces
982
983#endif // BOOST_MATH_POLICY_HPP
984
985

source code of boost/libs/math/include/boost/math/policies/policy.hpp