#ifndef BOOST_MATH_POLICY_HPP #define BOOST_MATH_POLICY_HPP #define BOOST_PARAMETER_MAX_ARITY 15 #include #include #include namespace boost{ namespace math{ namespace policy{ // // Define macros for our default policies, if they're not defined already: // #ifndef BOOST_MATH_DOMAIN_ERROR_POLICY #define BOOST_MATH_DOMAIN_ERROR_POLICY throw_on_error #endif #ifndef BOOST_MATH_POLE_ERROR_POLICY #define BOOST_MATH_POLE_ERROR_POLICY throw_on_error #endif #ifndef BOOST_MATH_OVERFLOW_ERROR_POLICY #define BOOST_MATH_OVERFLOW_ERROR_POLICY throw_on_error #endif #ifndef BOOST_MATH_EVALUATION_ERROR_POLICY #define BOOST_MATH_EVALUATION_ERROR_POLICY throw_on_error #endif #ifndef BOOST_MATH_UNDERFLOW_ERROR_POLICY #define BOOST_MATH_UNDERFLOW_ERROR_POLICY ignor_error #endif #ifndef BOOST_MATH_DENORM_ERROR_POLICY #define BOOST_MATH_DENORM_ERROR_POLICY ignor_error #endif #ifndef BOOST_MATH_DIGITS10_POLICY #define BOOST_MATH_DIGITS10_POLICY -1 #endif #ifndef BOOST_MATH_PROMOTE_FLOAT_POLICY #define BOOST_MATH_PROMOTE_FLOAT_POLICY true #endif #ifndef BOOST_MATH_PROMOTE_DOUBLE_POLICY #define BOOST_MATH_PROMOTE_DOUBLE_POLICY true #endif #ifndef BOOST_MATH_DISCRETE_QUANTILE_POLICY #define BOOST_MATH_DISCRETE_QUANTILE_POLICY integer_outside #endif #if !defined(__BORLANDC__) #define BOOST_MATH_META_INT(type, name)\ template struct name : public boost::mpl::int_{};\ namespace detail{\ template struct is_##name##_imp\ {\ template static char test(const name&);\ static double test(...);\ BOOST_STATIC_CONSTANT(bool, value = sizeof(test(T())) == 1);\ };\ }\ template struct is_##name : public boost::mpl::bool_::value>{}; #define BOOST_MATH_META_BOOL(name)\ template struct name : public boost::mpl::bool_{};\ namespace detail{\ template struct is_##name##_imp\ {\ template static char test(const name&);\ static double test(...);\ BOOST_STATIC_CONSTANT(bool, value = sizeof(test(T())) == 1);\ };\ }\ template struct is_##name : public boost::mpl::bool_::value>{}; #else #define BOOST_MATH_META_INT(Type, name)\ template struct name : public boost::mpl::int_{};\ namespace detail{\ template struct is_##name##_tester\ {\ template static char test(const name&);\ static double test(...);\ };\ template struct is_##name##_imp\ {\ static T inst;\ BOOST_STATIC_CONSTANT(bool, value = sizeof(detail::is_##name##_tester::test(inst)) == 1);\ };\ }\ template struct is_##name : public boost::mpl::bool_::value>\ {\ template struct apply{ typedef is_##name type; };\ }; #define BOOST_MATH_META_BOOL(name)\ template struct name : public boost::mpl::bool_{};\ namespace detail{\ template struct is_##name##_tester\ {\ template static char test(const name&);\ static double test(...);\ };\ template struct is_##name##_imp\ {\ static T inst;\ BOOST_STATIC_CONSTANT(bool, value = sizeof(detail::is_##name##_tester::test(inst)) == 1);\ };\ }\ template struct is_##name : public boost::mpl::bool_::value>\ {\ template struct apply{ typedef is_##name type; };\ }; #endif // // Begin by defining policy types for error handling: // enum error_policy_type { throw_on_error = 0, errno_on_error = 1, ignor_error = 2, user_error = 3 }; BOOST_MATH_META_INT(error_policy_type, domain_error) BOOST_MATH_META_INT(error_policy_type, pole_error) BOOST_MATH_META_INT(error_policy_type, overflow_error) BOOST_MATH_META_INT(error_policy_type, underflow_error) BOOST_MATH_META_INT(error_policy_type, denorm_error) BOOST_MATH_META_INT(error_policy_type, evaluation_error) // // Policy types for internal promotion: // BOOST_MATH_META_BOOL(promote_float); BOOST_MATH_META_BOOL(promote_double); // // Policy types for discrete quantiles: // enum discrete_quantile_policy_type { real, integer_outside, integer_inside, integer_below, integer_above }; BOOST_MATH_META_INT(discrete_quantile_policy_type, discrete_quantile); // // Precision: // BOOST_MATH_META_INT(int, digits10); BOOST_MATH_META_INT(int, digits2); // // Define the names for each possible policy: // #define BOOST_MATH_PARAMETER(name)\ BOOST_PARAMETER_TEMPLATE_KEYWORD(name##_name)\ BOOST_PARAMETER_NAME(name##_name) // // Error handlers: // BOOST_MATH_PARAMETER(domain_error) BOOST_MATH_PARAMETER(pole_error) BOOST_MATH_PARAMETER(overflow_error) BOOST_MATH_PARAMETER(underflow_error) BOOST_MATH_PARAMETER(denorm_error) BOOST_MATH_PARAMETER(evaluation_error) // // Precision: // BOOST_MATH_PARAMETER(digits10) BOOST_MATH_PARAMETER(digits2) // // Internal promotion: // BOOST_MATH_PARAMETER(promote_float) BOOST_MATH_PARAMETER(promote_double) // // Discrete quantile handling: // BOOST_MATH_PARAMETER(discrete_quantile) namespace detail{ // // Trait to work out bits precision from digits10 and digits2: // template struct precision { // // Now work out the precision: // typedef digits2<((Digits10::value + 1) * 1000L) / 301L> digits2_type; public: #ifdef __BORLANDC__ typedef typename mpl::if_c< (Digits2::value > ::boost::math::policy::detail::precision::digits2_type::value), Digits2, digits2_type>::type type; #else typedef typename mpl::if_c< (Digits2::value > digits2_type::value), Digits2, digits2_type>::type type; #endif }; } // // Define template signature complete with error checking of types: // using boost::mpl::_; typedef parameter::parameters< parameter::optional, is_domain_error > , parameter::optional, is_pole_error > , parameter::optional, is_overflow_error > , parameter::optional, is_underflow_error > , parameter::optional, is_denorm_error > , parameter::optional, is_evaluation_error > , parameter::optional, is_digits10 > , parameter::optional, is_digits2 > , parameter::optional, is_promote_float > , parameter::optional, is_promote_double > , parameter::optional, is_discrete_quantile > > policy_signature; // // Now define the policy type with enough arguments to handle all // the policies: // template struct policy { typedef policy_signature::bind bound_type; typedef typename bound_type::type args; typedef typename boost::parameter::binding< args, tag::domain_error_name, domain_error >::type domain_error_type; typedef typename boost::parameter::binding< args, tag::pole_error_name, pole_error >::type pole_error_type; typedef typename boost::parameter::binding< args, tag::overflow_error_name, overflow_error >::type overflow_error_type; typedef typename boost::parameter::binding< args, tag::underflow_error_name, underflow_error >::type underflow_error_type; typedef typename boost::parameter::binding< args, tag::denorm_error_name, denorm_error >::type denorm_error_type; typedef typename boost::parameter::binding< args, tag::evaluation_error_name, evaluation_error >::type evaluation_error_type; private: // // Now work out the precision: // typedef typename boost::parameter::binding< args, tag::digits10_name, digits10 >::type digits10_type; typedef typename boost::parameter::binding< args, tag::digits2_name, digits2<-1> >::type bits_precision_type; public: typedef typename detail::precision::type precision_type; // // Internal promotion: // typedef typename boost::parameter::binding< args, tag::promote_float_name, mpl::bool_ >::type float_promote_type; typedef typename boost::parameter::binding< args, tag::promote_double_name, mpl::bool_ >::type double_promote_type; // // Discrete quantiles: // typedef typename boost::parameter::binding< args, tag::discrete_quantile_name, discrete_quantile >::type discrete_quantile_type; }; template struct make_policy_result { private: typedef typename boost::parameter::value_type< args, tag::domain_error_name, domain_error >::type domain_error_type; typedef typename boost::parameter::value_type< args, tag::pole_error_name, pole_error >::type pole_error_type; typedef typename boost::parameter::value_type< args, tag::overflow_error_name, overflow_error >::type overflow_error_type; typedef typename boost::parameter::value_type< args, tag::underflow_error_name, underflow_error >::type underflow_error_type; typedef typename boost::parameter::value_type< args, tag::denorm_error_name, denorm_error >::type denorm_error_type; typedef typename boost::parameter::value_type< args, tag::evaluation_error_name, evaluation_error >::type evaluation_error_type; // // Now work out the precision: // typedef typename boost::parameter::value_type< args, tag::digits10_name, digits10 >::type digits10_type; typedef typename boost::parameter::value_type< args, tag::digits2_name, digits2<-1> >::type bits_precision_type; typedef typename detail::precision::type precision_type; // // Internal promotion: // typedef typename boost::parameter::value_type< args, tag::promote_float_name, promote_float >::type float_promote_type; typedef typename boost::parameter::value_type< args, tag::promote_double_name, promote_double >::type double_promote_type; // // Discrete quantiles: // typedef typename boost::parameter::value_type< args, tag::discrete_quantile_name, discrete_quantile >::type discrete_quantile_type; public: typedef policy< domain_error_type, pole_error_type, overflow_error_type, underflow_error_type, denorm_error_type, evaluation_error_type, precision_type, float_promote_type, double_promote_type, discrete_quantile_type > type; }; BOOST_PARAMETER_FUNCTION( // 1. parenthesized return type: (typename make_policy_result::type), // 2. name of the function template: make_policy, // 3. namespace of tag types: tag, // All parameters are deduced based on their type: (deduced // optional parameters, with defaults: (optional (domain_error_name, *(is_domain_error), domain_error()) (pole_error_name, *(is_pole_error), pole_error()) (overflow_error_name, *(is_overflow_error), overflow_error()) (underflow_error_name, *(is_underflow_error), underflow_error()) (denorm_error_name, *(is_denorm_error), denorm_error()) (evaluation_error_name, *(is_evaluation_error), evaluation_error()) (digits10_name, *(is_digits10), digits10()) (digits2_name, *(is_digits2), digits2<-1>()) (promote_float_name, *(is_promote_float), promote_float()) (promote_double_name, *(is_promote_double), promote_double()) (discrete_quantile_name, *(is_discrete_quantile), discrete_quantile()) ) ) ) { return typename make_policy_result::type(); } // // Define a functor that normalises a policy object, and also // merges it with whatever additional properties we wish to // override. We use this to reduce code bloat by ensuring that // two policy objects with the same policies installed, will // end up as the same type internally no matter how they were // created. Also lets us change some values: for example if // promotion has already occured once, we don't want to allow it // a second time. // typedef parameter::parameters< parameter::optional, is_domain_error > , parameter::optional, is_pole_error > , parameter::optional, is_overflow_error > , parameter::optional, is_underflow_error > , parameter::optional, is_denorm_error > , parameter::optional, is_evaluation_error > , parameter::optional, is_digits10 > , parameter::optional, is_digits2 > , parameter::optional, is_promote_float > , parameter::optional, is_promote_double > , parameter::optional, is_discrete_quantile > > normalise_signature; template struct normalise { private: typedef typename normalise_signature::bind::type args; typedef typename boost::parameter::binding< args, tag::domain_error_name, typename Policy::domain_error_type>::type domain_error_type; typedef typename boost::parameter::binding< args, tag::pole_error_name, typename Policy::pole_error_type>::type pole_error_type; typedef typename boost::parameter::binding< args, tag::overflow_error_name, typename Policy::overflow_error_type>::type overflow_error_type; typedef typename boost::parameter::binding< args, tag::underflow_error_name, typename Policy::underflow_error_type>::type underflow_error_type; typedef typename boost::parameter::binding< args, tag::denorm_error_name, typename Policy::denorm_error_type>::type denorm_error_type; typedef typename boost::parameter::binding< args, tag::evaluation_error_name, typename Policy::evaluation_error_type>::type evaluation_error_type; // // Now work out the precision: // typedef typename boost::parameter::binding< args, tag::digits10_name, digits10<-1> >::type digits10_type; typedef typename boost::parameter::binding< args, tag::digits2_name, typename Policy::precision_type>::type bits_precision_type; typedef typename detail::precision::type precision_type; // // Internal promotion: // typedef typename boost::parameter::binding< args, tag::promote_float_name, typename Policy::promote_float_type >::type float_promote_type; typedef typename boost::parameter::binding< args, tag::promote_double_name, typename Policy::promote_double_type>::type double_promote_type; // // Discrete quantiles: // typedef typename boost::parameter::binding< args, tag::discrete_quantile_name, typename Policy::discrete_quantile_type>::type discrete_quantile_type; public: typedef policy< domain_error_type, pole_error_type, overflow_error_type, underflow_error_type, denorm_error_type, evaluation_error_type, precision_type, float_promote_type, double_promote_type, discrete_quantile_type > type; }; }}} // namespaces #endif // BOOST_MATH_POLICY_HPP