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

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