1010 lines · plain
1// Copyright John Maddock 2007.2// Copyright Matt Borland 2021.3// Use, modification and distribution are subject to the4// Boost Software License, Version 1.0. (See accompanying file5// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)6 7#ifndef BOOST_MATH_POLICY_HPP8#define BOOST_MATH_POLICY_HPP9 10#include <boost/math/tools/config.hpp>11#include <boost/math/tools/mp.hpp>12#include <boost/math/tools/numeric_limits.hpp>13#include <boost/math/tools/type_traits.hpp>14#include <boost/math/tools/cstdint.hpp>15 16namespace boost{ namespace math{17 18namespace mp = tools::meta_programming;19 20namespace tools{21 22template <class T>23BOOST_MATH_GPU_ENABLED constexpr int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept;24template <class T>25BOOST_MATH_GPU_ENABLED constexpr T epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(boost::math::is_floating_point<T>::value);26 27}28 29namespace policies{30 31//32// Define macros for our default policies, if they're not defined already:33//34 35 36//37// Generic support for GPUs38//39#ifdef BOOST_MATH_HAS_GPU_SUPPORT40# ifndef BOOST_MATH_OVERFLOW_ERROR_POLICY41# define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error42# endif43# ifndef BOOST_MATH_PROMOTE_DOUBLE_POLICY44# define BOOST_MATH_PROMOTE_DOUBLE_POLICY false45# endif46# ifndef BOOST_MATH_DOMAIN_ERROR_POLICY47# define BOOST_MATH_DOMAIN_ERROR_POLICY ignore_error48# endif49# ifndef BOOST_MATH_POLE_ERROR_POLICY50# define BOOST_MATH_POLE_ERROR_POLICY ignore_error51# endif52# ifndef BOOST_MATH_EVALUATION_ERROR_POLICY53# define BOOST_MATH_EVALUATION_ERROR_POLICY ignore_error54# endif55# ifndef BOOST_MATH_ROUNDING_ERROR_POLICY56# define BOOST_MATH_ROUNDING_ERROR_POLICY ignore_error57# endif58#endif59 60//61// Special cases for exceptions disabled first:62//63#ifdef BOOST_MATH_NO_EXCEPTIONS64# ifndef BOOST_MATH_DOMAIN_ERROR_POLICY65# define BOOST_MATH_DOMAIN_ERROR_POLICY errno_on_error66# endif67# ifndef BOOST_MATH_POLE_ERROR_POLICY68# define BOOST_MATH_POLE_ERROR_POLICY errno_on_error69# endif70# ifndef BOOST_MATH_OVERFLOW_ERROR_POLICY71# define BOOST_MATH_OVERFLOW_ERROR_POLICY errno_on_error72# endif73# ifndef BOOST_MATH_EVALUATION_ERROR_POLICY74# define BOOST_MATH_EVALUATION_ERROR_POLICY errno_on_error75# endif76# ifndef BOOST_MATH_ROUNDING_ERROR_POLICY77# define BOOST_MATH_ROUNDING_ERROR_POLICY errno_on_error78# endif79#endif80//81// Then the regular cases:82//83#ifndef BOOST_MATH_DOMAIN_ERROR_POLICY84#define BOOST_MATH_DOMAIN_ERROR_POLICY throw_on_error85#endif86#ifndef BOOST_MATH_POLE_ERROR_POLICY87#define BOOST_MATH_POLE_ERROR_POLICY throw_on_error88#endif89#ifndef BOOST_MATH_OVERFLOW_ERROR_POLICY90#define BOOST_MATH_OVERFLOW_ERROR_POLICY throw_on_error91#endif92#ifndef BOOST_MATH_EVALUATION_ERROR_POLICY93#define BOOST_MATH_EVALUATION_ERROR_POLICY throw_on_error94#endif95#ifndef BOOST_MATH_ROUNDING_ERROR_POLICY96#define BOOST_MATH_ROUNDING_ERROR_POLICY throw_on_error97#endif98#ifndef BOOST_MATH_UNDERFLOW_ERROR_POLICY99#define BOOST_MATH_UNDERFLOW_ERROR_POLICY ignore_error100#endif101#ifndef BOOST_MATH_DENORM_ERROR_POLICY102#define BOOST_MATH_DENORM_ERROR_POLICY ignore_error103#endif104#ifndef BOOST_MATH_INDETERMINATE_RESULT_ERROR_POLICY105#define BOOST_MATH_INDETERMINATE_RESULT_ERROR_POLICY ignore_error106#endif107#ifndef BOOST_MATH_DIGITS10_POLICY108#define BOOST_MATH_DIGITS10_POLICY 0109#endif110#ifndef BOOST_MATH_PROMOTE_FLOAT_POLICY111#define BOOST_MATH_PROMOTE_FLOAT_POLICY true112#endif113#ifndef BOOST_MATH_PROMOTE_DOUBLE_POLICY114#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS115#define BOOST_MATH_PROMOTE_DOUBLE_POLICY false116#else117#define BOOST_MATH_PROMOTE_DOUBLE_POLICY true118#endif119#endif120#ifndef BOOST_MATH_DISCRETE_QUANTILE_POLICY121#define BOOST_MATH_DISCRETE_QUANTILE_POLICY integer_round_outwards122#endif123#ifndef BOOST_MATH_ASSERT_UNDEFINED_POLICY124#define BOOST_MATH_ASSERT_UNDEFINED_POLICY true125#endif126#ifndef BOOST_MATH_MAX_SERIES_ITERATION_POLICY127#define BOOST_MATH_MAX_SERIES_ITERATION_POLICY 1000000128#endif129#ifndef BOOST_MATH_MAX_ROOT_ITERATION_POLICY130#define BOOST_MATH_MAX_ROOT_ITERATION_POLICY 200131#endif132 133#define BOOST_MATH_META_INT(Type, name, Default) \134 template <Type N = Default> \135 class name : public boost::math::integral_constant<Type, N> { }; \136 \137 namespace detail{ \138 template <Type N> \139 BOOST_MATH_GPU_ENABLED char test_is_valid_arg(const name<N>* = nullptr); \140 BOOST_MATH_GPU_ENABLED char test_is_default_arg(const name<Default>* = nullptr); \141 \142 template <typename T> \143 class is_##name##_imp \144 { \145 private: \146 template <Type N> \147 BOOST_MATH_GPU_ENABLED static char test(const name<N>* = nullptr); \148 BOOST_MATH_GPU_ENABLED static double test(...); \149 public: \150 static constexpr bool value = sizeof(test(static_cast<T*>(nullptr))) == sizeof(char); \151 }; \152 } \153 \154 template <typename T> \155 class is_##name \156 { \157 public: \158 static constexpr bool value = boost::math::policies::detail::is_##name##_imp<T>::value; \159 using type = boost::math::integral_constant<bool, value>; \160 };161 162#define BOOST_MATH_META_BOOL(name, Default) \163 template <bool N = Default> \164 class name : public boost::math::integral_constant<bool, N>{}; \165 \166 namespace detail{ \167 template <bool N> \168 BOOST_MATH_GPU_ENABLED char test_is_valid_arg(const name<N>* = nullptr); \169 BOOST_MATH_GPU_ENABLED char test_is_default_arg(const name<Default>* = nullptr); \170 \171 template <typename T> \172 class is_##name##_imp \173 { \174 private: \175 template <bool N> \176 BOOST_MATH_GPU_ENABLED static char test(const name<N>* = nullptr); \177 BOOST_MATH_GPU_ENABLED static double test(...); \178 public: \179 static constexpr bool value = sizeof(test(static_cast<T*>(nullptr))) == sizeof(char); \180 }; \181 } \182 \183 template <typename T> \184 class is_##name \185 { \186 public: \187 static constexpr bool value = boost::math::policies::detail::is_##name##_imp<T>::value; \188 using type = boost::math::integral_constant<bool, value>; \189 };190 191//192// Begin by defining policy types for error handling:193//194enum error_policy_type195{196 throw_on_error = 0,197 errno_on_error = 1,198 ignore_error = 2,199 user_error = 3200};201 202BOOST_MATH_META_INT(error_policy_type, domain_error, BOOST_MATH_DOMAIN_ERROR_POLICY)203BOOST_MATH_META_INT(error_policy_type, pole_error, BOOST_MATH_POLE_ERROR_POLICY)204BOOST_MATH_META_INT(error_policy_type, overflow_error, BOOST_MATH_OVERFLOW_ERROR_POLICY)205BOOST_MATH_META_INT(error_policy_type, underflow_error, BOOST_MATH_UNDERFLOW_ERROR_POLICY)206BOOST_MATH_META_INT(error_policy_type, denorm_error, BOOST_MATH_DENORM_ERROR_POLICY)207BOOST_MATH_META_INT(error_policy_type, evaluation_error, BOOST_MATH_EVALUATION_ERROR_POLICY)208BOOST_MATH_META_INT(error_policy_type, rounding_error, BOOST_MATH_ROUNDING_ERROR_POLICY)209BOOST_MATH_META_INT(error_policy_type, indeterminate_result_error, BOOST_MATH_INDETERMINATE_RESULT_ERROR_POLICY)210 211//212// Policy types for internal promotion:213//214BOOST_MATH_META_BOOL(promote_float, BOOST_MATH_PROMOTE_FLOAT_POLICY)215BOOST_MATH_META_BOOL(promote_double, BOOST_MATH_PROMOTE_DOUBLE_POLICY)216BOOST_MATH_META_BOOL(assert_undefined, BOOST_MATH_ASSERT_UNDEFINED_POLICY)217//218// Policy types for discrete quantiles:219//220enum discrete_quantile_policy_type221{222 real,223 integer_round_outwards,224 integer_round_inwards,225 integer_round_down,226 integer_round_up,227 integer_round_nearest228};229 230BOOST_MATH_META_INT(discrete_quantile_policy_type, discrete_quantile, BOOST_MATH_DISCRETE_QUANTILE_POLICY)231//232// Precision:233//234BOOST_MATH_META_INT(int, digits10, BOOST_MATH_DIGITS10_POLICY)235BOOST_MATH_META_INT(int, digits2, 0)236//237// Iterations:238//239BOOST_MATH_META_INT(unsigned long, max_series_iterations, BOOST_MATH_MAX_SERIES_ITERATION_POLICY)240BOOST_MATH_META_INT(unsigned long, max_root_iterations, BOOST_MATH_MAX_ROOT_ITERATION_POLICY)241//242// Define the names for each possible policy:243//244#define BOOST_MATH_PARAMETER(name)\245 BOOST_PARAMETER_TEMPLATE_KEYWORD(name##_name)\246 BOOST_PARAMETER_NAME(name##_name)247 248struct default_policy{};249 250namespace detail{251//252// Trait to work out bits precision from digits10 and digits2:253//254template <class Digits10, class Digits2>255struct precision256{257 //258 // Now work out the precision:259 //260 using digits2_type = typename boost::math::conditional<261 (Digits10::value == 0),262 digits2<0>,263 digits2<((Digits10::value + 1) * 1000L) / 301L>264 >::type;265public:266#ifdef BOOST_BORLANDC267 using type = typename boost::math::conditional<268 (Digits2::value > ::boost::math::policies::detail::precision<Digits10,Digits2>::digits2_type::value),269 Digits2, digits2_type>::type;270#else271 using type = typename boost::math::conditional<272 (Digits2::value > digits2_type::value),273 Digits2, digits2_type>::type;274#endif275};276 277BOOST_MATH_GPU_ENABLED double test_is_valid_arg(...);278BOOST_MATH_GPU_ENABLED double test_is_default_arg(...);279BOOST_MATH_GPU_ENABLED char test_is_valid_arg(const default_policy*);280BOOST_MATH_GPU_ENABLED char test_is_default_arg(const default_policy*);281 282template <typename T>283class is_valid_policy_imp284{285public:286 static constexpr bool value = sizeof(boost::math::policies::detail::test_is_valid_arg(static_cast<T*>(nullptr))) == sizeof(char);287};288 289template <typename T>290class is_valid_policy291{292public:293 static constexpr bool value = boost::math::policies::detail::is_valid_policy_imp<T>::value;294};295 296template <typename T>297class is_default_policy_imp298{299public:300 static constexpr bool value = sizeof(boost::math::policies::detail::test_is_default_arg(static_cast<T*>(nullptr))) == sizeof(char);301};302 303template <typename T>304class is_default_policy305{306public:307 static constexpr bool value = boost::math::policies::detail::is_default_policy_imp<T>::value;308 using type = boost::math::integral_constant<bool, value>;309 310 template <typename U>311 struct apply312 {313 using type = is_default_policy<U>;314 };315};316 317template <class Seq, class T, boost::math::size_t N>318struct append_N319{320 using type = typename append_N<mp::mp_push_back<Seq, T>, T, N-1>::type;321};322 323template <class Seq, class T>324struct append_N<Seq, T, 0>325{326 using type = Seq;327};328 329//330// Traits class to work out what template parameters our default331// policy<> class will have when modified for forwarding:332//333template <bool f, bool d>334struct default_args335{336 typedef promote_float<false> arg1;337 typedef promote_double<false> arg2;338};339 340template <>341struct default_args<false, false>342{343 typedef default_policy arg1;344 typedef default_policy arg2;345};346 347template <>348struct default_args<true, false>349{350 typedef promote_float<false> arg1;351 typedef default_policy arg2;352};353 354template <>355struct default_args<false, true>356{357 typedef promote_double<false> arg1;358 typedef default_policy arg2;359};360 361typedef default_args<BOOST_MATH_PROMOTE_FLOAT_POLICY, BOOST_MATH_PROMOTE_DOUBLE_POLICY>::arg1 forwarding_arg1;362typedef default_args<BOOST_MATH_PROMOTE_FLOAT_POLICY, BOOST_MATH_PROMOTE_DOUBLE_POLICY>::arg2 forwarding_arg2;363 364} // detail365 366//367// Now define the policy type with enough arguments to handle all368// the policies:369//370template <typename A1 = default_policy,371 typename A2 = default_policy,372 typename A3 = default_policy,373 typename A4 = default_policy,374 typename A5 = default_policy,375 typename A6 = default_policy,376 typename A7 = default_policy,377 typename A8 = default_policy,378 typename A9 = default_policy,379 typename A10 = default_policy,380 typename A11 = default_policy,381 typename A12 = default_policy,382 typename A13 = default_policy>383class policy384{385private:386 //387 // Validate all our arguments:388 //389 static_assert(::boost::math::policies::detail::is_valid_policy<A1>::value, "::boost::math::policies::detail::is_valid_policy<A1>::value");390 static_assert(::boost::math::policies::detail::is_valid_policy<A2>::value, "::boost::math::policies::detail::is_valid_policy<A2>::value");391 static_assert(::boost::math::policies::detail::is_valid_policy<A3>::value, "::boost::math::policies::detail::is_valid_policy<A3>::value");392 static_assert(::boost::math::policies::detail::is_valid_policy<A4>::value, "::boost::math::policies::detail::is_valid_policy<A4>::value");393 static_assert(::boost::math::policies::detail::is_valid_policy<A5>::value, "::boost::math::policies::detail::is_valid_policy<A5>::value");394 static_assert(::boost::math::policies::detail::is_valid_policy<A6>::value, "::boost::math::policies::detail::is_valid_policy<A6>::value");395 static_assert(::boost::math::policies::detail::is_valid_policy<A7>::value, "::boost::math::policies::detail::is_valid_policy<A7>::value");396 static_assert(::boost::math::policies::detail::is_valid_policy<A8>::value, "::boost::math::policies::detail::is_valid_policy<A8>::value");397 static_assert(::boost::math::policies::detail::is_valid_policy<A9>::value, "::boost::math::policies::detail::is_valid_policy<A9>::value");398 static_assert(::boost::math::policies::detail::is_valid_policy<A10>::value, "::boost::math::policies::detail::is_valid_policy<A10>::value");399 static_assert(::boost::math::policies::detail::is_valid_policy<A11>::value, "::boost::math::policies::detail::is_valid_policy<A11>::value");400 static_assert(::boost::math::policies::detail::is_valid_policy<A12>::value, "::boost::math::policies::detail::is_valid_policy<A12>::value");401 static_assert(::boost::math::policies::detail::is_valid_policy<A13>::value, "::boost::math::policies::detail::is_valid_policy<A13>::value");402 //403 // Typelist of the arguments:404 //405 using arg_list = mp::mp_list<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13>;406 static constexpr boost::math::size_t arg_list_size = mp::mp_size<arg_list>::value;407 408 template<typename A, typename B, bool b>409 struct pick_arg410 {411 using type = A;412 };413 414 template<typename A, typename B>415 struct pick_arg<A, B, false>416 {417 using type = mp::mp_at<arg_list, B>;418 };419 420 template<typename Fn, typename Default>421 class arg_type422 {423 private:424 using index = mp::mp_find_if_q<arg_list, Fn>;425 static constexpr bool end = (index::value >= arg_list_size);426 public:427 using type = typename pick_arg<Default, index, end>::type;428 };429 430 // Work out the base 2 and 10 precisions to calculate the public precision_type:431 using digits10_type = typename arg_type<mp::mp_quote_trait<is_digits10>, digits10<>>::type;432 using bits_precision_type = typename arg_type<mp::mp_quote_trait<is_digits2>, digits2<>>::type;433 434public:435 436 // Error Types:437 using domain_error_type = typename arg_type<mp::mp_quote_trait<is_domain_error>, domain_error<>>::type;438 using pole_error_type = typename arg_type<mp::mp_quote_trait<is_pole_error>, pole_error<>>::type;439 using overflow_error_type = typename arg_type<mp::mp_quote_trait<is_overflow_error>, overflow_error<>>::type;440 using underflow_error_type = typename arg_type<mp::mp_quote_trait<is_underflow_error>, underflow_error<>>::type;441 using denorm_error_type = typename arg_type<mp::mp_quote_trait<is_denorm_error>, denorm_error<>>::type;442 using evaluation_error_type = typename arg_type<mp::mp_quote_trait<is_evaluation_error>, evaluation_error<>>::type;443 using rounding_error_type = typename arg_type<mp::mp_quote_trait<is_rounding_error>, rounding_error<>>::type;444 using indeterminate_result_error_type = typename arg_type<mp::mp_quote_trait<is_indeterminate_result_error>, indeterminate_result_error<>>::type;445 446 // Precision:447 using precision_type = typename detail::precision<digits10_type, bits_precision_type>::type;448 449 // Internal promotion:450 using promote_float_type = typename arg_type<mp::mp_quote_trait<is_promote_float>, promote_float<>>::type;451 using promote_double_type = typename arg_type<mp::mp_quote_trait<is_promote_double>, promote_double<>>::type;452 453 // Discrete quantiles:454 using discrete_quantile_type = typename arg_type<mp::mp_quote_trait<is_discrete_quantile>, discrete_quantile<>>::type;455 456 // Mathematically undefined properties:457 using assert_undefined_type = typename arg_type<mp::mp_quote_trait<is_assert_undefined>, assert_undefined<>>::type;458 459 // Max iterations:460 using max_series_iterations_type = typename arg_type<mp::mp_quote_trait<is_max_series_iterations>, max_series_iterations<>>::type;461 using max_root_iterations_type = typename arg_type<mp::mp_quote_trait<is_max_root_iterations>, max_root_iterations<>>::type;462};463 464//465// These full specializations are defined to reduce the amount of466// template instantiations that have to take place when using the default467// policies, they have quite a large impact on compile times:468//469template <>470class policy<default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy>471{472public:473 using domain_error_type = domain_error<>;474 using pole_error_type = pole_error<>;475 using overflow_error_type = overflow_error<>;476 using underflow_error_type = underflow_error<>;477 using denorm_error_type = denorm_error<>;478 using evaluation_error_type = evaluation_error<>;479 using rounding_error_type = rounding_error<>;480 using indeterminate_result_error_type = indeterminate_result_error<>;481#if BOOST_MATH_DIGITS10_POLICY == 0482 using precision_type = digits2<>;483#else484 using precision_type = detail::precision<digits10<>, digits2<>>::type;485#endif486 using promote_float_type = promote_float<>;487 using promote_double_type = promote_double<>;488 using discrete_quantile_type = discrete_quantile<>;489 using assert_undefined_type = assert_undefined<>;490 using max_series_iterations_type = max_series_iterations<>;491 using max_root_iterations_type = max_root_iterations<>;492};493 494template <>495struct 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>496{497public:498 using domain_error_type = domain_error<>;499 using pole_error_type = pole_error<>;500 using overflow_error_type = overflow_error<>;501 using underflow_error_type = underflow_error<>;502 using denorm_error_type = denorm_error<>;503 using evaluation_error_type = evaluation_error<>;504 using rounding_error_type = rounding_error<>;505 using indeterminate_result_error_type = indeterminate_result_error<>;506#if BOOST_MATH_DIGITS10_POLICY == 0507 using precision_type = digits2<>;508#else509 using precision_type = detail::precision<digits10<>, digits2<>>::type;510#endif511 using promote_float_type = promote_float<false>;512 using promote_double_type = promote_double<false>;513 using discrete_quantile_type = discrete_quantile<>;514 using assert_undefined_type = assert_undefined<>;515 using max_series_iterations_type = max_series_iterations<>;516 using max_root_iterations_type = max_root_iterations<>;517};518 519template <typename Policy,520 typename A1 = default_policy,521 typename A2 = default_policy,522 typename A3 = default_policy,523 typename A4 = default_policy,524 typename A5 = default_policy,525 typename A6 = default_policy,526 typename A7 = default_policy,527 typename A8 = default_policy,528 typename A9 = default_policy,529 typename A10 = default_policy,530 typename A11 = default_policy,531 typename A12 = default_policy,532 typename A13 = default_policy>533class normalise534{535private:536 using arg_list = mp::mp_list<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13>;537 static constexpr boost::math::size_t arg_list_size = mp::mp_size<arg_list>::value;538 539 template<typename A, typename B, bool b>540 struct pick_arg541 {542 using type = A;543 };544 545 template<typename A, typename B>546 struct pick_arg<A, B, false>547 {548 using type = mp::mp_at<arg_list, B>;549 };550 551 template<typename Fn, typename Default>552 class arg_type553 {554 private:555 using index = mp::mp_find_if_q<arg_list, Fn>;556 static constexpr bool end = (index::value >= arg_list_size);557 public:558 using type = typename pick_arg<Default, index, end>::type;559 };560 561 // Error types:562 using domain_error_type = typename arg_type<mp::mp_quote_trait<is_domain_error>, typename Policy::domain_error_type>::type;563 using pole_error_type = typename arg_type<mp::mp_quote_trait<is_pole_error>, typename Policy::pole_error_type>::type;564 using overflow_error_type = typename arg_type<mp::mp_quote_trait<is_overflow_error>, typename Policy::overflow_error_type>::type;565 using underflow_error_type = typename arg_type<mp::mp_quote_trait<is_underflow_error>, typename Policy::underflow_error_type>::type;566 using denorm_error_type = typename arg_type<mp::mp_quote_trait<is_denorm_error>, typename Policy::denorm_error_type>::type;567 using evaluation_error_type = typename arg_type<mp::mp_quote_trait<is_evaluation_error>, typename Policy::evaluation_error_type>::type;568 using rounding_error_type = typename arg_type<mp::mp_quote_trait<is_rounding_error>, typename Policy::rounding_error_type>::type;569 using indeterminate_result_error_type = typename arg_type<mp::mp_quote_trait<is_indeterminate_result_error>, typename Policy::indeterminate_result_error_type>::type;570 571 // Precision:572 using digits10_type = typename arg_type<mp::mp_quote_trait<is_digits10>, digits10<>>::type;573 using bits_precision_type = typename arg_type<mp::mp_quote_trait<is_digits2>, typename Policy::precision_type>::type;574 using precision_type = typename detail::precision<digits10_type, bits_precision_type>::type;575 576 // Internal promotion:577 using promote_float_type = typename arg_type<mp::mp_quote_trait<is_promote_float>, typename Policy::promote_float_type>::type;578 using promote_double_type = typename arg_type<mp::mp_quote_trait<is_promote_double>, typename Policy::promote_double_type>::type;579 580 // Discrete quantiles:581 using discrete_quantile_type = typename arg_type<mp::mp_quote_trait<is_discrete_quantile>, typename Policy::discrete_quantile_type>::type;582 583 // Mathematically undefined properties:584 using assert_undefined_type = typename arg_type<mp::mp_quote_trait<is_assert_undefined>, typename Policy::assert_undefined_type>::type;585 586 // Max iterations:587 using max_series_iterations_type = typename arg_type<mp::mp_quote_trait<is_max_series_iterations>, typename Policy::max_series_iterations_type>::type;588 using max_root_iterations_type = typename arg_type<mp::mp_quote_trait<is_max_root_iterations>, typename Policy::max_root_iterations_type>::type;589 590 // Define a typelist of the policies:591 using result_list = mp::mp_list<592 domain_error_type,593 pole_error_type,594 overflow_error_type,595 underflow_error_type,596 denorm_error_type,597 evaluation_error_type,598 rounding_error_type,599 indeterminate_result_error_type,600 precision_type,601 promote_float_type,602 promote_double_type,603 discrete_quantile_type,604 assert_undefined_type,605 max_series_iterations_type,606 max_root_iterations_type>;607 608 // Remove all the policies that are the same as the default:609 using fn = mp::mp_quote_trait<detail::is_default_policy>;610 using reduced_list = mp::mp_remove_if_q<result_list, fn>;611 612 // Pad out the list with defaults:613 using result_type = typename detail::append_N<reduced_list, default_policy, (14UL - mp::mp_size<reduced_list>::value)>::type;614 615public:616 using type = policy<617 mp::mp_at_c<result_type, 0>,618 mp::mp_at_c<result_type, 1>,619 mp::mp_at_c<result_type, 2>,620 mp::mp_at_c<result_type, 3>,621 mp::mp_at_c<result_type, 4>,622 mp::mp_at_c<result_type, 5>,623 mp::mp_at_c<result_type, 6>,624 mp::mp_at_c<result_type, 7>,625 mp::mp_at_c<result_type, 8>,626 mp::mp_at_c<result_type, 9>,627 mp::mp_at_c<result_type, 10>,628 mp::mp_at_c<result_type, 11>,629 mp::mp_at_c<result_type, 12>630 >;631};632 633// Full specialisation to speed up compilation of the common case:634template <>635struct normalise<policy<>,636 promote_float<false>,637 promote_double<false>,638 discrete_quantile<>,639 assert_undefined<>,640 default_policy,641 default_policy,642 default_policy,643 default_policy,644 default_policy,645 default_policy,646 default_policy>647{648 using type = policy<detail::forwarding_arg1, detail::forwarding_arg2>;649};650 651template <>652struct normalise<policy<detail::forwarding_arg1, detail::forwarding_arg2>,653 promote_float<false>,654 promote_double<false>,655 discrete_quantile<>,656 assert_undefined<>,657 default_policy,658 default_policy,659 default_policy,660 default_policy,661 default_policy,662 default_policy,663 default_policy>664{665 using type = policy<detail::forwarding_arg1, detail::forwarding_arg2>;666};667 668BOOST_MATH_GPU_ENABLED constexpr policy<> make_policy() noexcept669{ return {}; }670 671template <class A1>672BOOST_MATH_GPU_ENABLED constexpr typename normalise<policy<>, A1>::type make_policy(const A1&) noexcept673{674 typedef typename normalise<policy<>, A1>::type result_type;675 return result_type();676}677 678template <class A1, class A2>679BOOST_MATH_GPU_ENABLED constexpr typename normalise<policy<>, A1, A2>::type make_policy(const A1&, const A2&) noexcept680{681 typedef typename normalise<policy<>, A1, A2>::type result_type;682 return result_type();683}684 685template <class A1, class A2, class A3>686BOOST_MATH_GPU_ENABLED constexpr typename normalise<policy<>, A1, A2, A3>::type make_policy(const A1&, const A2&, const A3&) noexcept687{688 typedef typename normalise<policy<>, A1, A2, A3>::type result_type;689 return result_type();690}691 692template <class A1, class A2, class A3, class A4>693BOOST_MATH_GPU_ENABLED constexpr typename normalise<policy<>, A1, A2, A3, A4>::type make_policy(const A1&, const A2&, const A3&, const A4&) noexcept694{695 typedef typename normalise<policy<>, A1, A2, A3, A4>::type result_type;696 return result_type();697}698 699template <class A1, class A2, class A3, class A4, class A5>700BOOST_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&) noexcept701{702 typedef typename normalise<policy<>, A1, A2, A3, A4, A5>::type result_type;703 return result_type();704}705 706template <class A1, class A2, class A3, class A4, class A5, class A6>707BOOST_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&) noexcept708{709 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6>::type result_type;710 return result_type();711}712 713template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>714BOOST_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&) noexcept715{716 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7>::type result_type;717 return result_type();718}719 720template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>721BOOST_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&) noexcept722{723 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8>::type result_type;724 return result_type();725}726 727template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>728BOOST_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&) noexcept729{730 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9>::type result_type;731 return result_type();732}733 734template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>735BOOST_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&) noexcept736{737 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>::type result_type;738 return result_type();739}740 741template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10, class A11>742BOOST_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&) noexcept743{744 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11>::type result_type;745 return result_type();746}747 748//749// Traits class to handle internal promotion:750//751template <class Real, class Policy>752struct evaluation753{754 typedef Real type;755};756 757template <class Policy>758struct evaluation<float, Policy>759{760 using type = typename boost::math::conditional<Policy::promote_float_type::value, double, float>::type;761};762 763template <class Policy>764struct evaluation<double, Policy>765{766 using type = typename boost::math::conditional<Policy::promote_double_type::value, long double, double>::type;767};768 769template <class Real, class Policy>770struct precision771{772 static_assert((boost::math::numeric_limits<Real>::radix == 2) || ((boost::math::numeric_limits<Real>::is_specialized == 0) || (boost::math::numeric_limits<Real>::digits == 0)),773 "(boost::math::numeric_limits<Real>::radix == 2) || ((boost::math::numeric_limits<Real>::is_specialized == 0) || (boost::math::numeric_limits<Real>::digits == 0))");774#ifndef BOOST_BORLANDC775 using precision_type = typename Policy::precision_type;776 using type = typename boost::math::conditional<777 ((boost::math::numeric_limits<Real>::is_specialized == 0) || (boost::math::numeric_limits<Real>::digits == 0)),778 // Possibly unknown precision:779 precision_type,780 typename boost::math::conditional<781 ((boost::math::numeric_limits<Real>::digits <= precision_type::value)782 || (Policy::precision_type::value <= 0)),783 // Default case, full precision for RealType:784 digits2< boost::math::numeric_limits<Real>::digits>,785 // User customised precision:786 precision_type787 >::type788 >::type;789#else790 using precision_type = typename Policy::precision_type;791 using digits_t = boost::math::integral_constant<int, boost::math::numeric_limits<Real>::digits>;792 using spec_t = boost::math::integral_constant<bool, boost::math::numeric_limits<Real>::is_specialized>;793 using type = typename boost::math::conditional<794 (spec_t::value == true boost::math::true_type || digits_t::value == 0),795 // Possibly unknown precision:796 precision_type,797 typename boost::math::conditional<798 (digits_t::value <= precision_type::value || precision_type::value <= 0),799 // Default case, full precision for RealType:800 digits2< boost::math::numeric_limits<Real>::digits>,801 // User customised precision:802 precision_type803 >::type804 >::type;805#endif806};807 808#ifdef BOOST_MATH_USE_FLOAT128809 810template <class Policy>811struct precision<BOOST_MATH_FLOAT128_TYPE, Policy>812{813 typedef boost::math::integral_constant<int, 113> type;814};815 816#endif817 818namespace detail{819 820template <class T, class Policy>821BOOST_MATH_GPU_ENABLED constexpr int digits_imp(boost::math::true_type const&) noexcept822{823 static_assert( boost::math::numeric_limits<T>::is_specialized, "boost::math::numeric_limits<T>::is_specialized");824 typedef typename boost::math::policies::precision<T, Policy>::type p_t;825 return p_t::value;826}827 828template <class T, class Policy>829BOOST_MATH_GPU_ENABLED constexpr int digits_imp(boost::math::false_type const&) noexcept830{831 return tools::digits<T>();832}833 834} // namespace detail835 836template <class T, class Policy>837BOOST_MATH_GPU_ENABLED constexpr int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept838{839 typedef boost::math::integral_constant<bool, boost::math::numeric_limits<T>::is_specialized > tag_type;840 return detail::digits_imp<T, Policy>(tag_type());841}842template <class T, class Policy>843BOOST_MATH_GPU_ENABLED constexpr int digits_base10(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept844{845 return boost::math::policies::digits<T, Policy>() * 301 / 1000L;846}847 848template <class Policy>849BOOST_MATH_GPU_ENABLED constexpr unsigned long get_max_series_iterations() noexcept850{851 typedef typename Policy::max_series_iterations_type iter_type;852 return iter_type::value;853}854 855template <class Policy>856BOOST_MATH_GPU_ENABLED constexpr unsigned long get_max_root_iterations() noexcept857{858 typedef typename Policy::max_root_iterations_type iter_type;859 return iter_type::value;860}861 862namespace detail{863 864template <class T, class Digits, class Small, class Default>865struct series_factor_calc866{867 BOOST_MATH_GPU_ENABLED static T get() noexcept(boost::math::is_floating_point<T>::value)868 {869 return ldexp(T(1.0), 1 - Digits::value);870 }871};872 873template <class T, class Digits>874struct series_factor_calc<T, Digits, boost::math::true_type, boost::math::true_type>875{876 BOOST_MATH_GPU_ENABLED static constexpr T get() noexcept(boost::math::is_floating_point<T>::value)877 {878 return boost::math::tools::epsilon<T>();879 }880};881template <class T, class Digits>882struct series_factor_calc<T, Digits, boost::math::true_type, boost::math::false_type>883{884 BOOST_MATH_GPU_ENABLED static constexpr T get() noexcept(boost::math::is_floating_point<T>::value)885 {886 return 1 / static_cast<T>(static_cast<boost::math::uintmax_t>(1u) << (Digits::value - 1));887 }888};889template <class T, class Digits>890struct series_factor_calc<T, Digits, boost::math::false_type, boost::math::true_type>891{892 BOOST_MATH_GPU_ENABLED static constexpr T get() noexcept(boost::math::is_floating_point<T>::value)893 {894 return boost::math::tools::epsilon<T>();895 }896};897 898template <class T, class Policy>899BOOST_MATH_GPU_ENABLED constexpr T get_epsilon_imp(boost::math::true_type const&) noexcept(boost::math::is_floating_point<T>::value)900{901 static_assert(boost::math::numeric_limits<T>::is_specialized, "boost::math::numeric_limits<T>::is_specialized");902 static_assert(boost::math::numeric_limits<T>::radix == 2, "boost::math::numeric_limits<T>::radix == 2");903 904 typedef typename boost::math::policies::precision<T, Policy>::type p_t;905 typedef boost::math::integral_constant<bool, p_t::value <= boost::math::numeric_limits<boost::math::uintmax_t>::digits> is_small_int;906 typedef boost::math::integral_constant<bool, p_t::value >= boost::math::numeric_limits<T>::digits> is_default_value;907 return series_factor_calc<T, p_t, is_small_int, is_default_value>::get();908}909 910template <class T, class Policy>911BOOST_MATH_GPU_ENABLED constexpr T get_epsilon_imp(boost::math::false_type const&) noexcept(boost::math::is_floating_point<T>::value)912{913 return tools::epsilon<T>();914}915 916} // namespace detail917 918template <class T, class Policy>919BOOST_MATH_GPU_ENABLED constexpr T get_epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) noexcept(boost::math::is_floating_point<T>::value)920{921 typedef boost::math::integral_constant<bool, (boost::math::numeric_limits<T>::is_specialized && (boost::math::numeric_limits<T>::radix == 2)) > tag_type;922 return detail::get_epsilon_imp<T, Policy>(tag_type());923}924 925namespace detail{926 927template <class A1,928 class A2,929 class A3,930 class A4,931 class A5,932 class A6,933 class A7,934 class A8,935 class A9,936 class A10,937 class A11>938BOOST_MATH_GPU_ENABLED char test_is_policy(const policy<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11>*);939BOOST_MATH_GPU_ENABLED double test_is_policy(...);940 941template <typename P>942class is_policy_imp943{944public:945 static constexpr bool value = (sizeof(::boost::math::policies::detail::test_is_policy(static_cast<P*>(nullptr))) == sizeof(char));946};947 948}949 950template <typename P>951class is_policy952{953public:954 static constexpr bool value = boost::math::policies::detail::is_policy_imp<P>::value;955 using type = boost::math::integral_constant<bool, value>;956};957 958//959// Helper traits class for distribution error handling:960//961template <class Policy>962struct constructor_error_check963{964 using domain_error_type = typename Policy::domain_error_type;965 using type = typename boost::math::conditional<966 (domain_error_type::value == throw_on_error) || (domain_error_type::value == user_error) || (domain_error_type::value == errno_on_error),967 boost::math::true_type,968 boost::math::false_type>::type;969};970 971template <class Policy>972struct method_error_check973{974 using domain_error_type = typename Policy::domain_error_type;975 using type = typename boost::math::conditional<976 (domain_error_type::value == throw_on_error),977 boost::math::false_type,978 boost::math::true_type>::type;979};980//981// Does the Policy ever throw on error?982//983template <class Policy>984struct is_noexcept_error_policy985{986 typedef typename Policy::domain_error_type t1;987 typedef typename Policy::pole_error_type t2;988 typedef typename Policy::overflow_error_type t3;989 typedef typename Policy::underflow_error_type t4;990 typedef typename Policy::denorm_error_type t5;991 typedef typename Policy::evaluation_error_type t6;992 typedef typename Policy::rounding_error_type t7;993 typedef typename Policy::indeterminate_result_error_type t8;994 995 static constexpr bool value =996 ((t1::value != throw_on_error) && (t1::value != user_error)997 && (t2::value != throw_on_error) && (t2::value != user_error)998 && (t3::value != throw_on_error) && (t3::value != user_error)999 && (t4::value != throw_on_error) && (t4::value != user_error)1000 && (t5::value != throw_on_error) && (t5::value != user_error)1001 && (t6::value != throw_on_error) && (t6::value != user_error)1002 && (t7::value != throw_on_error) && (t7::value != user_error)1003 && (t8::value != throw_on_error) && (t8::value != user_error));1004};1005 1006}}} // namespaces1007 1008#endif // BOOST_MATH_POLICY_HPP1009 1010