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 pdalboost{ 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(__BORLANDC__)
120 #define BOOST_MATH_META_INT(type, name, Default)\
121    template <type N = Default> struct name : public pdalboost::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 pdalboost::mpl::bool_< ::pdalboost::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 pdalboost::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 pdalboost::mpl::bool_< ::pdalboost::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 pdalboost::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( ::pdalboost::math::policies::detail::is_##name##_tester<T>::test(inst)) == 1);\
165    };\
166    }\
167    template <class T> struct is_##name : public pdalboost::mpl::bool_< ::pdalboost::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 pdalboost::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( ::pdalboost::math::policies::detail::is_##name##_tester<T>::test(inst)) == 1);\
187    };\
188    }\
189    template <class T> struct is_##name : public pdalboost::mpl::bool_< ::pdalboost::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 __BORLANDC__
270    typedef typename mpl::if_c<
271       (Digits2::value > ::pdalboost::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       ::pdalboost::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(::pdalboost::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(::pdalboost::math::policies::detail::test_is_default_arg(static_cast<T*>(0))) == 1);
318 };
319 
320 template <class T> struct is_valid_policy
321 : public mpl::bool_<
322    ::pdalboost::math::policies::detail::is_valid_policy_imp<T>::value>
323 {};
324 
325 template <class T> struct is_default_policy
326 : public mpl::bool_<
327    ::pdalboost::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 
336 template <class Seq, class T, int N>
337 struct 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 
343 template <class Seq, class T>
344 struct 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 //
353 template <bool f, bool d>
354 struct default_args
355 {
356    typedef promote_float<false> arg1;
357    typedef promote_double<false> arg2;
358 };
359 
360 template <>
361 struct default_args<false, false>
362 {
363    typedef default_policy arg1;
364    typedef default_policy arg2;
365 };
366 
367 template <>
368 struct default_args<true, false>
369 {
370    typedef promote_float<false> arg1;
371    typedef default_policy arg2;
372 };
373 
374 template <>
375 struct default_args<false, true>
376 {
377    typedef promote_double<false> arg1;
378    typedef default_policy arg2;
379 };
380 
381 typedef default_args<BOOST_MATH_PROMOTE_FLOAT_POLICY, BOOST_MATH_PROMOTE_DOUBLE_POLICY>::arg1 forwarding_arg1;
382 typedef 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 //
389 template <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>
402 struct policy
403 {
404 private:
405    //
406    // Validate all our arguments:
407    //
408    BOOST_STATIC_ASSERT(::pdalboost::math::policies::detail::is_valid_policy<A1>::value);
409    BOOST_STATIC_ASSERT(::pdalboost::math::policies::detail::is_valid_policy<A2>::value);
410    BOOST_STATIC_ASSERT(::pdalboost::math::policies::detail::is_valid_policy<A3>::value);
411    BOOST_STATIC_ASSERT(::pdalboost::math::policies::detail::is_valid_policy<A4>::value);
412    BOOST_STATIC_ASSERT(::pdalboost::math::policies::detail::is_valid_policy<A5>::value);
413    BOOST_STATIC_ASSERT(::pdalboost::math::policies::detail::is_valid_policy<A6>::value);
414    BOOST_STATIC_ASSERT(::pdalboost::math::policies::detail::is_valid_policy<A7>::value);
415    BOOST_STATIC_ASSERT(::pdalboost::math::policies::detail::is_valid_policy<A8>::value);
416    BOOST_STATIC_ASSERT(::pdalboost::math::policies::detail::is_valid_policy<A9>::value);
417    BOOST_STATIC_ASSERT(::pdalboost::math::policies::detail::is_valid_policy<A10>::value);
418    BOOST_STATIC_ASSERT(::pdalboost::math::policies::detail::is_valid_policy<A11>::value);
419    BOOST_STATIC_ASSERT(::pdalboost::math::policies::detail::is_valid_policy<A12>::value);
420    BOOST_STATIC_ASSERT(::pdalboost::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 
426 public:
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;
435 private:
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;
441 public:
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 //
467 template <>
468 struct policy<default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy>
469 {
470 public:
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 
492 template <>
493 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>
494 {
495 public:
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 
517 template <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>
531 struct normalise
532 {
533 private:
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 - ::pdalboost::mpl::size<reduced_list>::value)>::type result_type;
594 public:
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 //
613 template <>
614 struct 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 
630 template <>
631 struct 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 
make_policy()647 inline BOOST_MATH_CONSTEXPR policy<> make_policy() BOOST_NOEXCEPT
648 { return policy<>(); }
649 
650 template <class A1>
make_policy(const A1 &)651 inline 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 
657 template <class A1, class A2>
make_policy(const A1 &,const A2 &)658 inline 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 
664 template <class A1, class A2, class A3>
make_policy(const A1 &,const A2 &,const A3 &)665 inline 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 
671 template <class A1, class A2, class A3, class A4>
make_policy(const A1 &,const A2 &,const A3 &,const A4 &)672 inline 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 
678 template <class A1, class A2, class A3, class A4, class A5>
make_policy(const A1 &,const A2 &,const A3 &,const A4 &,const A5 &)679 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
680 {
681    typedef typename normalise<policy<>, A1, A2, A3, A4, A5>::type result_type;
682    return result_type();
683 }
684 
685 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 &)686 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
687 {
688    typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6>::type result_type;
689    return result_type();
690 }
691 
692 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 &)693 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
694 {
695    typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7>::type result_type;
696    return result_type();
697 }
698 
699 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 &)700 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
701 {
702    typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8>::type result_type;
703    return result_type();
704 }
705 
706 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 &)707 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
708 {
709    typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9>::type result_type;
710    return result_type();
711 }
712 
713 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 &)714 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
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 
720 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 &)721 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
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 //
730 template <class Real, class Policy>
731 struct evaluation
732 {
733    typedef Real type;
734 };
735 
736 template <class Policy>
737 struct evaluation<float, Policy>
738 {
739    typedef typename mpl::if_<typename Policy::promote_float_type, double, float>::type type;
740 };
741 
742 template <class Policy>
743 struct 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 
750 template <class Real>
751 struct basic_digits : public mpl::int_<0>{ };
752 template <>
753 struct basic_digits<float> : public mpl::int_<FLT_MANT_DIG>{ };
754 template <>
755 struct basic_digits<double> : public mpl::int_<DBL_MANT_DIG>{ };
756 template <>
757 struct basic_digits<long double> : public mpl::int_<LDBL_MANT_DIG>{ };
758 
759 template <class Real, class Policy>
760 struct 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 
779 template <class Policy>
780 struct precision<float, Policy>
781 {
782    typedef digits2<FLT_MANT_DIG> type;
783 };
784 template <class Policy>
785 struct precision<double, Policy>
786 {
787    typedef digits2<DBL_MANT_DIG> type;
788 };
789 template <class Policy>
790 struct precision<long double, Policy>
791 {
792    typedef digits2<LDBL_MANT_DIG> type;
793 };
794 
795 #else
796 
797 template <class Real, class Policy>
798 struct 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 
839 template <class Policy>
840 struct precision<BOOST_MATH_FLOAT128_TYPE, Policy>
841 {
842    typedef mpl::int_<113> type;
843 };
844 
845 #endif
846 
847 namespace detail{
848 
849 template <class T, class Policy>
digits_imp(mpl::true_ const &)850 inline 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 pdalboost::math::policies::precision<T, Policy>::type p_t;
858    return p_t::value;
859 }
860 
861 template <class T, class Policy>
digits_imp(mpl::false_ const &)862 inline BOOST_MATH_CONSTEXPR int digits_imp(mpl::false_ const&) BOOST_NOEXCEPT
863 {
864    return tools::digits<T>();
865 }
866 
867 } // namespace detail
868 
869 template <class T, class Policy>
digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE (T))870 inline 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 }
875 template <class T, class Policy>
digits_base10(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE (T))876 inline BOOST_MATH_CONSTEXPR int digits_base10(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) BOOST_NOEXCEPT
877 {
878    return pdalboost::math::policies::digits<T, Policy>() * 301 / 1000L;
879 }
880 
881 template <class Policy>
get_max_series_iterations()882 inline 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 
888 template <class Policy>
get_max_root_iterations()889 inline 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 
895 namespace detail{
896 
897 template <class T, class Digits, class Small, class Default>
898 struct series_factor_calc
899 {
getpdalboost::math::policies::detail::series_factor_calc900    static T get() BOOST_MATH_NOEXCEPT(T)
901    {
902       return ldexp(T(1.0), 1 - Digits::value);
903    }
904 };
905 
906 template <class T, class Digits>
907 struct series_factor_calc<T, Digits, mpl::true_, mpl::true_>
908 {
getpdalboost::math::policies::detail::series_factor_calc909    static BOOST_MATH_CONSTEXPR T get() BOOST_MATH_NOEXCEPT(T)
910    {
911       return pdalboost::math::tools::epsilon<T>();
912    }
913 };
914 template <class T, class Digits>
915 struct series_factor_calc<T, Digits, mpl::true_, mpl::false_>
916 {
917    BOOST_STATIC_CONSTANT(pdalboost::uintmax_t, v = static_cast<pdalboost::uintmax_t>(1u) << (Digits::value - 1));
918 
getpdalboost::math::policies::detail::series_factor_calc919    static BOOST_MATH_CONSTEXPR T get() BOOST_MATH_NOEXCEPT(T)
920    {
921       return 1 / static_cast<T>(v);
922    }
923 };
924 template <class T, class Digits>
925 struct series_factor_calc<T, Digits, mpl::false_, mpl::true_>
926 {
getpdalboost::math::policies::detail::series_factor_calc927    static BOOST_MATH_CONSTEXPR T get() BOOST_MATH_NOEXCEPT(T)
928    {
929       return pdalboost::math::tools::epsilon<T>();
930    }
931 };
932 
933 template <class T, class Policy>
get_epsilon_imp(mpl::true_ const &)934 inline BOOST_MATH_CONSTEXPR T get_epsilon_imp(mpl::true_ const&) BOOST_MATH_NOEXCEPT(T)
935 {
936 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
937    BOOST_STATIC_ASSERT( ::std::numeric_limits<T>::is_specialized);
938    BOOST_STATIC_ASSERT( ::std::numeric_limits<T>::radix == 2);
939 #else
940    BOOST_ASSERT(::std::numeric_limits<T>::is_specialized);
941    BOOST_ASSERT(::std::numeric_limits<T>::radix == 2);
942 #endif
943    typedef typename pdalboost::math::policies::precision<T, Policy>::type p_t;
944    typedef mpl::bool_<p_t::value <= std::numeric_limits<pdalboost::uintmax_t>::digits> is_small_int;
945    typedef mpl::bool_<p_t::value >= std::numeric_limits<T>::digits> is_default_value;
946    return series_factor_calc<T, p_t, is_small_int, is_default_value>::get();
947 }
948 
949 template <class T, class Policy>
get_epsilon_imp(mpl::false_ const &)950 inline BOOST_MATH_CONSTEXPR T get_epsilon_imp(mpl::false_ const&) BOOST_MATH_NOEXCEPT(T)
951 {
952    return tools::epsilon<T>();
953 }
954 
955 } // namespace detail
956 
957 template <class T, class Policy>
get_epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE (T))958 inline BOOST_MATH_CONSTEXPR T get_epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) BOOST_MATH_NOEXCEPT(T)
959 {
960    typedef mpl::bool_< (std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::radix == 2)) > tag_type;
961    return detail::get_epsilon_imp<T, Policy>(tag_type());
962 }
963 
964 namespace detail{
965 
966 template <class A1,
967           class A2,
968           class A3,
969           class A4,
970           class A5,
971           class A6,
972           class A7,
973           class A8,
974           class A9,
975           class A10,
976           class A11>
977 char test_is_policy(const policy<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11>*);
978 double test_is_policy(...);
979 
980 template <class P>
981 struct is_policy_imp
982 {
983    BOOST_STATIC_CONSTANT(bool, value = (sizeof(::pdalboost::math::policies::detail::test_is_policy(static_cast<P*>(0))) == 1));
984 };
985 
986 }
987 
988 template <class P>
989 struct is_policy : public mpl::bool_< ::pdalboost::math::policies::detail::is_policy_imp<P>::value> {};
990 
991 //
992 // Helper traits class for distribution error handling:
993 //
994 template <class Policy>
995 struct constructor_error_check
996 {
997    typedef typename Policy::domain_error_type domain_error_type;
998    typedef typename mpl::if_c<
999       (domain_error_type::value == throw_on_error) || (domain_error_type::value == user_error) || (domain_error_type::value == errno_on_error),
1000       mpl::true_,
1001       mpl::false_>::type type;
1002 };
1003 
1004 template <class Policy>
1005 struct method_error_check
1006 {
1007    typedef typename Policy::domain_error_type domain_error_type;
1008    typedef typename mpl::if_c<
1009       (domain_error_type::value == throw_on_error) && (domain_error_type::value != user_error),
1010       mpl::false_,
1011       mpl::true_>::type type;
1012 };
1013 //
1014 // Does the Policy ever throw on error?
1015 //
1016 template <class Policy>
1017 struct is_noexcept_error_policy
1018 {
1019    typedef typename Policy::domain_error_type               t1;
1020    typedef typename Policy::pole_error_type                 t2;
1021    typedef typename Policy::overflow_error_type             t3;
1022    typedef typename Policy::underflow_error_type            t4;
1023    typedef typename Policy::denorm_error_type               t5;
1024    typedef typename Policy::evaluation_error_type           t6;
1025    typedef typename Policy::rounding_error_type             t7;
1026    typedef typename Policy::indeterminate_result_error_type t8;
1027 
1028    BOOST_STATIC_CONSTANT(bool, value =
1029       ((t1::value != throw_on_error) && (t1::value != user_error)
1030       && (t2::value != throw_on_error) && (t2::value != user_error)
1031       && (t3::value != throw_on_error) && (t3::value != user_error)
1032       && (t4::value != throw_on_error) && (t4::value != user_error)
1033       && (t5::value != throw_on_error) && (t5::value != user_error)
1034       && (t6::value != throw_on_error) && (t6::value != user_error)
1035       && (t7::value != throw_on_error) && (t7::value != user_error)
1036       && (t8::value != throw_on_error) && (t8::value != user_error)));
1037 };
1038 
1039 }}} // namespaces
1040 
1041 #endif // BOOST_MATH_POLICY_HPP
1042 
1043