Home | History | Annotate | Download | only in policies
      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 int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T));
     37 template <class T>
     38 T epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T));
     39 
     40 }
     41 
     42 namespace 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 //
    176 enum error_policy_type
    177 {
    178    throw_on_error = 0,
    179    errno_on_error = 1,
    180    ignore_error = 2,
    181    user_error = 3
    182 };
    183 
    184 BOOST_MATH_META_INT(error_policy_type, domain_error, BOOST_MATH_DOMAIN_ERROR_POLICY)
    185 BOOST_MATH_META_INT(error_policy_type, pole_error, BOOST_MATH_POLE_ERROR_POLICY)
    186 BOOST_MATH_META_INT(error_policy_type, overflow_error, BOOST_MATH_OVERFLOW_ERROR_POLICY)
    187 BOOST_MATH_META_INT(error_policy_type, underflow_error, BOOST_MATH_UNDERFLOW_ERROR_POLICY)
    188 BOOST_MATH_META_INT(error_policy_type, denorm_error, BOOST_MATH_DENORM_ERROR_POLICY)
    189 BOOST_MATH_META_INT(error_policy_type, evaluation_error, BOOST_MATH_EVALUATION_ERROR_POLICY)
    190 BOOST_MATH_META_INT(error_policy_type, rounding_error, BOOST_MATH_ROUNDING_ERROR_POLICY)
    191 BOOST_MATH_META_INT(error_policy_type, indeterminate_result_error, BOOST_MATH_INDETERMINATE_RESULT_ERROR_POLICY)
    192 
    193 //
    194 // Policy types for internal promotion:
    195 //
    196 BOOST_MATH_META_BOOL(promote_float, BOOST_MATH_PROMOTE_FLOAT_POLICY)
    197 BOOST_MATH_META_BOOL(promote_double, BOOST_MATH_PROMOTE_DOUBLE_POLICY)
    198 BOOST_MATH_META_BOOL(assert_undefined, BOOST_MATH_ASSERT_UNDEFINED_POLICY)
    199 //
    200 // Policy types for discrete quantiles:
    201 //
    202 enum 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 
    212 BOOST_MATH_META_INT(discrete_quantile_policy_type, discrete_quantile, BOOST_MATH_DISCRETE_QUANTILE_POLICY)
    213 //
    214 // Precision:
    215 //
    216 BOOST_MATH_META_INT(int, digits10, BOOST_MATH_DIGITS10_POLICY)
    217 BOOST_MATH_META_INT(int, digits2, 0)
    218 //
    219 // Iterations:
    220 //
    221 BOOST_MATH_META_INT(unsigned long, max_series_iterations, BOOST_MATH_MAX_SERIES_ITERATION_POLICY)
    222 BOOST_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 
    230 struct default_policy{};
    231 
    232 namespace detail{
    233 //
    234 // Trait to work out bits precision from digits10 and digits2:
    235 //
    236 template <class Digits10, class Digits2>
    237 struct 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;
    247 public:
    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 
    259 template <class A, class B, bool b>
    260 struct select_result
    261 {
    262    typedef A type;
    263 };
    264 template <class A, class B>
    265 struct select_result<A, B, false>
    266 {
    267    typedef typename mpl::deref<B>::type type;
    268 };
    269 
    270 template <class Seq, class Pred, class DefaultType>
    271 struct find_arg
    272 {
    273 private:
    274    typedef typename mpl::find_if<Seq, Pred>::type iter;
    275    typedef typename mpl::end<Seq>::type end_type;
    276 public:
    277    typedef typename select_result<
    278       DefaultType, iter,
    279       ::boost::is_same<iter, end_type>::value>::type type;
    280 };
    281 
    282 double test_is_valid_arg(...);
    283 double test_is_default_arg(...);
    284 char test_is_valid_arg(const default_policy*);
    285 char test_is_default_arg(const default_policy*);
    286 
    287 template <class T>
    288 struct 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 
    293 template <class T>
    294 struct 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 
    299 template <class T> struct is_valid_policy
    300 : public mpl::bool_<
    301    ::boost::math::policies::detail::is_valid_policy_imp<T>::value>
    302 {};
    303 
    304 template <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 
    315 template <class Seq, class T, int N>
    316 struct 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 
    322 template <class Seq, class T>
    323 struct 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 //
    332 template <bool f, bool d>
    333 struct default_args
    334 {
    335    typedef promote_float<false> arg1;
    336    typedef promote_double<false> arg2;
    337 };
    338 
    339 template <>
    340 struct default_args<false, false>
    341 {
    342    typedef default_policy arg1;
    343    typedef default_policy arg2;
    344 };
    345 
    346 template <>
    347 struct default_args<true, false>
    348 {
    349    typedef promote_float<false> arg1;
    350    typedef default_policy arg2;
    351 };
    352 
    353 template <>
    354 struct default_args<false, true>
    355 {
    356    typedef promote_double<false> arg1;
    357    typedef default_policy arg2;
    358 };
    359 
    360 typedef default_args<BOOST_MATH_PROMOTE_FLOAT_POLICY, BOOST_MATH_PROMOTE_DOUBLE_POLICY>::arg1 forwarding_arg1;
    361 typedef 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 //
    368 template <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>
    381 struct policy
    382 {
    383 private:
    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 
    405 public:
    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;
    414 private:
    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;
    420 public:
    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 //
    446 template <>
    447 struct policy<default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy>
    448 {
    449 public:
    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 
    471 template <>
    472 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>
    473 {
    474 public:
    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 
    496 template <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>
    510 struct normalise
    511 {
    512 private:
    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;
    573 public:
    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 //
    592 template <>
    593 struct 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 
    609 template <>
    610 struct 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 
    626 inline policy<> make_policy()
    627 { return policy<>(); }
    628 
    629 template <class A1>
    630 inline 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 
    636 template <class A1, class A2>
    637 inline 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 
    643 template <class A1, class A2, class A3>
    644 inline 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 
    650 template <class A1, class A2, class A3, class A4>
    651 inline 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 
    657 template <class A1, class A2, class A3, class A4, class A5>
    658 inline 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 
    664 template <class A1, class A2, class A3, class A4, class A5, class A6>
    665 inline 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 
    671 template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
    672 inline 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 
    678 template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
    679 inline 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 
    685 template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
    686 inline 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 
    692 template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
    693 inline 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 
    699 template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10, class A11>
    700 inline 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 //
    709 template <class Real, class Policy>
    710 struct evaluation
    711 {
    712    typedef Real type;
    713 };
    714 
    715 template <class Policy>
    716 struct evaluation<float, Policy>
    717 {
    718    typedef typename mpl::if_<typename Policy::promote_float_type, double, float>::type type;
    719 };
    720 
    721 template <class Policy>
    722 struct 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 
    729 template <class Real>
    730 struct basic_digits : public mpl::int_<0>{ };
    731 template <>
    732 struct basic_digits<float> : public mpl::int_<FLT_MANT_DIG>{ };
    733 template <>
    734 struct basic_digits<double> : public mpl::int_<DBL_MANT_DIG>{ };
    735 template <>
    736 struct basic_digits<long double> : public mpl::int_<LDBL_MANT_DIG>{ };
    737 
    738 template <class Real, class Policy>
    739 struct 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 
    758 template <class Policy>
    759 struct precision<float, Policy>
    760 {
    761    typedef digits2<FLT_MANT_DIG> type;
    762 };
    763 template <class Policy>
    764 struct precision<double, Policy>
    765 {
    766    typedef digits2<DBL_MANT_DIG> type;
    767 };
    768 template <class Policy>
    769 struct precision<long double, Policy>
    770 {
    771    typedef digits2<LDBL_MANT_DIG> type;
    772 };
    773 
    774 #else
    775 
    776 template <class Real, class Policy>
    777 struct 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 
    816 namespace detail{
    817 
    818 template <class T, class Policy>
    819 inline 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 
    830 template <class T, class Policy>
    831 inline int digits_imp(mpl::false_ const&)
    832 {
    833    return tools::digits<T>();
    834 }
    835 
    836 } // namespace detail
    837 
    838 template <class T, class Policy>
    839 inline 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 
    845 template <class Policy>
    846 inline unsigned long get_max_series_iterations()
    847 {
    848    typedef typename Policy::max_series_iterations_type iter_type;
    849    return iter_type::value;
    850 }
    851 
    852 template <class Policy>
    853 inline unsigned long get_max_root_iterations()
    854 {
    855    typedef typename Policy::max_root_iterations_type iter_type;
    856    return iter_type::value;
    857 }
    858 
    859 namespace detail{
    860 
    861 template <class T, class Digits, class Small, class Default>
    862 struct series_factor_calc
    863 {
    864    static T get()
    865    {
    866       return ldexp(T(1.0), 1 - Digits::value);
    867    }
    868 };
    869 
    870 template <class T, class Digits>
    871 struct series_factor_calc<T, Digits, mpl::true_, mpl::true_>
    872 {
    873    static T get()
    874    {
    875       return boost::math::tools::epsilon<T>();
    876    }
    877 };
    878 template <class T, class Digits>
    879 struct 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 };
    887 template <class T, class Digits>
    888 struct 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 
    896 template <class T, class Policy>
    897 inline 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 
    912 template <class T, class Policy>
    913 inline T get_epsilon_imp(mpl::false_ const&)
    914 {
    915    return tools::epsilon<T>();
    916 }
    917 
    918 } // namespace detail
    919 
    920 template <class T, class Policy>
    921 inline 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 
    927 namespace detail{
    928 
    929 template <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>
    940 char test_is_policy(const policy<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11>*);
    941 double test_is_policy(...);
    942 
    943 template <class P>
    944 struct 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 
    951 template <class P>
    952 struct 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 //
    957 template <class Policy>
    958 struct 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 
    967 template <class Policy>
    968 struct 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