annotate any/include/boost/math/distributions/detail/generic_mode.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
rev   line source
cannam@160 1 // Copyright John Maddock 2008.
cannam@160 2
cannam@160 3 // Use, modification and distribution are subject to the
cannam@160 4 // Boost Software License, Version 1.0.
cannam@160 5 // (See accompanying file LICENSE_1_0.txt
cannam@160 6 // or copy at http://www.boost.org/LICENSE_1_0.txt)
cannam@160 7
cannam@160 8 #ifndef BOOST_MATH_DISTRIBUTIONS_DETAIL_MODE_HPP
cannam@160 9 #define BOOST_MATH_DISTRIBUTIONS_DETAIL_MODE_HPP
cannam@160 10
cannam@160 11 #include <boost/math/tools/minima.hpp> // function minimization for mode
cannam@160 12 #include <boost/math/policies/error_handling.hpp>
cannam@160 13 #include <boost/math/distributions/fwd.hpp>
cannam@160 14
cannam@160 15 namespace boost{ namespace math{ namespace detail{
cannam@160 16
cannam@160 17 template <class Dist>
cannam@160 18 struct pdf_minimizer
cannam@160 19 {
cannam@160 20 pdf_minimizer(const Dist& d)
cannam@160 21 : dist(d) {}
cannam@160 22
cannam@160 23 typename Dist::value_type operator()(const typename Dist::value_type& x)
cannam@160 24 {
cannam@160 25 return -pdf(dist, x);
cannam@160 26 }
cannam@160 27 private:
cannam@160 28 Dist dist;
cannam@160 29 };
cannam@160 30
cannam@160 31 template <class Dist>
cannam@160 32 typename Dist::value_type generic_find_mode(const Dist& dist, typename Dist::value_type guess, const char* function, typename Dist::value_type step = 0)
cannam@160 33 {
cannam@160 34 BOOST_MATH_STD_USING
cannam@160 35 typedef typename Dist::value_type value_type;
cannam@160 36 typedef typename Dist::policy_type policy_type;
cannam@160 37 //
cannam@160 38 // Need to begin by bracketing the maxima of the PDF:
cannam@160 39 //
cannam@160 40 value_type maxval;
cannam@160 41 value_type upper_bound = guess;
cannam@160 42 value_type lower_bound;
cannam@160 43 value_type v = pdf(dist, guess);
cannam@160 44 if(v == 0)
cannam@160 45 {
cannam@160 46 //
cannam@160 47 // Oops we don't know how to handle this, or even in which
cannam@160 48 // direction we should move in, treat as an evaluation error:
cannam@160 49 //
cannam@160 50 return policies::raise_evaluation_error(
cannam@160 51 function,
cannam@160 52 "Could not locate a starting location for the search for the mode, original guess was %1%", guess, policy_type());
cannam@160 53 }
cannam@160 54 do
cannam@160 55 {
cannam@160 56 maxval = v;
cannam@160 57 if(step != 0)
cannam@160 58 upper_bound += step;
cannam@160 59 else
cannam@160 60 upper_bound *= 2;
cannam@160 61 v = pdf(dist, upper_bound);
cannam@160 62 }while(maxval < v);
cannam@160 63
cannam@160 64 lower_bound = upper_bound;
cannam@160 65 do
cannam@160 66 {
cannam@160 67 maxval = v;
cannam@160 68 if(step != 0)
cannam@160 69 lower_bound -= step;
cannam@160 70 else
cannam@160 71 lower_bound /= 2;
cannam@160 72 v = pdf(dist, lower_bound);
cannam@160 73 }while(maxval < v);
cannam@160 74
cannam@160 75 boost::uintmax_t max_iter = policies::get_max_root_iterations<policy_type>();
cannam@160 76
cannam@160 77 value_type result = tools::brent_find_minima(
cannam@160 78 pdf_minimizer<Dist>(dist),
cannam@160 79 lower_bound,
cannam@160 80 upper_bound,
cannam@160 81 policies::digits<value_type, policy_type>(),
cannam@160 82 max_iter).first;
cannam@160 83 if(max_iter >= policies::get_max_root_iterations<policy_type>())
cannam@160 84 {
cannam@160 85 return policies::raise_evaluation_error<value_type>(
cannam@160 86 function,
cannam@160 87 "Unable to locate solution in a reasonable time:"
cannam@160 88 " either there is no answer to the mode of the distribution"
cannam@160 89 " or the answer is infinite. Current best guess is %1%", result, policy_type());
cannam@160 90 }
cannam@160 91 return result;
cannam@160 92 }
cannam@160 93 //
cannam@160 94 // As above,but confined to the interval [0,1]:
cannam@160 95 //
cannam@160 96 template <class Dist>
cannam@160 97 typename Dist::value_type generic_find_mode_01(const Dist& dist, typename Dist::value_type guess, const char* function)
cannam@160 98 {
cannam@160 99 BOOST_MATH_STD_USING
cannam@160 100 typedef typename Dist::value_type value_type;
cannam@160 101 typedef typename Dist::policy_type policy_type;
cannam@160 102 //
cannam@160 103 // Need to begin by bracketing the maxima of the PDF:
cannam@160 104 //
cannam@160 105 value_type maxval;
cannam@160 106 value_type upper_bound = guess;
cannam@160 107 value_type lower_bound;
cannam@160 108 value_type v = pdf(dist, guess);
cannam@160 109 do
cannam@160 110 {
cannam@160 111 maxval = v;
cannam@160 112 upper_bound = 1 - (1 - upper_bound) / 2;
cannam@160 113 if(upper_bound == 1)
cannam@160 114 return 1;
cannam@160 115 v = pdf(dist, upper_bound);
cannam@160 116 }while(maxval < v);
cannam@160 117
cannam@160 118 lower_bound = upper_bound;
cannam@160 119 do
cannam@160 120 {
cannam@160 121 maxval = v;
cannam@160 122 lower_bound /= 2;
cannam@160 123 if(lower_bound < tools::min_value<value_type>())
cannam@160 124 return 0;
cannam@160 125 v = pdf(dist, lower_bound);
cannam@160 126 }while(maxval < v);
cannam@160 127
cannam@160 128 boost::uintmax_t max_iter = policies::get_max_root_iterations<policy_type>();
cannam@160 129
cannam@160 130 value_type result = tools::brent_find_minima(
cannam@160 131 pdf_minimizer<Dist>(dist),
cannam@160 132 lower_bound,
cannam@160 133 upper_bound,
cannam@160 134 policies::digits<value_type, policy_type>(),
cannam@160 135 max_iter).first;
cannam@160 136 if(max_iter >= policies::get_max_root_iterations<policy_type>())
cannam@160 137 {
cannam@160 138 return policies::raise_evaluation_error<value_type>(
cannam@160 139 function,
cannam@160 140 "Unable to locate solution in a reasonable time:"
cannam@160 141 " either there is no answer to the mode of the distribution"
cannam@160 142 " or the answer is infinite. Current best guess is %1%", result, policy_type());
cannam@160 143 }
cannam@160 144 return result;
cannam@160 145 }
cannam@160 146
cannam@160 147 }}} // namespaces
cannam@160 148
cannam@160 149 #endif // BOOST_MATH_DISTRIBUTIONS_DETAIL_MODE_HPP