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 
31 namespace boost{ namespace math{
32 
33 namespace tools{
34 
35 template <class T>
36 BOOST_MATH_CONSTEXPR int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) BOOST_NOEXCEPT;
37 template <class T>
38 BOOST_MATH_CONSTEXPR T epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) BOOST_MATH_NOEXCEPT(T);
39 
40 }
41 
42 namespace 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(BOOST_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 //
197 enum error_policy_type
198 {
199    throw_on_error = 0,
200    errno_on_error = 1,
201    ignore_error = 2,
202    user_error = 3
203 };
204 
205 BOOST_MATH_META_INT(error_policy_type, domain_error, BOOST_MATH_DOMAIN_ERROR_POLICY)
206 BOOST_MATH_META_INT(error_policy_type, pole_error, BOOST_MATH_POLE_ERROR_POLICY)
207 BOOST_MATH_META_INT(error_policy_type, overflow_error, BOOST_MATH_OVERFLOW_ERROR_POLICY)
208 BOOST_MATH_META_INT(error_policy_type, underflow_error, BOOST_MATH_UNDERFLOW_ERROR_POLICY)
209 BOOST_MATH_META_INT(error_policy_type, denorm_error, BOOST_MATH_DENORM_ERROR_POLICY)
210 BOOST_MATH_META_INT(error_policy_type, evaluation_error, BOOST_MATH_EVALUATION_ERROR_POLICY)
211 BOOST_MATH_META_INT(error_policy_type, rounding_error, BOOST_MATH_ROUNDING_ERROR_POLICY)
212 BOOST_MATH_META_INT(error_policy_type, indeterminate_result_error, BOOST_MATH_INDETERMINATE_RESULT_ERROR_POLICY)
213 
214 //
215 // Policy types for internal promotion:
216 //
217 BOOST_MATH_META_BOOL(promote_float, BOOST_MATH_PROMOTE_FLOAT_POLICY)
218 BOOST_MATH_META_BOOL(promote_double, BOOST_MATH_PROMOTE_DOUBLE_POLICY)
219 BOOST_MATH_META_BOOL(assert_undefined, BOOST_MATH_ASSERT_UNDEFINED_POLICY)
220 //
221 // Policy types for discrete quantiles:
222 //
223 enum 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 
233 BOOST_MATH_META_INT(discrete_quantile_policy_type, discrete_quantile, BOOST_MATH_DISCRETE_QUANTILE_POLICY)
234 //
235 // Precision:
236 //
237 BOOST_MATH_META_INT(int, digits10, BOOST_MATH_DIGITS10_POLICY)
238 BOOST_MATH_META_INT(int, digits2, 0)
239 //
240 // Iterations:
241 //
242 BOOST_MATH_META_INT(unsigned long, max_series_iterations, BOOST_MATH_MAX_SERIES_ITERATION_POLICY)
243 BOOST_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 
251 struct default_policy{};
252 
253 namespace detail{
254 //
255 // Trait to work out bits precision from digits10 and digits2:
256 //
257 template <class Digits10, class Digits2>
258 struct 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;
268 public:
269 #ifdef BOOST_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 
280 template <class A, class B, bool b>
281 struct select_result
282 {
283    typedef A type;
284 };
285 template <class A, class B>
286 struct select_result<A, B, false>
287 {
288    typedef typename mpl::deref<B>::type type;
289 };
290 
291 template <class Seq, class Pred, class DefaultType>
292 struct find_arg
293 {
294 private:
295    typedef typename mpl::find_if<Seq, Pred>::type iter;
296    typedef typename mpl::end<Seq>::type end_type;
297 public:
298    typedef typename select_result<
299       DefaultType, iter,
300       ::boost::is_same<iter, end_type>::value>::type type;
301 };
302 
303 double test_is_valid_arg(...);
304 double test_is_default_arg(...);
305 char test_is_valid_arg(const default_policy*);
306 char test_is_default_arg(const default_policy*);
307 
308 template <class T>
309 struct 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 
314 template <class T>
315 struct 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 
320 template <class T> struct is_valid_policy
321 : public boost::integral_constant<bool, ::boost::math::policies::detail::is_valid_policy_imp<T>::value>
322 {};
323 
324 template <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 
334 template <class Seq, class T, int N>
335 struct 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 
341 template <class Seq, class T>
342 struct 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 //
351 template <bool f, bool d>
352 struct default_args
353 {
354    typedef promote_float<false> arg1;
355    typedef promote_double<false> arg2;
356 };
357 
358 template <>
359 struct default_args<false, false>
360 {
361    typedef default_policy arg1;
362    typedef default_policy arg2;
363 };
364 
365 template <>
366 struct default_args<true, false>
367 {
368    typedef promote_float<false> arg1;
369    typedef default_policy arg2;
370 };
371 
372 template <>
373 struct default_args<false, true>
374 {
375    typedef promote_double<false> arg1;
376    typedef default_policy arg2;
377 };
378 
379 typedef default_args<BOOST_MATH_PROMOTE_FLOAT_POLICY, BOOST_MATH_PROMOTE_DOUBLE_POLICY>::arg1 forwarding_arg1;
380 typedef 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 //
387 template <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>
400 struct policy
401 {
402 private:
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 
424 public:
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;
433 private:
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;
439 public:
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 //
465 template <>
466 struct policy<default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy>
467 {
468 public:
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 
490 template <>
491 struct 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 {
493 public:
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 
515 template <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>
529 struct normalise
530 {
531 private:
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;
592 public:
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 //
611 template <>
612 struct 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 
628 template <>
629 struct 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 
make_policy()645 inline BOOST_MATH_CONSTEXPR policy<> make_policy() BOOST_NOEXCEPT
646 { return policy<>(); }
647 
648 template <class A1>
make_policy(const A1 &)649 inline 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 
655 template <class A1, class A2>
make_policy(const A1 &,const A2 &)656 inline 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 
662 template <class A1, class A2, class A3>
make_policy(const A1 &,const A2 &,const A3 &)663 inline 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 
669 template <class A1, class A2, class A3, class A4>
make_policy(const A1 &,const A2 &,const A3 &,const A4 &)670 inline 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 
676 template <class A1, class A2, class A3, class A4, class A5>
make_policy(const A1 &,const A2 &,const A3 &,const A4 &,const A5 &)677 inline 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 
683 template <class A1, class A2, class A3, class A4, class A5, class A6>
make_policy(const A1 &,const A2 &,const A3 &,const A4 &,const A5 &,const A6 &)684 inline 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 
690 template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
make_policy(const A1 &,const A2 &,const A3 &,const A4 &,const A5 &,const A6 &,const A7 &)691 inline 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 
697 template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
make_policy(const A1 &,const A2 &,const A3 &,const A4 &,const A5 &,const A6 &,const A7 &,const A8 &)698 inline 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 
704 template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
make_policy(const A1 &,const A2 &,const A3 &,const A4 &,const A5 &,const A6 &,const A7 &,const A8 &,const A9 &)705 inline 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 
711 template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
make_policy(const A1 &,const A2 &,const A3 &,const A4 &,const A5 &,const A6 &,const A7 &,const A8 &,const A9 &,const A10 &)712 inline 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 
718 template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10, class A11>
make_policy(const A1 &,const A2 &,const A3 &,const A4 &,const A5 &,const A6 &,const A7 &,const A8 &,const A9 &,const A10 &,const A11 &)719 inline 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 //
728 template <class Real, class Policy>
729 struct evaluation
730 {
731    typedef Real type;
732 };
733 
734 template <class Policy>
735 struct evaluation<float, Policy>
736 {
737    typedef typename mpl::if_<typename Policy::promote_float_type, double, float>::type type;
738 };
739 
740 template <class Policy>
741 struct 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 
748 template <class Real>
749 struct basic_digits : public boost::integral_constant<int, 0>{ };
750 template <>
751 struct basic_digits<float> : public boost::integral_constant<int, FLT_MANT_DIG>{ };
752 template <>
753 struct basic_digits<double> : public boost::integral_constant<int, DBL_MANT_DIG>{ };
754 template <>
755 struct basic_digits<long double> : public boost::integral_constant<int, LDBL_MANT_DIG>{ };
756 
757 template <class Real, class Policy>
758 struct 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 
777 template <class Policy>
778 struct precision<float, Policy>
779 {
780    typedef digits2<FLT_MANT_DIG> type;
781 };
782 template <class Policy>
783 struct precision<double, Policy>
784 {
785    typedef digits2<DBL_MANT_DIG> type;
786 };
787 template <class Policy>
788 struct precision<long double, Policy>
789 {
790    typedef digits2<LDBL_MANT_DIG> type;
791 };
792 
793 #else
794 
795 template <class Real, class Policy>
796 struct 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 BOOST_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 
837 template <class Policy>
838 struct precision<BOOST_MATH_FLOAT128_TYPE, Policy>
839 {
840    typedef boost::integral_constant<int, 113> type;
841 };
842 
843 #endif
844 
845 namespace detail{
846 
847 template <class T, class Policy>
digits_imp(boost::true_type const &)848 inline 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 
859 template <class T, class Policy>
digits_imp(boost::false_type const &)860 inline BOOST_MATH_CONSTEXPR int digits_imp(boost::false_type const&) BOOST_NOEXCEPT
861 {
862    return tools::digits<T>();
863 }
864 
865 } // namespace detail
866 
867 template <class T, class Policy>
digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE (T))868 inline 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 }
873 template <class T, class Policy>
digits_base10(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE (T))874 inline 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 
879 template <class Policy>
get_max_series_iterations()880 inline 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 
886 template <class Policy>
get_max_root_iterations()887 inline 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 
893 namespace detail{
894 
895 template <class T, class Digits, class Small, class Default>
896 struct series_factor_calc
897 {
getboost::math::policies::detail::series_factor_calc898    static T get() BOOST_MATH_NOEXCEPT(T)
899    {
900       return ldexp(T(1.0), 1 - Digits::value);
901    }
902 };
903 
904 template <class T, class Digits>
905 struct series_factor_calc<T, Digits, boost::true_type, boost::true_type>
906 {
getboost::math::policies::detail::series_factor_calc907    static BOOST_MATH_CONSTEXPR T get() BOOST_MATH_NOEXCEPT(T)
908    {
909       return boost::math::tools::epsilon<T>();
910    }
911 };
912 template <class T, class Digits>
913 struct series_factor_calc<T, Digits, boost::true_type, boost::false_type>
914 {
getboost::math::policies::detail::series_factor_calc915    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 };
920 template <class T, class Digits>
921 struct series_factor_calc<T, Digits, boost::false_type, boost::true_type>
922 {
getboost::math::policies::detail::series_factor_calc923    static BOOST_MATH_CONSTEXPR T get() BOOST_MATH_NOEXCEPT(T)
924    {
925       return boost::math::tools::epsilon<T>();
926    }
927 };
928 
929 template <class T, class Policy>
get_epsilon_imp(boost::true_type const &)930 inline 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 
945 template <class T, class Policy>
get_epsilon_imp(boost::false_type const &)946 inline 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 
953 template <class T, class Policy>
get_epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE (T))954 inline 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 
960 namespace detail{
961 
962 template <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>
973 char test_is_policy(const policy<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11>*);
974 double test_is_policy(...);
975 
976 template <class P>
977 struct 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 
984 template <class P>
985 struct 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 //
990 template <class Policy>
991 struct 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 
1000 template <class Policy>
1001 struct 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 //
1012 template <class Policy>
1013 struct 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