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