| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031 |
- // Copyright John Maddock 2007.
- // Copyright Matt Borland 2021.
- // Use, modification and distribution are subject to the
- // Boost Software License, Version 1.0. (See accompanying file
- // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- #ifndef BOOST_MATH_POLICY_HPP
- #define BOOST_MATH_POLICY_HPP
- #include <boost/math/tools/config.hpp>
- #include <boost/math/tools/mp.hpp>
- #include <boost/math/tools/numeric_limits.hpp>
- #include <boost/math/tools/type_traits.hpp>
- #include <boost/math/tools/cstdint.hpp>
- namespace boost{ namespace math{
- namespace mp = tools::meta_programming;
- namespace tools{
- template <class T>
- BOOST_MATH_GPU_ENABLED constexpr int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept;
- template <class T>
- BOOST_MATH_GPU_ENABLED constexpr T epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(boost::math::is_floating_point<T>::value);
- }
- namespace policies{
- //
- // Define macros for our default policies, if they're not defined already:
- //
- //
- // Generic support for GPUs
- //
- #ifdef BOOST_MATH_HAS_GPU_SUPPORT
- # ifndef BOOST_MATH_OVERFLOW_ERROR_POLICY
- # define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error
- # endif
- # ifndef BOOST_MATH_PROMOTE_DOUBLE_POLICY
- # define BOOST_MATH_PROMOTE_DOUBLE_POLICY false
- # endif
- # ifndef BOOST_MATH_DOMAIN_ERROR_POLICY
- # define BOOST_MATH_DOMAIN_ERROR_POLICY ignore_error
- # endif
- # ifndef BOOST_MATH_POLE_ERROR_POLICY
- # define BOOST_MATH_POLE_ERROR_POLICY ignore_error
- # endif
- # ifndef BOOST_MATH_EVALUATION_ERROR_POLICY
- # define BOOST_MATH_EVALUATION_ERROR_POLICY ignore_error
- # endif
- # ifndef BOOST_MATH_ROUNDING_ERROR_POLICY
- # define BOOST_MATH_ROUNDING_ERROR_POLICY ignore_error
- # endif
- #endif
- //
- // Special cases for exceptions disabled first:
- //
- #ifdef BOOST_MATH_NO_EXCEPTIONS
- # ifndef BOOST_MATH_DOMAIN_ERROR_POLICY
- # define BOOST_MATH_DOMAIN_ERROR_POLICY errno_on_error
- # endif
- # ifndef BOOST_MATH_POLE_ERROR_POLICY
- # define BOOST_MATH_POLE_ERROR_POLICY errno_on_error
- # endif
- # ifndef BOOST_MATH_OVERFLOW_ERROR_POLICY
- # define BOOST_MATH_OVERFLOW_ERROR_POLICY errno_on_error
- # endif
- # ifndef BOOST_MATH_EVALUATION_ERROR_POLICY
- # define BOOST_MATH_EVALUATION_ERROR_POLICY errno_on_error
- # endif
- # ifndef BOOST_MATH_ROUNDING_ERROR_POLICY
- # define BOOST_MATH_ROUNDING_ERROR_POLICY errno_on_error
- # endif
- #endif
- //
- // Then the regular cases:
- //
- #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_ROUNDING_ERROR_POLICY
- #define BOOST_MATH_ROUNDING_ERROR_POLICY throw_on_error
- #endif
- #ifndef BOOST_MATH_UNDERFLOW_ERROR_POLICY
- #define BOOST_MATH_UNDERFLOW_ERROR_POLICY ignore_error
- #endif
- #ifndef BOOST_MATH_DENORM_ERROR_POLICY
- #define BOOST_MATH_DENORM_ERROR_POLICY ignore_error
- #endif
- #ifndef BOOST_MATH_INDETERMINATE_RESULT_ERROR_POLICY
- #define BOOST_MATH_INDETERMINATE_RESULT_ERROR_POLICY ignore_error
- #endif
- #ifndef BOOST_MATH_DIGITS10_POLICY
- #define BOOST_MATH_DIGITS10_POLICY 0
- #endif
- #ifndef BOOST_MATH_PROMOTE_FLOAT_POLICY
- #define BOOST_MATH_PROMOTE_FLOAT_POLICY true
- #endif
- #ifndef BOOST_MATH_PROMOTE_DOUBLE_POLICY
- #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
- #define BOOST_MATH_PROMOTE_DOUBLE_POLICY false
- #else
- #define BOOST_MATH_PROMOTE_DOUBLE_POLICY true
- #endif
- #endif
- #ifndef BOOST_MATH_DISCRETE_QUANTILE_POLICY
- #define BOOST_MATH_DISCRETE_QUANTILE_POLICY integer_round_outwards
- #endif
- #ifndef BOOST_MATH_ASSERT_UNDEFINED_POLICY
- #define BOOST_MATH_ASSERT_UNDEFINED_POLICY true
- #endif
- #ifndef BOOST_MATH_MAX_SERIES_ITERATION_POLICY
- #define BOOST_MATH_MAX_SERIES_ITERATION_POLICY 1000000
- #endif
- #ifndef BOOST_MATH_MAX_ROOT_ITERATION_POLICY
- #define BOOST_MATH_MAX_ROOT_ITERATION_POLICY 200
- #endif
- #define BOOST_MATH_META_INT(Type, name, Default) \
- template <Type N = Default> \
- class name : public boost::math::integral_constant<Type, N> { }; \
- \
- namespace detail{ \
- template <Type N> \
- BOOST_MATH_GPU_ENABLED char test_is_valid_arg(const name<N>* = nullptr); \
- BOOST_MATH_GPU_ENABLED char test_is_default_arg(const name<Default>* = nullptr); \
- \
- template <typename T> \
- class is_##name##_imp \
- { \
- private: \
- template <Type N> \
- BOOST_MATH_GPU_ENABLED static char test(const name<N>* = nullptr); \
- BOOST_MATH_GPU_ENABLED static double test(...); \
- public: \
- static constexpr bool value = sizeof(test(static_cast<T*>(nullptr))) == sizeof(char); \
- }; \
- } \
- \
- template <typename T> \
- class is_##name \
- { \
- public: \
- static constexpr bool value = boost::math::policies::detail::is_##name##_imp<T>::value; \
- using type = boost::math::integral_constant<bool, value>; \
- };
- #define BOOST_MATH_META_BOOL(name, Default) \
- template <bool N = Default> \
- class name : public boost::math::integral_constant<bool, N>{}; \
- \
- namespace detail{ \
- template <bool N> \
- BOOST_MATH_GPU_ENABLED char test_is_valid_arg(const name<N>* = nullptr); \
- BOOST_MATH_GPU_ENABLED char test_is_default_arg(const name<Default>* = nullptr); \
- \
- template <typename T> \
- class is_##name##_imp \
- { \
- private: \
- template <bool N> \
- BOOST_MATH_GPU_ENABLED static char test(const name<N>* = nullptr); \
- BOOST_MATH_GPU_ENABLED static double test(...); \
- public: \
- static constexpr bool value = sizeof(test(static_cast<T*>(nullptr))) == sizeof(char); \
- }; \
- } \
- \
- template <typename T> \
- class is_##name \
- { \
- public: \
- static constexpr bool value = boost::math::policies::detail::is_##name##_imp<T>::value; \
- using type = boost::math::integral_constant<bool, value>; \
- };
- //
- // Begin by defining policy types for error handling:
- //
- enum error_policy_type
- {
- throw_on_error = 0,
- errno_on_error = 1,
- ignore_error = 2,
- user_error = 3
- };
- BOOST_MATH_META_INT(error_policy_type, domain_error, BOOST_MATH_DOMAIN_ERROR_POLICY)
- BOOST_MATH_META_INT(error_policy_type, pole_error, BOOST_MATH_POLE_ERROR_POLICY)
- BOOST_MATH_META_INT(error_policy_type, overflow_error, BOOST_MATH_OVERFLOW_ERROR_POLICY)
- BOOST_MATH_META_INT(error_policy_type, underflow_error, BOOST_MATH_UNDERFLOW_ERROR_POLICY)
- BOOST_MATH_META_INT(error_policy_type, denorm_error, BOOST_MATH_DENORM_ERROR_POLICY)
- BOOST_MATH_META_INT(error_policy_type, evaluation_error, BOOST_MATH_EVALUATION_ERROR_POLICY)
- BOOST_MATH_META_INT(error_policy_type, rounding_error, BOOST_MATH_ROUNDING_ERROR_POLICY)
- BOOST_MATH_META_INT(error_policy_type, indeterminate_result_error, BOOST_MATH_INDETERMINATE_RESULT_ERROR_POLICY)
- //
- // Policy types for internal promotion:
- //
- BOOST_MATH_META_BOOL(promote_float, BOOST_MATH_PROMOTE_FLOAT_POLICY)
- BOOST_MATH_META_BOOL(promote_double, BOOST_MATH_PROMOTE_DOUBLE_POLICY)
- BOOST_MATH_META_BOOL(assert_undefined, BOOST_MATH_ASSERT_UNDEFINED_POLICY)
- //
- // Policy types for discrete quantiles:
- //
- enum discrete_quantile_policy_type
- {
- real,
- integer_round_outwards,
- integer_round_inwards,
- integer_round_down,
- integer_round_up,
- integer_round_nearest
- };
- BOOST_MATH_META_INT(discrete_quantile_policy_type, discrete_quantile, BOOST_MATH_DISCRETE_QUANTILE_POLICY)
- //
- // Precision:
- //
- BOOST_MATH_META_INT(int, digits10, BOOST_MATH_DIGITS10_POLICY)
- BOOST_MATH_META_INT(int, digits2, 0)
- //
- // Iterations:
- //
- BOOST_MATH_META_INT(unsigned long, max_series_iterations, BOOST_MATH_MAX_SERIES_ITERATION_POLICY)
- BOOST_MATH_META_INT(unsigned long, max_root_iterations, BOOST_MATH_MAX_ROOT_ITERATION_POLICY)
- //
- // Define the names for each possible policy:
- //
- #define BOOST_MATH_PARAMETER(name)\
- BOOST_PARAMETER_TEMPLATE_KEYWORD(name##_name)\
- BOOST_PARAMETER_NAME(name##_name)
- struct default_policy{};
- namespace detail{
- //
- // Trait to work out bits precision from digits10 and digits2:
- //
- template <class Digits10, class Digits2>
- struct precision
- {
- //
- // Now work out the precision:
- //
- using digits2_type = typename boost::math::conditional<
- (Digits10::value == 0),
- digits2<0>,
- digits2<((Digits10::value + 1) * 1000L) / 301L>
- >::type;
- public:
- #ifdef BOOST_BORLANDC
- using type = typename boost::math::conditional<
- (Digits2::value > ::boost::math::policies::detail::precision<Digits10,Digits2>::digits2_type::value),
- Digits2, digits2_type>::type;
- #else
- using type = typename boost::math::conditional<
- (Digits2::value > digits2_type::value),
- Digits2, digits2_type>::type;
- #endif
- };
- BOOST_MATH_GPU_ENABLED double test_is_valid_arg(...);
- BOOST_MATH_GPU_ENABLED double test_is_default_arg(...);
- BOOST_MATH_GPU_ENABLED char test_is_valid_arg(const default_policy*);
- BOOST_MATH_GPU_ENABLED char test_is_default_arg(const default_policy*);
- template <typename T>
- class is_valid_policy_imp
- {
- public:
- static constexpr bool value = sizeof(boost::math::policies::detail::test_is_valid_arg(static_cast<T*>(nullptr))) == sizeof(char);
- };
- template <typename T>
- class is_valid_policy
- {
- public:
- static constexpr bool value = boost::math::policies::detail::is_valid_policy_imp<T>::value;
- };
- template <typename T>
- class is_default_policy_imp
- {
- public:
- static constexpr bool value = sizeof(boost::math::policies::detail::test_is_default_arg(static_cast<T*>(nullptr))) == sizeof(char);
- };
- template <typename T>
- class is_default_policy
- {
- public:
- static constexpr bool value = boost::math::policies::detail::is_default_policy_imp<T>::value;
- using type = boost::math::integral_constant<bool, value>;
- template <typename U>
- struct apply
- {
- using type = is_default_policy<U>;
- };
- };
- template <class Seq, class T, boost::math::size_t N>
- struct append_N
- {
- using type = typename append_N<mp::mp_push_back<Seq, T>, T, N-1>::type;
- };
- template <class Seq, class T>
- struct append_N<Seq, T, 0>
- {
- using type = Seq;
- };
- //
- // Traits class to work out what template parameters our default
- // policy<> class will have when modified for forwarding:
- //
- template <bool f, bool d>
- struct default_args
- {
- typedef promote_float<false> arg1;
- typedef promote_double<false> arg2;
- };
- template <>
- struct default_args<false, false>
- {
- typedef default_policy arg1;
- typedef default_policy arg2;
- };
- template <>
- struct default_args<true, false>
- {
- typedef promote_float<false> arg1;
- typedef default_policy arg2;
- };
- template <>
- struct default_args<false, true>
- {
- typedef promote_double<false> arg1;
- typedef default_policy arg2;
- };
- typedef default_args<BOOST_MATH_PROMOTE_FLOAT_POLICY, BOOST_MATH_PROMOTE_DOUBLE_POLICY>::arg1 forwarding_arg1;
- typedef default_args<BOOST_MATH_PROMOTE_FLOAT_POLICY, BOOST_MATH_PROMOTE_DOUBLE_POLICY>::arg2 forwarding_arg2;
- } // detail
- //
- // Now define the policy type with enough arguments to handle all
- // the policies:
- //
- template <typename A1 = default_policy,
- typename A2 = default_policy,
- typename A3 = default_policy,
- typename A4 = default_policy,
- typename A5 = default_policy,
- typename A6 = default_policy,
- typename A7 = default_policy,
- typename A8 = default_policy,
- typename A9 = default_policy,
- typename A10 = default_policy,
- typename A11 = default_policy,
- typename A12 = default_policy,
- typename A13 = default_policy>
- class policy
- {
- private:
- //
- // Validate all our arguments:
- //
- static_assert(::boost::math::policies::detail::is_valid_policy<A1>::value, "::boost::math::policies::detail::is_valid_policy<A1>::value");
- static_assert(::boost::math::policies::detail::is_valid_policy<A2>::value, "::boost::math::policies::detail::is_valid_policy<A2>::value");
- static_assert(::boost::math::policies::detail::is_valid_policy<A3>::value, "::boost::math::policies::detail::is_valid_policy<A3>::value");
- static_assert(::boost::math::policies::detail::is_valid_policy<A4>::value, "::boost::math::policies::detail::is_valid_policy<A4>::value");
- static_assert(::boost::math::policies::detail::is_valid_policy<A5>::value, "::boost::math::policies::detail::is_valid_policy<A5>::value");
- static_assert(::boost::math::policies::detail::is_valid_policy<A6>::value, "::boost::math::policies::detail::is_valid_policy<A6>::value");
- static_assert(::boost::math::policies::detail::is_valid_policy<A7>::value, "::boost::math::policies::detail::is_valid_policy<A7>::value");
- static_assert(::boost::math::policies::detail::is_valid_policy<A8>::value, "::boost::math::policies::detail::is_valid_policy<A8>::value");
- static_assert(::boost::math::policies::detail::is_valid_policy<A9>::value, "::boost::math::policies::detail::is_valid_policy<A9>::value");
- static_assert(::boost::math::policies::detail::is_valid_policy<A10>::value, "::boost::math::policies::detail::is_valid_policy<A10>::value");
- static_assert(::boost::math::policies::detail::is_valid_policy<A11>::value, "::boost::math::policies::detail::is_valid_policy<A11>::value");
- static_assert(::boost::math::policies::detail::is_valid_policy<A12>::value, "::boost::math::policies::detail::is_valid_policy<A12>::value");
- static_assert(::boost::math::policies::detail::is_valid_policy<A13>::value, "::boost::math::policies::detail::is_valid_policy<A13>::value");
- //
- // Typelist of the arguments:
- //
- using arg_list = mp::mp_list<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13>;
- static constexpr boost::math::size_t arg_list_size = mp::mp_size<arg_list>::value;
- template<typename A, typename B, bool b>
- struct pick_arg
- {
- using type = A;
- };
- template<typename A, typename B>
- struct pick_arg<A, B, false>
- {
- using type = mp::mp_at<arg_list, B>;
- };
- template<typename Fn, typename Default>
- class arg_type
- {
- private:
- using index = mp::mp_find_if_q<arg_list, Fn>;
- static constexpr bool end = (index::value >= arg_list_size);
- public:
- using type = typename pick_arg<Default, index, end>::type;
- };
- // Work out the base 2 and 10 precisions to calculate the public precision_type:
- using digits10_type = typename arg_type<mp::mp_quote_trait<is_digits10>, digits10<>>::type;
- using bits_precision_type = typename arg_type<mp::mp_quote_trait<is_digits2>, digits2<>>::type;
- public:
- // Error Types:
- using domain_error_type = typename arg_type<mp::mp_quote_trait<is_domain_error>, domain_error<>>::type;
- using pole_error_type = typename arg_type<mp::mp_quote_trait<is_pole_error>, pole_error<>>::type;
- using overflow_error_type = typename arg_type<mp::mp_quote_trait<is_overflow_error>, overflow_error<>>::type;
- using underflow_error_type = typename arg_type<mp::mp_quote_trait<is_underflow_error>, underflow_error<>>::type;
- using denorm_error_type = typename arg_type<mp::mp_quote_trait<is_denorm_error>, denorm_error<>>::type;
- using evaluation_error_type = typename arg_type<mp::mp_quote_trait<is_evaluation_error>, evaluation_error<>>::type;
- using rounding_error_type = typename arg_type<mp::mp_quote_trait<is_rounding_error>, rounding_error<>>::type;
- using indeterminate_result_error_type = typename arg_type<mp::mp_quote_trait<is_indeterminate_result_error>, indeterminate_result_error<>>::type;
- // Precision:
- using precision_type = typename detail::precision<digits10_type, bits_precision_type>::type;
- // Internal promotion:
- using promote_float_type = typename arg_type<mp::mp_quote_trait<is_promote_float>, promote_float<>>::type;
- using promote_double_type = typename arg_type<mp::mp_quote_trait<is_promote_double>, promote_double<>>::type;
- // Discrete quantiles:
- using discrete_quantile_type = typename arg_type<mp::mp_quote_trait<is_discrete_quantile>, discrete_quantile<>>::type;
- // Mathematically undefined properties:
- using assert_undefined_type = typename arg_type<mp::mp_quote_trait<is_assert_undefined>, assert_undefined<>>::type;
- // Max iterations:
- using max_series_iterations_type = typename arg_type<mp::mp_quote_trait<is_max_series_iterations>, max_series_iterations<>>::type;
- using max_root_iterations_type = typename arg_type<mp::mp_quote_trait<is_max_root_iterations>, max_root_iterations<>>::type;
- };
- //
- // These full specializations are defined to reduce the amount of
- // template instantiations that have to take place when using the default
- // policies, they have quite a large impact on compile times:
- //
- template <>
- class policy<default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy>
- {
- public:
- using domain_error_type = domain_error<>;
- using pole_error_type = pole_error<>;
- using overflow_error_type = overflow_error<>;
- using underflow_error_type = underflow_error<>;
- using denorm_error_type = denorm_error<>;
- using evaluation_error_type = evaluation_error<>;
- using rounding_error_type = rounding_error<>;
- using indeterminate_result_error_type = indeterminate_result_error<>;
- #if BOOST_MATH_DIGITS10_POLICY == 0
- using precision_type = digits2<>;
- #else
- using precision_type = detail::precision<digits10<>, digits2<>>::type;
- #endif
- using promote_float_type = promote_float<>;
- using promote_double_type = promote_double<>;
- using discrete_quantile_type = discrete_quantile<>;
- using assert_undefined_type = assert_undefined<>;
- using max_series_iterations_type = max_series_iterations<>;
- using max_root_iterations_type = max_root_iterations<>;
- };
- template <>
- 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>
- {
- public:
- using domain_error_type = domain_error<>;
- using pole_error_type = pole_error<>;
- using overflow_error_type = overflow_error<>;
- using underflow_error_type = underflow_error<>;
- using denorm_error_type = denorm_error<>;
- using evaluation_error_type = evaluation_error<>;
- using rounding_error_type = rounding_error<>;
- using indeterminate_result_error_type = indeterminate_result_error<>;
- #if BOOST_MATH_DIGITS10_POLICY == 0
- using precision_type = digits2<>;
- #else
- using precision_type = detail::precision<digits10<>, digits2<>>::type;
- #endif
- using promote_float_type = promote_float<false>;
- using promote_double_type = promote_double<false>;
- using discrete_quantile_type = discrete_quantile<>;
- using assert_undefined_type = assert_undefined<>;
- using max_series_iterations_type = max_series_iterations<>;
- using max_root_iterations_type = max_root_iterations<>;
- };
- template <typename Policy,
- typename A1 = default_policy,
- typename A2 = default_policy,
- typename A3 = default_policy,
- typename A4 = default_policy,
- typename A5 = default_policy,
- typename A6 = default_policy,
- typename A7 = default_policy,
- typename A8 = default_policy,
- typename A9 = default_policy,
- typename A10 = default_policy,
- typename A11 = default_policy,
- typename A12 = default_policy,
- typename A13 = default_policy>
- class normalise
- {
- private:
- using arg_list = mp::mp_list<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13>;
- static constexpr boost::math::size_t arg_list_size = mp::mp_size<arg_list>::value;
- template<typename A, typename B, bool b>
- struct pick_arg
- {
- using type = A;
- };
- template<typename A, typename B>
- struct pick_arg<A, B, false>
- {
- using type = mp::mp_at<arg_list, B>;
- };
- template<typename Fn, typename Default>
- class arg_type
- {
- private:
- using index = mp::mp_find_if_q<arg_list, Fn>;
- static constexpr bool end = (index::value >= arg_list_size);
- public:
- using type = typename pick_arg<Default, index, end>::type;
- };
- // Error types:
- using domain_error_type = typename arg_type<mp::mp_quote_trait<is_domain_error>, typename Policy::domain_error_type>::type;
- using pole_error_type = typename arg_type<mp::mp_quote_trait<is_pole_error>, typename Policy::pole_error_type>::type;
- using overflow_error_type = typename arg_type<mp::mp_quote_trait<is_overflow_error>, typename Policy::overflow_error_type>::type;
- using underflow_error_type = typename arg_type<mp::mp_quote_trait<is_underflow_error>, typename Policy::underflow_error_type>::type;
- using denorm_error_type = typename arg_type<mp::mp_quote_trait<is_denorm_error>, typename Policy::denorm_error_type>::type;
- using evaluation_error_type = typename arg_type<mp::mp_quote_trait<is_evaluation_error>, typename Policy::evaluation_error_type>::type;
- using rounding_error_type = typename arg_type<mp::mp_quote_trait<is_rounding_error>, typename Policy::rounding_error_type>::type;
- using indeterminate_result_error_type = typename arg_type<mp::mp_quote_trait<is_indeterminate_result_error>, typename Policy::indeterminate_result_error_type>::type;
- // Precision:
- using digits10_type = typename arg_type<mp::mp_quote_trait<is_digits10>, digits10<>>::type;
- using bits_precision_type = typename arg_type<mp::mp_quote_trait<is_digits2>, typename Policy::precision_type>::type;
- using precision_type = typename detail::precision<digits10_type, bits_precision_type>::type;
- // Internal promotion:
- using promote_float_type = typename arg_type<mp::mp_quote_trait<is_promote_float>, typename Policy::promote_float_type>::type;
- using promote_double_type = typename arg_type<mp::mp_quote_trait<is_promote_double>, typename Policy::promote_double_type>::type;
- // Discrete quantiles:
- using discrete_quantile_type = typename arg_type<mp::mp_quote_trait<is_discrete_quantile>, typename Policy::discrete_quantile_type>::type;
- // Mathematically undefined properties:
- using assert_undefined_type = typename arg_type<mp::mp_quote_trait<is_assert_undefined>, typename Policy::assert_undefined_type>::type;
- // Max iterations:
- using max_series_iterations_type = typename arg_type<mp::mp_quote_trait<is_max_series_iterations>, typename Policy::max_series_iterations_type>::type;
- using max_root_iterations_type = typename arg_type<mp::mp_quote_trait<is_max_root_iterations>, typename Policy::max_root_iterations_type>::type;
- // Define a typelist of the policies:
- using result_list = mp::mp_list<
- domain_error_type,
- pole_error_type,
- overflow_error_type,
- underflow_error_type,
- denorm_error_type,
- evaluation_error_type,
- rounding_error_type,
- indeterminate_result_error_type,
- precision_type,
- promote_float_type,
- promote_double_type,
- discrete_quantile_type,
- assert_undefined_type,
- max_series_iterations_type,
- max_root_iterations_type>;
- // Remove all the policies that are the same as the default:
- using fn = mp::mp_quote_trait<detail::is_default_policy>;
- using reduced_list = mp::mp_remove_if_q<result_list, fn>;
- // Pad out the list with defaults:
- using result_type = typename detail::append_N<reduced_list, default_policy, (14UL - mp::mp_size<reduced_list>::value)>::type;
- public:
- using type = policy<
- mp::mp_at_c<result_type, 0>,
- mp::mp_at_c<result_type, 1>,
- mp::mp_at_c<result_type, 2>,
- mp::mp_at_c<result_type, 3>,
- mp::mp_at_c<result_type, 4>,
- mp::mp_at_c<result_type, 5>,
- mp::mp_at_c<result_type, 6>,
- mp::mp_at_c<result_type, 7>,
- mp::mp_at_c<result_type, 8>,
- mp::mp_at_c<result_type, 9>,
- mp::mp_at_c<result_type, 10>,
- mp::mp_at_c<result_type, 11>,
- mp::mp_at_c<result_type, 12>
- >;
- };
- // Full specialisation to speed up compilation of the common case:
- template <>
- struct normalise<policy<>,
- promote_float<false>,
- promote_double<false>,
- discrete_quantile<>,
- assert_undefined<>,
- default_policy,
- default_policy,
- default_policy,
- default_policy,
- default_policy,
- default_policy,
- default_policy>
- {
- using type = policy<detail::forwarding_arg1, detail::forwarding_arg2>;
- };
- template <>
- struct normalise<policy<detail::forwarding_arg1, detail::forwarding_arg2>,
- promote_float<false>,
- promote_double<false>,
- discrete_quantile<>,
- assert_undefined<>,
- default_policy,
- default_policy,
- default_policy,
- default_policy,
- default_policy,
- default_policy,
- default_policy>
- {
- using type = policy<detail::forwarding_arg1, detail::forwarding_arg2>;
- };
- BOOST_MATH_GPU_ENABLED constexpr policy<> make_policy() noexcept
- { return {}; }
- template <class A1>
- BOOST_MATH_GPU_ENABLED constexpr typename normalise<policy<>, A1>::type make_policy(const A1&) noexcept
- {
- typedef typename normalise<policy<>, A1>::type result_type;
- return result_type();
- }
- template <class A1, class A2>
- BOOST_MATH_GPU_ENABLED constexpr typename normalise<policy<>, A1, A2>::type make_policy(const A1&, const A2&) noexcept
- {
- typedef typename normalise<policy<>, A1, A2>::type result_type;
- return result_type();
- }
- template <class A1, class A2, class A3>
- BOOST_MATH_GPU_ENABLED constexpr typename normalise<policy<>, A1, A2, A3>::type make_policy(const A1&, const A2&, const A3&) noexcept
- {
- typedef typename normalise<policy<>, A1, A2, A3>::type result_type;
- return result_type();
- }
- template <class A1, class A2, class A3, class A4>
- BOOST_MATH_GPU_ENABLED constexpr typename normalise<policy<>, A1, A2, A3, A4>::type make_policy(const A1&, const A2&, const A3&, const A4&) noexcept
- {
- typedef typename normalise<policy<>, A1, A2, A3, A4>::type result_type;
- return result_type();
- }
- template <class A1, class A2, class A3, class A4, class A5>
- BOOST_MATH_GPU_ENABLED constexpr typename normalise<policy<>, A1, A2, A3, A4, A5>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&) noexcept
- {
- typedef typename normalise<policy<>, A1, A2, A3, A4, A5>::type result_type;
- return result_type();
- }
- template <class A1, class A2, class A3, class A4, class A5, class A6>
- BOOST_MATH_GPU_ENABLED constexpr typename normalise<policy<>, A1, A2, A3, A4, A5, A6>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&) noexcept
- {
- typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6>::type result_type;
- return result_type();
- }
- template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
- BOOST_MATH_GPU_ENABLED constexpr typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&) noexcept
- {
- typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7>::type result_type;
- return result_type();
- }
- template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
- BOOST_MATH_GPU_ENABLED constexpr typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&) noexcept
- {
- typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8>::type result_type;
- return result_type();
- }
- template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
- BOOST_MATH_GPU_ENABLED constexpr typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&, const A9&) noexcept
- {
- typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9>::type result_type;
- return result_type();
- }
- template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
- BOOST_MATH_GPU_ENABLED constexpr typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&, const A9&, const A10&) noexcept
- {
- typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>::type result_type;
- return result_type();
- }
- template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10, class A11>
- BOOST_MATH_GPU_ENABLED constexpr typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&, const A9&, const A10&, const A11&) noexcept
- {
- typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11>::type result_type;
- return result_type();
- }
- //
- // Traits class to handle internal promotion:
- //
- template <class Real, class Policy>
- struct evaluation
- {
- typedef Real type;
- };
- template <class Policy>
- struct evaluation<float, Policy>
- {
- using type = typename boost::math::conditional<Policy::promote_float_type::value, double, float>::type;
- };
- template <class Policy>
- struct evaluation<double, Policy>
- {
- using type = typename boost::math::conditional<Policy::promote_double_type::value, long double, double>::type;
- };
- template <class Real, class Policy>
- struct precision
- {
- static_assert((boost::math::numeric_limits<Real>::radix == 2) || ((boost::math::numeric_limits<Real>::is_specialized == 0) || (boost::math::numeric_limits<Real>::digits == 0)),
- "(boost::math::numeric_limits<Real>::radix == 2) || ((boost::math::numeric_limits<Real>::is_specialized == 0) || (boost::math::numeric_limits<Real>::digits == 0))");
- #ifndef BOOST_BORLANDC
- using precision_type = typename Policy::precision_type;
- using type = typename boost::math::conditional<
- ((boost::math::numeric_limits<Real>::is_specialized == 0) || (boost::math::numeric_limits<Real>::digits == 0)),
- // Possibly unknown precision:
- precision_type,
- typename boost::math::conditional<
- ((boost::math::numeric_limits<Real>::digits <= precision_type::value)
- || (Policy::precision_type::value <= 0)),
- // Default case, full precision for RealType:
- digits2< boost::math::numeric_limits<Real>::digits>,
- // User customised precision:
- precision_type
- >::type
- >::type;
- #else
- using precision_type = typename Policy::precision_type;
- using digits_t = boost::math::integral_constant<int, boost::math::numeric_limits<Real>::digits>;
- using spec_t = boost::math::integral_constant<bool, boost::math::numeric_limits<Real>::is_specialized>;
- using type = typename boost::math::conditional<
- (spec_t::value == true boost::math::true_type || digits_t::value == 0),
- // Possibly unknown precision:
- precision_type,
- typename boost::math::conditional<
- (digits_t::value <= precision_type::value || precision_type::value <= 0),
- // Default case, full precision for RealType:
- digits2< boost::math::numeric_limits<Real>::digits>,
- // User customised precision:
- precision_type
- >::type
- >::type;
- #endif
- };
- #ifdef BOOST_MATH_USE_FLOAT128
- template <class Policy>
- struct precision<BOOST_MATH_FLOAT128_TYPE, Policy>
- {
- typedef boost::math::integral_constant<int, 113> type;
- };
- #endif
- namespace detail{
- template <class T, class Policy>
- BOOST_MATH_GPU_ENABLED constexpr int digits_imp(boost::math::true_type const&) noexcept
- {
- static_assert( boost::math::numeric_limits<T>::is_specialized, "boost::math::numeric_limits<T>::is_specialized");
- typedef typename boost::math::policies::precision<T, Policy>::type p_t;
- return p_t::value;
- }
- template <class T, class Policy>
- BOOST_MATH_GPU_ENABLED constexpr int digits_imp(boost::math::false_type const&) noexcept
- {
- return tools::digits<T>();
- }
- } // namespace detail
- template <class T, class Policy>
- BOOST_MATH_GPU_ENABLED constexpr int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept
- {
- typedef boost::math::integral_constant<bool, boost::math::numeric_limits<T>::is_specialized > tag_type;
- return detail::digits_imp<T, Policy>(tag_type());
- }
- template <class T, class Policy>
- BOOST_MATH_GPU_ENABLED constexpr int digits_base10(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept
- {
- return boost::math::policies::digits<T, Policy>() * 301 / 1000L;
- }
- template <class Policy>
- BOOST_MATH_GPU_ENABLED constexpr unsigned long get_max_series_iterations() noexcept
- {
- typedef typename Policy::max_series_iterations_type iter_type;
- return iter_type::value;
- }
- template <class Policy>
- BOOST_MATH_GPU_ENABLED constexpr unsigned long get_max_root_iterations() noexcept
- {
- typedef typename Policy::max_root_iterations_type iter_type;
- return iter_type::value;
- }
- namespace detail{
- template <class T, class Digits, class Small, class Default>
- struct series_factor_calc
- {
- BOOST_MATH_GPU_ENABLED static T get() noexcept(boost::math::is_floating_point<T>::value)
- {
- return ldexp(T(1.0), 1 - Digits::value);
- }
- };
- template <class T, class Digits>
- struct series_factor_calc<T, Digits, boost::math::true_type, boost::math::true_type>
- {
- BOOST_MATH_GPU_ENABLED static constexpr T get() noexcept(boost::math::is_floating_point<T>::value)
- {
- return boost::math::tools::epsilon<T>();
- }
- };
- template <class T, class Digits>
- struct series_factor_calc<T, Digits, boost::math::true_type, boost::math::false_type>
- {
- BOOST_MATH_GPU_ENABLED static constexpr T get() noexcept(boost::math::is_floating_point<T>::value)
- {
- return 1 / static_cast<T>(static_cast<boost::math::uintmax_t>(1u) << (Digits::value - 1));
- }
- };
- template <class T, class Digits>
- struct series_factor_calc<T, Digits, boost::math::false_type, boost::math::true_type>
- {
- BOOST_MATH_GPU_ENABLED static constexpr T get() noexcept(boost::math::is_floating_point<T>::value)
- {
- return boost::math::tools::epsilon<T>();
- }
- };
- template <class T, class Policy>
- BOOST_MATH_GPU_ENABLED constexpr T get_epsilon_imp(boost::math::true_type const&) noexcept(boost::math::is_floating_point<T>::value)
- {
- static_assert(boost::math::numeric_limits<T>::is_specialized, "boost::math::numeric_limits<T>::is_specialized");
- static_assert(boost::math::numeric_limits<T>::radix == 2, "boost::math::numeric_limits<T>::radix == 2");
- typedef typename boost::math::policies::precision<T, Policy>::type p_t;
- typedef boost::math::integral_constant<bool, p_t::value <= boost::math::numeric_limits<boost::math::uintmax_t>::digits> is_small_int;
- typedef boost::math::integral_constant<bool, p_t::value >= boost::math::numeric_limits<T>::digits> is_default_value;
- return series_factor_calc<T, p_t, is_small_int, is_default_value>::get();
- }
- template <class T, class Policy>
- BOOST_MATH_GPU_ENABLED constexpr T get_epsilon_imp(boost::math::false_type const&) noexcept(boost::math::is_floating_point<T>::value)
- {
- return tools::epsilon<T>();
- }
- } // namespace detail
- template <class T, class Policy>
- BOOST_MATH_GPU_ENABLED constexpr T get_epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(boost::math::is_floating_point<T>::value)
- {
- typedef boost::math::integral_constant<bool, (boost::math::numeric_limits<T>::is_specialized && (boost::math::numeric_limits<T>::radix == 2)) > tag_type;
- return detail::get_epsilon_imp<T, Policy>(tag_type());
- }
- namespace detail{
- template <class A1,
- class A2,
- class A3,
- class A4,
- class A5,
- class A6,
- class A7,
- class A8,
- class A9,
- class A10,
- class A11>
- BOOST_MATH_GPU_ENABLED char test_is_policy(const policy<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11>*);
- BOOST_MATH_GPU_ENABLED double test_is_policy(...);
- template <typename P>
- class is_policy_imp
- {
- public:
- static constexpr bool value = (sizeof(detail::test_is_policy(static_cast<boost::math::remove_reference_t<boost::math::remove_cv_t<P>>*>(nullptr))) == sizeof(char));
- };
- }
- template <typename P>
- class is_policy
- {
- public:
- static constexpr bool value = boost::math::policies::detail::is_policy_imp<P>::value;
- using type = boost::math::integral_constant<bool, value>;
- };
- template <typename T>
- BOOST_MATH_INLINE_CONSTEXPR bool is_policy_v = is_policy<T>::value;
- //
- // Helper traits class for distribution error handling:
- //
- template <class Policy>
- struct constructor_error_check
- {
- using domain_error_type = typename Policy::domain_error_type;
- using type = typename boost::math::conditional<
- (domain_error_type::value == throw_on_error) || (domain_error_type::value == user_error) || (domain_error_type::value == errno_on_error),
- boost::math::true_type,
- boost::math::false_type>::type;
- };
- template <class Policy>
- struct method_error_check
- {
- using domain_error_type = typename Policy::domain_error_type;
- using type = typename boost::math::conditional<
- (domain_error_type::value == throw_on_error),
- boost::math::false_type,
- boost::math::true_type>::type;
- };
- //
- // Does the Policy ever throw on error?
- //
- template <class Policy>
- struct is_noexcept_error_policy
- {
- typedef typename Policy::domain_error_type t1;
- typedef typename Policy::pole_error_type t2;
- typedef typename Policy::overflow_error_type t3;
- typedef typename Policy::underflow_error_type t4;
- typedef typename Policy::denorm_error_type t5;
- typedef typename Policy::evaluation_error_type t6;
- typedef typename Policy::rounding_error_type t7;
- typedef typename Policy::indeterminate_result_error_type t8;
- static constexpr bool value =
- ((t1::value != throw_on_error) && (t1::value != user_error)
- && (t2::value != throw_on_error) && (t2::value != user_error)
- && (t3::value != throw_on_error) && (t3::value != user_error)
- && (t4::value != throw_on_error) && (t4::value != user_error)
- && (t5::value != throw_on_error) && (t5::value != user_error)
- && (t6::value != throw_on_error) && (t6::value != user_error)
- && (t7::value != throw_on_error) && (t7::value != user_error)
- && (t8::value != throw_on_error) && (t8::value != user_error));
- };
- // Generate a forwarding policy to stop further promotion from occurring
- // For example if a special function for float promotes to double, we don't want the next
- // function in the call chain to then promote to long double
- template <typename Policy>
- struct make_forwarding_policy
- {
- using type =
- typename policies::normalise<
- Policy,
- policies::promote_float<false>,
- policies::promote_double<false>,
- policies::discrete_quantile<>,
- policies::assert_undefined<>
- >::type;
- };
- template <typename Policy>
- using make_forwarding_policy_t = typename make_forwarding_policy<Policy>::type;
- }}} // namespaces
- #endif // BOOST_MATH_POLICY_HPP
|