Mercurial > hg > sv-dependency-builds
diff any/include/boost/math/distributions/detail/generic_quantile.hpp @ 160:cff480c41f97
Add some cross-platform Boost headers
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Sat, 16 Feb 2019 16:31:25 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/any/include/boost/math/distributions/detail/generic_quantile.hpp Sat Feb 16 16:31:25 2019 +0000 @@ -0,0 +1,91 @@ +// Copyright John Maddock 2008. +// 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_DISTIBUTIONS_DETAIL_GENERIC_QUANTILE_HPP +#define BOOST_MATH_DISTIBUTIONS_DETAIL_GENERIC_QUANTILE_HPP + +namespace boost{ namespace math{ namespace detail{ + +template <class Dist> +struct generic_quantile_finder +{ + typedef typename Dist::value_type value_type; + typedef typename Dist::policy_type policy_type; + + generic_quantile_finder(const Dist& d, value_type t, bool c) + : dist(d), target(t), comp(c) {} + + value_type operator()(const value_type& x) + { + return comp ? + value_type(target - cdf(complement(dist, x))) + : value_type(cdf(dist, x) - target); + } + +private: + Dist dist; + value_type target; + bool comp; +}; + +template <class T, class Policy> +inline T check_range_result(const T& x, const Policy& pol, const char* function) +{ + if((x >= 0) && (x < tools::min_value<T>())) + return policies::raise_underflow_error<T>(function, 0, pol); + if(x <= -tools::max_value<T>()) + return -policies::raise_overflow_error<T>(function, 0, pol); + if(x >= tools::max_value<T>()) + return policies::raise_overflow_error<T>(function, 0, pol); + return x; +} + +template <class Dist> +typename Dist::value_type generic_quantile(const Dist& dist, const typename Dist::value_type& p, const typename Dist::value_type& guess, bool comp, const char* function) +{ + typedef typename Dist::value_type value_type; + typedef typename Dist::policy_type policy_type; + typedef typename policies::normalise< + policy_type, + policies::promote_float<false>, + policies::promote_double<false>, + policies::discrete_quantile<>, + policies::assert_undefined<> >::type forwarding_policy; + + // + // Special cases first: + // + if(p == 0) + { + return comp + ? check_range_result(range(dist).second, forwarding_policy(), function) + : check_range_result(range(dist).first, forwarding_policy(), function); + } + if(p == 1) + { + return !comp + ? check_range_result(range(dist).second, forwarding_policy(), function) + : check_range_result(range(dist).first, forwarding_policy(), function); + } + + generic_quantile_finder<Dist> f(dist, p, comp); + tools::eps_tolerance<value_type> tol(policies::digits<value_type, forwarding_policy>() - 3); + boost::uintmax_t max_iter = policies::get_max_root_iterations<forwarding_policy>(); + std::pair<value_type, value_type> ir = tools::bracket_and_solve_root( + f, guess, value_type(2), true, tol, max_iter, forwarding_policy()); + value_type result = ir.first + (ir.second - ir.first) / 2; + if(max_iter >= policies::get_max_root_iterations<forwarding_policy>()) + { + return policies::raise_evaluation_error<value_type>(function, "Unable to locate solution in a reasonable time:" + " either there is no answer to quantile" + " or the answer is infinite. Current best guess is %1%", result, forwarding_policy()); + } + return result; +} + +}}} // namespaces + +#endif // BOOST_MATH_DISTIBUTIONS_DETAIL_GENERIC_QUANTILE_HPP +