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::mpl::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::mpl::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::mpl::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::mpl::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::mpl::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::mpl::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::mpl::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::mpl::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 mpl::bool_<
322 ::boost::math::policies::detail::is_valid_policy_imp<T>::value>
323{};
324
325template <class T> struct is_default_policy
326: public mpl::bool_<
327 ::boost::math::policies::detail::is_default_policy_imp<T>::value>
328{
329 template <class U>
330 struct apply
331 {
332 typedef is_default_policy<U> type;
333 };
334};
335
336template <class Seq, class T, int N>
337struct append_N
338{
339 typedef typename mpl::push_back<Seq, T>::type new_seq;
340 typedef typename append_N<new_seq, T, N-1>::type type;
341};
342
343template <class Seq, class T>
344struct append_N<Seq, T, 0>
345{
346 typedef Seq type;
347};
348
349//
350// Traits class to work out what template parameters our default
351// policy<> class will have when modified for forwarding:
352//
353template <bool f, bool d>
354struct default_args
355{
356 typedef promote_float<false> arg1;
357 typedef promote_double<false> arg2;
358};
359
360template <>
361struct default_args<false, false>
362{
363 typedef default_policy arg1;
364 typedef default_policy arg2;
365};
366
367template <>
368struct default_args<true, false>
369{
370 typedef promote_float<false> arg1;
371 typedef default_policy arg2;
372};
373
374template <>
375struct default_args<false, true>
376{
377 typedef promote_double<false> arg1;
378 typedef default_policy arg2;
379};
380
381typedef default_args<BOOST_MATH_PROMOTE_FLOAT_POLICY, BOOST_MATH_PROMOTE_DOUBLE_POLICY>::arg1 forwarding_arg1;
382typedef default_args<BOOST_MATH_PROMOTE_FLOAT_POLICY, BOOST_MATH_PROMOTE_DOUBLE_POLICY>::arg2 forwarding_arg2;
383
384} // detail
385//
386// Now define the policy type with enough arguments to handle all
387// the policies:
388//
389template <class A1 = default_policy,
390 class A2 = default_policy,
391 class A3 = default_policy,
392 class A4 = default_policy,
393 class A5 = default_policy,
394 class A6 = default_policy,
395 class A7 = default_policy,
396 class A8 = default_policy,
397 class A9 = default_policy,
398 class A10 = default_policy,
399 class A11 = default_policy,
400 class A12 = default_policy,
401 class A13 = default_policy>
402struct policy
403{
404private:
405 //
406 // Validate all our arguments:
407 //
408 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A1>::value);
409 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A2>::value);
410 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A3>::value);
411 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A4>::value);
412 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A5>::value);
413 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A6>::value);
414 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A7>::value);
415 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A8>::value);
416 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A9>::value);
417 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A10>::value);
418 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A11>::value);
419 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A12>::value);
420 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A13>::value);
421 //
422 // Typelist of the arguments:
423 //
424 typedef mpl::list<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13> arg_list;
425
426public:
427 typedef typename detail::find_arg<arg_list, is_domain_error<mpl::_1>, domain_error<> >::type domain_error_type;
428 typedef typename detail::find_arg<arg_list, is_pole_error<mpl::_1>, pole_error<> >::type pole_error_type;
429 typedef typename detail::find_arg<arg_list, is_overflow_error<mpl::_1>, overflow_error<> >::type overflow_error_type;
430 typedef typename detail::find_arg<arg_list, is_underflow_error<mpl::_1>, underflow_error<> >::type underflow_error_type;
431 typedef typename detail::find_arg<arg_list, is_denorm_error<mpl::_1>, denorm_error<> >::type denorm_error_type;
432 typedef typename detail::find_arg<arg_list, is_evaluation_error<mpl::_1>, evaluation_error<> >::type evaluation_error_type;
433 typedef typename detail::find_arg<arg_list, is_rounding_error<mpl::_1>, rounding_error<> >::type rounding_error_type;
434 typedef typename detail::find_arg<arg_list, is_indeterminate_result_error<mpl::_1>, indeterminate_result_error<> >::type indeterminate_result_error_type;
435private:
436 //
437 // Now work out the precision:
438 //
439 typedef typename detail::find_arg<arg_list, is_digits10<mpl::_1>, digits10<> >::type digits10_type;
440 typedef typename detail::find_arg<arg_list, is_digits2<mpl::_1>, digits2<> >::type bits_precision_type;
441public:
442 typedef typename detail::precision<digits10_type, bits_precision_type>::type precision_type;
443 //
444 // Internal promotion:
445 //
446 typedef typename detail::find_arg<arg_list, is_promote_float<mpl::_1>, promote_float<> >::type promote_float_type;
447 typedef typename detail::find_arg<arg_list, is_promote_double<mpl::_1>, promote_double<> >::type promote_double_type;
448 //
449 // Discrete quantiles:
450 //
451 typedef typename detail::find_arg<arg_list, is_discrete_quantile<mpl::_1>, discrete_quantile<> >::type discrete_quantile_type;
452 //
453 // Mathematically undefined properties:
454 //
455 typedef typename detail::find_arg<arg_list, is_assert_undefined<mpl::_1>, assert_undefined<> >::type assert_undefined_type;
456 //
457 // Max iterations:
458 //
459 typedef typename detail::find_arg<arg_list, is_max_series_iterations<mpl::_1>, max_series_iterations<> >::type max_series_iterations_type;
460 typedef typename detail::find_arg<arg_list, is_max_root_iterations<mpl::_1>, max_root_iterations<> >::type max_root_iterations_type;
461};
462//
463// These full specializations are defined to reduce the amount of
464// template instantiations that have to take place when using the default
465// policies, they have quite a large impact on compile times:
466//
467template <>
468struct policy<default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy>
469{
470public:
471 typedef domain_error<> domain_error_type;
472 typedef pole_error<> pole_error_type;
473 typedef overflow_error<> overflow_error_type;
474 typedef underflow_error<> underflow_error_type;
475 typedef denorm_error<> denorm_error_type;
476 typedef evaluation_error<> evaluation_error_type;
477 typedef rounding_error<> rounding_error_type;
478 typedef indeterminate_result_error<> indeterminate_result_error_type;
479#if BOOST_MATH_DIGITS10_POLICY == 0
480 typedef digits2<> precision_type;
481#else
482 typedef detail::precision<digits10<>, digits2<> >::type precision_type;
483#endif
484 typedef promote_float<> promote_float_type;
485 typedef promote_double<> promote_double_type;
486 typedef discrete_quantile<> discrete_quantile_type;
487 typedef assert_undefined<> assert_undefined_type;
488 typedef max_series_iterations<> max_series_iterations_type;
489 typedef max_root_iterations<> max_root_iterations_type;
490};
491
492template <>
493struct 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>
494{
495public:
496 typedef domain_error<> domain_error_type;
497 typedef pole_error<> pole_error_type;
498 typedef overflow_error<> overflow_error_type;
499 typedef underflow_error<> underflow_error_type;
500 typedef denorm_error<> denorm_error_type;
501 typedef evaluation_error<> evaluation_error_type;
502 typedef rounding_error<> rounding_error_type;
503 typedef indeterminate_result_error<> indeterminate_result_error_type;
504#if BOOST_MATH_DIGITS10_POLICY == 0
505 typedef digits2<> precision_type;
506#else
507 typedef detail::precision<digits10<>, digits2<> >::type precision_type;
508#endif
509 typedef promote_float<false> promote_float_type;
510 typedef promote_double<false> promote_double_type;
511 typedef discrete_quantile<> discrete_quantile_type;
512 typedef assert_undefined<> assert_undefined_type;
513 typedef max_series_iterations<> max_series_iterations_type;
514 typedef max_root_iterations<> max_root_iterations_type;
515};
516
517template <class Policy,
518 class A1 = default_policy,
519 class A2 = default_policy,
520 class A3 = default_policy,
521 class A4 = default_policy,
522 class A5 = default_policy,
523 class A6 = default_policy,
524 class A7 = default_policy,
525 class A8 = default_policy,
526 class A9 = default_policy,
527 class A10 = default_policy,
528 class A11 = default_policy,
529 class A12 = default_policy,
530 class A13 = default_policy>
531struct normalise
532{
533private:
534 typedef mpl::list<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13> arg_list;
535 typedef typename detail::find_arg<arg_list, is_domain_error<mpl::_1>, typename Policy::domain_error_type >::type domain_error_type;
536 typedef typename detail::find_arg<arg_list, is_pole_error<mpl::_1>, typename Policy::pole_error_type >::type pole_error_type;
537 typedef typename detail::find_arg<arg_list, is_overflow_error<mpl::_1>, typename Policy::overflow_error_type >::type overflow_error_type;
538 typedef typename detail::find_arg<arg_list, is_underflow_error<mpl::_1>, typename Policy::underflow_error_type >::type underflow_error_type;
539 typedef typename detail::find_arg<arg_list, is_denorm_error<mpl::_1>, typename Policy::denorm_error_type >::type denorm_error_type;
540 typedef typename detail::find_arg<arg_list, is_evaluation_error<mpl::_1>, typename Policy::evaluation_error_type >::type evaluation_error_type;
541 typedef typename detail::find_arg<arg_list, is_rounding_error<mpl::_1>, typename Policy::rounding_error_type >::type rounding_error_type;
542 typedef typename detail::find_arg<arg_list, is_indeterminate_result_error<mpl::_1>, typename Policy::indeterminate_result_error_type >::type indeterminate_result_error_type;
543 //
544 // Now work out the precision:
545 //
546 typedef typename detail::find_arg<arg_list, is_digits10<mpl::_1>, digits10<> >::type digits10_type;
547 typedef typename detail::find_arg<arg_list, is_digits2<mpl::_1>, typename Policy::precision_type >::type bits_precision_type;
548 typedef typename detail::precision<digits10_type, bits_precision_type>::type precision_type;
549 //
550 // Internal promotion:
551 //
552 typedef typename detail::find_arg<arg_list, is_promote_float<mpl::_1>, typename Policy::promote_float_type >::type promote_float_type;
553 typedef typename detail::find_arg<arg_list, is_promote_double<mpl::_1>, typename Policy::promote_double_type >::type promote_double_type;
554 //
555 // Discrete quantiles:
556 //
557 typedef typename detail::find_arg<arg_list, is_discrete_quantile<mpl::_1>, typename Policy::discrete_quantile_type >::type discrete_quantile_type;
558 //
559 // Mathematically undefined properties:
560 //
561 typedef typename detail::find_arg<arg_list, is_assert_undefined<mpl::_1>, typename Policy::assert_undefined_type >::type assert_undefined_type;
562 //
563 // Max iterations:
564 //
565 typedef typename detail::find_arg<arg_list, is_max_series_iterations<mpl::_1>, typename Policy::max_series_iterations_type>::type max_series_iterations_type;
566 typedef typename detail::find_arg<arg_list, is_max_root_iterations<mpl::_1>, typename Policy::max_root_iterations_type>::type max_root_iterations_type;
567 //
568 // Define a typelist of the policies:
569 //
570 typedef mpl::vector<
571 domain_error_type,
572 pole_error_type,
573 overflow_error_type,
574 underflow_error_type,
575 denorm_error_type,
576 evaluation_error_type,
577 rounding_error_type,
578 indeterminate_result_error_type,
579 precision_type,
580 promote_float_type,
581 promote_double_type,
582 discrete_quantile_type,
583 assert_undefined_type,
584 max_series_iterations_type,
585 max_root_iterations_type> result_list;
586 //
587 // Remove all the policies that are the same as the default:
588 //
589 typedef typename mpl::remove_if<result_list, detail::is_default_policy<mpl::_> >::type reduced_list;
590 //
591 // Pad out the list with defaults:
592 //
593 typedef typename detail::append_N<reduced_list, default_policy, (14 - ::boost::mpl::size<reduced_list>::value)>::type result_type;
594public:
595 typedef policy<
596 typename mpl::at<result_type, mpl::int_<0> >::type,
597 typename mpl::at<result_type, mpl::int_<1> >::type,
598 typename mpl::at<result_type, mpl::int_<2> >::type,
599 typename mpl::at<result_type, mpl::int_<3> >::type,
600 typename mpl::at<result_type, mpl::int_<4> >::type,
601 typename mpl::at<result_type, mpl::int_<5> >::type,
602 typename mpl::at<result_type, mpl::int_<6> >::type,
603 typename mpl::at<result_type, mpl::int_<7> >::type,
604 typename mpl::at<result_type, mpl::int_<8> >::type,
605 typename mpl::at<result_type, mpl::int_<9> >::type,
606 typename mpl::at<result_type, mpl::int_<10> >::type,
607 typename mpl::at<result_type, mpl::int_<11> >::type,
608 typename mpl::at<result_type, mpl::int_<12> >::type > type;
609};
610//
611// Full specialisation to speed up compilation of the common case:
612//
613template <>
614struct normalise<policy<>,
615 promote_float<false>,
616 promote_double<false>,
617 discrete_quantile<>,
618 assert_undefined<>,
619 default_policy,
620 default_policy,
621 default_policy,
622 default_policy,
623 default_policy,
624 default_policy,
625 default_policy>
626{
627 typedef policy<detail::forwarding_arg1, detail::forwarding_arg2> type;
628};
629
630template <>
631struct normalise<policy<detail::forwarding_arg1, detail::forwarding_arg2>,
632 promote_float<false>,
633 promote_double<false>,
634 discrete_quantile<>,
635 assert_undefined<>,
636 default_policy,
637 default_policy,
638 default_policy,
639 default_policy,
640 default_policy,
641 default_policy,
642 default_policy>
643{
644 typedef policy<detail::forwarding_arg1, detail::forwarding_arg2> type;
645};
646
647inline BOOST_MATH_CONSTEXPR policy<> make_policy() BOOST_NOEXCEPT
648{ return policy<>(); }
649
650template <class A1>
651inline BOOST_MATH_CONSTEXPR typename normalise<policy<>, A1>::type make_policy(const A1&) BOOST_NOEXCEPT
652{
653 typedef typename normalise<policy<>, A1>::type result_type;
654 return result_type();
655}
656
657template <class A1, class A2>
658inline BOOST_MATH_CONSTEXPR typename normalise<policy<>, A1, A2>::type make_policy(const A1&, const A2&) BOOST_NOEXCEPT
659{
660 typedef typename normalise<policy<>, A1, A2>::type result_type;
661 return result_type();
662}
663
664template <class A1, class A2, class A3>
665inline BOOST_MATH_CONSTEXPR typename normalise<policy<>, A1, A2, A3>::type make_policy(const A1&, const A2&, const A3&) BOOST_NOEXCEPT
666{
667 typedef typename normalise<policy<>, A1, A2, A3>::type result_type;
668 return result_type();
669}
670
671template <class A1, class A2, class A3, class A4>
672inline BOOST_MATH_CONSTEXPR typename normalise<policy<>, A1, A2, A3, A4>::type make_policy(const A1&, const A2&, const A3&, const A4&) BOOST_NOEXCEPT
673{
674 typedef typename normalise<policy<>, A1, A2, A3, A4>::type result_type;
675 return result_type();
676}
677
678template <class A1, class A2, class A3, class A4, class A5>
679inline 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
680{
681 typedef typename normalise<policy<>, A1, A2, A3, A4, A5>::type result_type;
682 return result_type();
683}
684
685template <class A1, class A2, class A3, class A4, class A5, class A6>
686inline 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
687{
688 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6>::type result_type;
689 return result_type();
690}
691
692template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
693inline 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
694{
695 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7>::type result_type;
696 return result_type();
697}
698
699template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
700inline 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
701{
702 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8>::type result_type;
703 return result_type();
704}
705
706template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
707inline 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
708{
709 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9>::type result_type;
710 return result_type();
711}
712
713template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
714inline 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
715{
716 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>::type result_type;
717 return result_type();
718}
719
720template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10, class A11>
721inline 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
722{
723 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11>::type result_type;
724 return result_type();
725}
726
727//
728// Traits class to handle internal promotion:
729//
730template <class Real, class Policy>
731struct evaluation
732{
733 typedef Real type;
734};
735
736template <class Policy>
737struct evaluation<float, Policy>
738{
739 typedef typename mpl::if_<typename Policy::promote_float_type, double, float>::type type;
740};
741
742template <class Policy>
743struct evaluation<double, Policy>
744{
745 typedef typename mpl::if_<typename Policy::promote_double_type, long double, double>::type type;
746};
747
748#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
749
750template <class Real>
751struct basic_digits : public mpl::int_<0>{ };
752template <>
753struct basic_digits<float> : public mpl::int_<FLT_MANT_DIG>{ };
754template <>
755struct basic_digits<double> : public mpl::int_<DBL_MANT_DIG>{ };
756template <>
757struct basic_digits<long double> : public mpl::int_<LDBL_MANT_DIG>{ };
758
759template <class Real, class Policy>
760struct precision
761{
762 BOOST_STATIC_ASSERT( ::std::numeric_limits<Real>::radix == 2);
763 typedef typename Policy::precision_type precision_type;
764 typedef basic_digits<Real> digits_t;
765 typedef typename mpl::if_<
766 mpl::equal_to<digits_t, mpl::int_<0> >,
767 // Possibly unknown precision:
768 precision_type,
769 typename mpl::if_<
770 mpl::or_<mpl::less_equal<digits_t, precision_type>, mpl::less_equal<precision_type, mpl::int_<0> > >,
771 // Default case, full precision for RealType:
772 digits2< ::std::numeric_limits<Real>::digits>,
773 // User customised precision:
774 precision_type
775 >::type
776 >::type type;
777};
778
779template <class Policy>
780struct precision<float, Policy>
781{
782 typedef digits2<FLT_MANT_DIG> type;
783};
784template <class Policy>
785struct precision<double, Policy>
786{
787 typedef digits2<DBL_MANT_DIG> type;
788};
789template <class Policy>
790struct precision<long double, Policy>
791{
792 typedef digits2<LDBL_MANT_DIG> type;
793};
794
795#else
796
797template <class Real, class Policy>
798struct precision
799{
800 BOOST_STATIC_ASSERT((::std::numeric_limits<Real>::radix == 2) || ((::std::numeric_limits<Real>::is_specialized == 0) || (::std::numeric_limits<Real>::digits == 0)));
801#ifndef __BORLANDC__
802 typedef typename Policy::precision_type precision_type;
803 typedef typename mpl::if_c<
804 ((::std::numeric_limits<Real>::is_specialized == 0) || (::std::numeric_limits<Real>::digits == 0)),
805 // Possibly unknown precision:
806 precision_type,
807 typename mpl::if_c<
808 ((::std::numeric_limits<Real>::digits <= precision_type::value)
809 || (Policy::precision_type::value <= 0)),
810 // Default case, full precision for RealType:
811 digits2< ::std::numeric_limits<Real>::digits>,
812 // User customised precision:
813 precision_type
814 >::type
815 >::type type;
816#else
817 typedef typename Policy::precision_type precision_type;
818 typedef mpl::int_< ::std::numeric_limits<Real>::digits> digits_t;
819 typedef mpl::bool_< ::std::numeric_limits<Real>::is_specialized> spec_t;
820 typedef typename mpl::if_<
821 mpl::or_<mpl::equal_to<spec_t, mpl::false_>, mpl::equal_to<digits_t, mpl::int_<0> > >,
822 // Possibly unknown precision:
823 precision_type,
824 typename mpl::if_<
825 mpl::or_<mpl::less_equal<digits_t, precision_type>, mpl::less_equal<precision_type, mpl::int_<0> > >,
826 // Default case, full precision for RealType:
827 digits2< ::std::numeric_limits<Real>::digits>,
828 // User customised precision:
829 precision_type
830 >::type
831 >::type type;
832#endif
833};
834
835#endif
836
837#ifdef BOOST_MATH_USE_FLOAT128
838
839template <class Policy>
840struct precision<BOOST_MATH_FLOAT128_TYPE, Policy>
841{
842 typedef mpl::int_<113> type;
843};
844
845#endif
846
847namespace detail{
848
849template <class T, class Policy>
850inline BOOST_MATH_CONSTEXPR int digits_imp(mpl::true_ const&) BOOST_NOEXCEPT
851{
852#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
853 BOOST_STATIC_ASSERT( ::std::numeric_limits<T>::is_specialized);
854#else
855 BOOST_ASSERT(::std::numeric_limits<T>::is_specialized);
856#endif
857 typedef typename boost::math::policies::precision<T, Policy>::type p_t;
858 return p_t::value;
859}
860
861template <class T, class Policy>
862inline BOOST_MATH_CONSTEXPR int digits_imp(mpl::false_ const&) BOOST_NOEXCEPT
863{
864 return tools::digits<T>();
865}
866
867} // namespace detail
868
869template <class T, class Policy>
870inline BOOST_MATH_CONSTEXPR int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) BOOST_NOEXCEPT
871{
872 typedef mpl::bool_< std::numeric_limits<T>::is_specialized > tag_type;
873 return detail::digits_imp<T, Policy>(tag_type());
874}
875template <class T, class Policy>
876inline BOOST_MATH_CONSTEXPR int digits_base10(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) BOOST_NOEXCEPT
877{
878 return boost::math::policies::digits<T, Policy>() * 301 / 1000L;
879}
880
881template <class Policy>
882inline BOOST_MATH_CONSTEXPR unsigned long get_max_series_iterations() BOOST_NOEXCEPT
883{
884 typedef typename Policy::max_series_iterations_type iter_type;
885 return iter_type::value;
886}
887
888template <class Policy>
889inline BOOST_MATH_CONSTEXPR unsigned long get_max_root_iterations() BOOST_NOEXCEPT
890{
891 typedef typename Policy::max_root_iterations_type iter_type;
892 return iter_type::value;
893}
894
895namespace detail{
896
897template <class T, class Digits, class Small, class Default>
898struct series_factor_calc
899{
900 static T get() BOOST_MATH_NOEXCEPT(T)
901 {
902 return ldexp(T(1.0), 1 - Digits::value);
903 }
904};
905
906template <class T, class Digits>
907struct series_factor_calc<T, Digits, mpl::true_, mpl::true_>
908{
909 static BOOST_MATH_CONSTEXPR T get() BOOST_MATH_NOEXCEPT(T)
910 {
911 return boost::math::tools::epsilon<T>();
912 }
913};
914template <class T, class Digits>
915struct series_factor_calc<T, Digits, mpl::true_, mpl::false_>
916{
917 static BOOST_MATH_CONSTEXPR T get() BOOST_MATH_NOEXCEPT(T)
918 {
919 return 1 / static_cast<T>(static_cast<boost::uintmax_t>(1u) << (Digits::value - 1));
920 }
921};
922template <class T, class Digits>
923struct series_factor_calc<T, Digits, mpl::false_, mpl::true_>
924{
925 static BOOST_MATH_CONSTEXPR T get() BOOST_MATH_NOEXCEPT(T)
926 {
927 return boost::math::tools::epsilon<T>();
928 }
929};
930
931template <class T, class Policy>
932inline BOOST_MATH_CONSTEXPR T get_epsilon_imp(mpl::true_ const&) BOOST_MATH_NOEXCEPT(T)
933{
934#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
935 BOOST_STATIC_ASSERT( ::std::numeric_limits<T>::is_specialized);
936 BOOST_STATIC_ASSERT( ::std::numeric_limits<T>::radix == 2);
937#else
938 BOOST_ASSERT(::std::numeric_limits<T>::is_specialized);
939 BOOST_ASSERT(::std::numeric_limits<T>::radix == 2);
940#endif
941 typedef typename boost::math::policies::precision<T, Policy>::type p_t;
942 typedef mpl::bool_<p_t::value <= std::numeric_limits<boost::uintmax_t>::digits> is_small_int;
943 typedef mpl::bool_<p_t::value >= std::numeric_limits<T>::digits> is_default_value;
944 return series_factor_calc<T, p_t, is_small_int, is_default_value>::get();
945}
946
947template <class T, class Policy>
948inline BOOST_MATH_CONSTEXPR T get_epsilon_imp(mpl::false_ const&) BOOST_MATH_NOEXCEPT(T)
949{
950 return tools::epsilon<T>();
951}
952
953} // namespace detail
954
955template <class T, class Policy>
956inline BOOST_MATH_CONSTEXPR T get_epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) BOOST_MATH_NOEXCEPT(T)
957{
958 typedef mpl::bool_< (std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::radix == 2)) > tag_type;
959 return detail::get_epsilon_imp<T, Policy>(tag_type());
960}
961
962namespace detail{
963
964template <class A1,
965 class A2,
966 class A3,
967 class A4,
968 class A5,
969 class A6,
970 class A7,
971 class A8,
972 class A9,
973 class A10,
974 class A11>
975char test_is_policy(const policy<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11>*);
976double test_is_policy(...);
977
978template <class P>
979struct is_policy_imp
980{
981 BOOST_STATIC_CONSTANT(bool, value = (sizeof(::boost::math::policies::detail::test_is_policy(static_cast<P*>(0))) == 1));
982};
983
984}
985
986template <class P>
987struct is_policy : public mpl::bool_< ::boost::math::policies::detail::is_policy_imp<P>::value> {};
988
989//
990// Helper traits class for distribution error handling:
991//
992template <class Policy>
993struct constructor_error_check
994{
995 typedef typename Policy::domain_error_type domain_error_type;
996 typedef typename mpl::if_c<
997 (domain_error_type::value == throw_on_error) || (domain_error_type::value == user_error) || (domain_error_type::value == errno_on_error),
998 mpl::true_,
999 mpl::false_>::type type;
1000};
1001
1002template <class Policy>
1003struct method_error_check
1004{
1005 typedef typename Policy::domain_error_type domain_error_type;
1006 typedef typename mpl::if_c<
1007 (domain_error_type::value == throw_on_error) && (domain_error_type::value != user_error),
1008 mpl::false_,
1009 mpl::true_>::type type;
1010};
1011//
1012// Does the Policy ever throw on error?
1013//
1014template <class Policy>
1015struct is_noexcept_error_policy
1016{
1017 typedef typename Policy::domain_error_type t1;
1018 typedef typename Policy::pole_error_type t2;
1019 typedef typename Policy::overflow_error_type t3;
1020 typedef typename Policy::underflow_error_type t4;
1021 typedef typename Policy::denorm_error_type t5;
1022 typedef typename Policy::evaluation_error_type t6;
1023 typedef typename Policy::rounding_error_type t7;
1024 typedef typename Policy::indeterminate_result_error_type t8;
1025
1026 BOOST_STATIC_CONSTANT(bool, value =
1027 ((t1::value != throw_on_error) && (t1::value != user_error)
1028 && (t2::value != throw_on_error) && (t2::value != user_error)
1029 && (t3::value != throw_on_error) && (t3::value != user_error)
1030 && (t4::value != throw_on_error) && (t4::value != user_error)
1031 && (t5::value != throw_on_error) && (t5::value != user_error)
1032 && (t6::value != throw_on_error) && (t6::value != user_error)
1033 && (t7::value != throw_on_error) && (t7::value != user_error)
1034 && (t8::value != throw_on_error) && (t8::value != user_error)));
1035};
1036
1037}}} // namespaces
1038
1039#endif // BOOST_MATH_POLICY_HPP
1040
1041