572 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			572 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
//  Copyright John Maddock 2007.
 | 
						|
//  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_DISTRIBUTIONS_DETAIL_INV_DISCRETE_QUANTILE
 | 
						|
#define BOOST_MATH_DISTRIBUTIONS_DETAIL_INV_DISCRETE_QUANTILE
 | 
						|
 | 
						|
#include <algorithm>
 | 
						|
 | 
						|
namespace boost{ namespace math{ namespace detail{
 | 
						|
 | 
						|
//
 | 
						|
// Functor for root finding algorithm:
 | 
						|
//
 | 
						|
template <class Dist>
 | 
						|
struct distribution_quantile_finder
 | 
						|
{
 | 
						|
   typedef typename Dist::value_type value_type;
 | 
						|
   typedef typename Dist::policy_type policy_type;
 | 
						|
 | 
						|
   distribution_quantile_finder(const Dist d, value_type p, bool c)
 | 
						|
      : dist(d), target(p), comp(c) {}
 | 
						|
 | 
						|
   value_type operator()(value_type const& x)
 | 
						|
   {
 | 
						|
      return comp ? value_type(target - cdf(complement(dist, x))) : value_type(cdf(dist, x) - target);
 | 
						|
   }
 | 
						|
 | 
						|
private:
 | 
						|
   Dist dist;
 | 
						|
   value_type target;
 | 
						|
   bool comp;
 | 
						|
};
 | 
						|
//
 | 
						|
// The purpose of adjust_bounds, is to toggle the last bit of the
 | 
						|
// range so that both ends round to the same integer, if possible.
 | 
						|
// If they do both round the same then we terminate the search
 | 
						|
// for the root *very* quickly when finding an integer result.
 | 
						|
// At the point that this function is called we know that "a" is
 | 
						|
// below the root and "b" above it, so this change can not result
 | 
						|
// in the root no longer being bracketed.
 | 
						|
//
 | 
						|
template <class Real, class Tol>
 | 
						|
void adjust_bounds(Real& /* a */, Real& /* b */, Tol const& /* tol */){}
 | 
						|
 | 
						|
template <class Real>
 | 
						|
void adjust_bounds(Real& /* a */, Real& b, tools::equal_floor const& /* tol */)
 | 
						|
{
 | 
						|
   BOOST_MATH_STD_USING
 | 
						|
   b -= tools::epsilon<Real>() * b;
 | 
						|
}
 | 
						|
 | 
						|
template <class Real>
 | 
						|
void adjust_bounds(Real& a, Real& /* b */, tools::equal_ceil const& /* tol */)
 | 
						|
{
 | 
						|
   BOOST_MATH_STD_USING
 | 
						|
   a += tools::epsilon<Real>() * a;
 | 
						|
}
 | 
						|
 | 
						|
template <class Real>
 | 
						|
void adjust_bounds(Real& a, Real& b, tools::equal_nearest_integer const& /* tol */)
 | 
						|
{
 | 
						|
   BOOST_MATH_STD_USING
 | 
						|
   a += tools::epsilon<Real>() * a;
 | 
						|
   b -= tools::epsilon<Real>() * b;
 | 
						|
}
 | 
						|
//
 | 
						|
// This is where all the work is done:
 | 
						|
//
 | 
						|
template <class Dist, class Tolerance>
 | 
						|
typename Dist::value_type 
 | 
						|
   do_inverse_discrete_quantile(
 | 
						|
      const Dist& dist,
 | 
						|
      const typename Dist::value_type& p,
 | 
						|
      bool comp,
 | 
						|
      typename Dist::value_type guess,
 | 
						|
      const typename Dist::value_type& multiplier,
 | 
						|
      typename Dist::value_type adder,
 | 
						|
      const Tolerance& tol,
 | 
						|
      boost::uintmax_t& max_iter)
 | 
						|
{
 | 
						|
   typedef typename Dist::value_type value_type;
 | 
						|
   typedef typename Dist::policy_type policy_type;
 | 
						|
 | 
						|
   static const char* function = "boost::math::do_inverse_discrete_quantile<%1%>";
 | 
						|
 | 
						|
   BOOST_MATH_STD_USING
 | 
						|
 | 
						|
   distribution_quantile_finder<Dist> f(dist, p, comp);
 | 
						|
   //
 | 
						|
   // Max bounds of the distribution:
 | 
						|
   //
 | 
						|
   value_type min_bound, max_bound;
 | 
						|
   boost::math::tie(min_bound, max_bound) = support(dist);
 | 
						|
 | 
						|
   if(guess > max_bound)
 | 
						|
      guess = max_bound;
 | 
						|
   if(guess < min_bound)
 | 
						|
      guess = min_bound;
 | 
						|
 | 
						|
   value_type fa = f(guess);
 | 
						|
   boost::uintmax_t count = max_iter - 1;
 | 
						|
   value_type fb(fa), a(guess), b =0; // Compiler warning C4701: potentially uninitialized local variable 'b' used
 | 
						|
 | 
						|
   if(fa == 0)
 | 
						|
      return guess;
 | 
						|
 | 
						|
   //
 | 
						|
   // For small expected results, just use a linear search:
 | 
						|
   //
 | 
						|
   if(guess < 10)
 | 
						|
   {
 | 
						|
      b = a;
 | 
						|
      while((a < 10) && (fa * fb >= 0))
 | 
						|
      {
 | 
						|
         if(fb <= 0)
 | 
						|
         {
 | 
						|
            a = b;
 | 
						|
            b = a + 1;
 | 
						|
            if(b > max_bound)
 | 
						|
               b = max_bound;
 | 
						|
            fb = f(b);
 | 
						|
            --count;
 | 
						|
            if(fb == 0)
 | 
						|
               return b;
 | 
						|
            if(a == b)
 | 
						|
               return b; // can't go any higher!
 | 
						|
         }
 | 
						|
         else
 | 
						|
         {
 | 
						|
            b = a;
 | 
						|
            a = (std::max)(value_type(b - 1), value_type(0));
 | 
						|
            if(a < min_bound)
 | 
						|
               a = min_bound;
 | 
						|
            fa = f(a);
 | 
						|
            --count;
 | 
						|
            if(fa == 0)
 | 
						|
               return a;
 | 
						|
            if(a == b)
 | 
						|
               return a;  //  We can't go any lower than this!
 | 
						|
         }
 | 
						|
      }
 | 
						|
   }
 | 
						|
   //
 | 
						|
   // Try and bracket using a couple of additions first, 
 | 
						|
   // we're assuming that "guess" is likely to be accurate
 | 
						|
   // to the nearest int or so:
 | 
						|
   //
 | 
						|
   else if(adder != 0)
 | 
						|
   {
 | 
						|
      //
 | 
						|
      // If we're looking for a large result, then bump "adder" up
 | 
						|
      // by a bit to increase our chances of bracketing the root:
 | 
						|
      //
 | 
						|
      //adder = (std::max)(adder, 0.001f * guess);
 | 
						|
      if(fa < 0)
 | 
						|
      {
 | 
						|
         b = a + adder;
 | 
						|
         if(b > max_bound)
 | 
						|
            b = max_bound;
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
         b = (std::max)(value_type(a - adder), value_type(0));
 | 
						|
         if(b < min_bound)
 | 
						|
            b = min_bound;
 | 
						|
      }
 | 
						|
      fb = f(b);
 | 
						|
      --count;
 | 
						|
      if(fb == 0)
 | 
						|
         return b;
 | 
						|
      if(count && (fa * fb >= 0))
 | 
						|
      {
 | 
						|
         //
 | 
						|
         // We didn't bracket the root, try 
 | 
						|
         // once more:
 | 
						|
         //
 | 
						|
         a = b;
 | 
						|
         fa = fb;
 | 
						|
         if(fa < 0)
 | 
						|
         {
 | 
						|
            b = a + adder;
 | 
						|
            if(b > max_bound)
 | 
						|
               b = max_bound;
 | 
						|
         }
 | 
						|
         else
 | 
						|
         {
 | 
						|
            b = (std::max)(value_type(a - adder), value_type(0));
 | 
						|
            if(b < min_bound)
 | 
						|
               b = min_bound;
 | 
						|
         }
 | 
						|
         fb = f(b);
 | 
						|
         --count;
 | 
						|
      }
 | 
						|
      if(a > b)
 | 
						|
      {
 | 
						|
         using std::swap;
 | 
						|
         swap(a, b);
 | 
						|
         swap(fa, fb);
 | 
						|
      }
 | 
						|
   }
 | 
						|
   //
 | 
						|
   // If the root hasn't been bracketed yet, try again
 | 
						|
   // using the multiplier this time:
 | 
						|
   //
 | 
						|
   if((boost::math::sign)(fb) == (boost::math::sign)(fa))
 | 
						|
   {
 | 
						|
      if(fa < 0)
 | 
						|
      {
 | 
						|
         //
 | 
						|
         // Zero is to the right of x2, so walk upwards
 | 
						|
         // until we find it:
 | 
						|
         //
 | 
						|
         while(((boost::math::sign)(fb) == (boost::math::sign)(fa)) && (a != b))
 | 
						|
         {
 | 
						|
            if(count == 0)
 | 
						|
               return policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", b, policy_type());
 | 
						|
            a = b;
 | 
						|
            fa = fb;
 | 
						|
            b *= multiplier;
 | 
						|
            if(b > max_bound)
 | 
						|
               b = max_bound;
 | 
						|
            fb = f(b);
 | 
						|
            --count;
 | 
						|
            BOOST_MATH_INSTRUMENT_CODE("a = " << a << " b = " << b << " fa = " << fa << " fb = " << fb << " count = " << count);
 | 
						|
         }
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
         //
 | 
						|
         // Zero is to the left of a, so walk downwards
 | 
						|
         // until we find it:
 | 
						|
         //
 | 
						|
         while(((boost::math::sign)(fb) == (boost::math::sign)(fa)) && (a != b))
 | 
						|
         {
 | 
						|
            if(fabs(a) < tools::min_value<value_type>())
 | 
						|
            {
 | 
						|
               // Escape route just in case the answer is zero!
 | 
						|
               max_iter -= count;
 | 
						|
               max_iter += 1;
 | 
						|
               return 0;
 | 
						|
            }
 | 
						|
            if(count == 0)
 | 
						|
               return policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", a, policy_type());
 | 
						|
            b = a;
 | 
						|
            fb = fa;
 | 
						|
            a /= multiplier;
 | 
						|
            if(a < min_bound)
 | 
						|
               a = min_bound;
 | 
						|
            fa = f(a);
 | 
						|
            --count;
 | 
						|
            BOOST_MATH_INSTRUMENT_CODE("a = " << a << " b = " << b << " fa = " << fa << " fb = " << fb << " count = " << count);
 | 
						|
         }
 | 
						|
      }
 | 
						|
   }
 | 
						|
   max_iter -= count;
 | 
						|
   if(fa == 0)
 | 
						|
      return a;
 | 
						|
   if(fb == 0)
 | 
						|
      return b;
 | 
						|
   if(a == b)
 | 
						|
      return b;  // Ran out of bounds trying to bracket - there is no answer!
 | 
						|
   //
 | 
						|
   // Adjust bounds so that if we're looking for an integer
 | 
						|
   // result, then both ends round the same way:
 | 
						|
   //
 | 
						|
   adjust_bounds(a, b, tol);
 | 
						|
   //
 | 
						|
   // We don't want zero or denorm lower bounds:
 | 
						|
   //
 | 
						|
   if(a < tools::min_value<value_type>())
 | 
						|
      a = tools::min_value<value_type>();
 | 
						|
   //
 | 
						|
   // Go ahead and find the root:
 | 
						|
   //
 | 
						|
   std::pair<value_type, value_type> r = toms748_solve(f, a, b, fa, fb, tol, count, policy_type());
 | 
						|
   max_iter += count;
 | 
						|
   BOOST_MATH_INSTRUMENT_CODE("max_iter = " << max_iter << " count = " << count);
 | 
						|
   return (r.first + r.second) / 2;
 | 
						|
}
 | 
						|
//
 | 
						|
// Some special routine for rounding up and down:
 | 
						|
// We want to check and see if we are very close to an integer, and if so test to see if
 | 
						|
// that integer is an exact root of the cdf.  We do this because our root finder only
 | 
						|
// guarantees to find *a root*, and there can sometimes be many consecutive floating
 | 
						|
// point values which are all roots.  This is especially true if the target probability
 | 
						|
// is very close 1.
 | 
						|
//
 | 
						|
template <class Dist>
 | 
						|
inline typename Dist::value_type round_to_floor(const Dist& d, typename Dist::value_type result, typename Dist::value_type p, bool c)
 | 
						|
{
 | 
						|
   BOOST_MATH_STD_USING
 | 
						|
   typename Dist::value_type cc = ceil(result);
 | 
						|
   typename Dist::value_type pp = cc <= support(d).second ? c ? cdf(complement(d, cc)) : cdf(d, cc) : 1;
 | 
						|
   if(pp == p)
 | 
						|
      result = cc;
 | 
						|
   else
 | 
						|
      result = floor(result);
 | 
						|
   //
 | 
						|
   // Now find the smallest integer <= result for which we get an exact root:
 | 
						|
   //
 | 
						|
   while(result != 0)
 | 
						|
   {
 | 
						|
      cc = result - 1;
 | 
						|
      if(cc < support(d).first)
 | 
						|
         break;
 | 
						|
      pp = c ? cdf(complement(d, cc)) : cdf(d, cc);
 | 
						|
      if(pp == p)
 | 
						|
         result = cc;
 | 
						|
      else if(c ? pp > p : pp < p)
 | 
						|
         break;
 | 
						|
      result -= 1;
 | 
						|
   }
 | 
						|
 | 
						|
   return result;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef BOOST_MSVC
 | 
						|
#pragma warning(push)
 | 
						|
#pragma warning(disable:4127)
 | 
						|
#endif
 | 
						|
 | 
						|
template <class Dist>
 | 
						|
inline typename Dist::value_type round_to_ceil(const Dist& d, typename Dist::value_type result, typename Dist::value_type p, bool c)
 | 
						|
{
 | 
						|
   BOOST_MATH_STD_USING
 | 
						|
   typename Dist::value_type cc = floor(result);
 | 
						|
   typename Dist::value_type pp = cc >= support(d).first ? c ? cdf(complement(d, cc)) : cdf(d, cc) : 0;
 | 
						|
   if(pp == p)
 | 
						|
      result = cc;
 | 
						|
   else
 | 
						|
      result = ceil(result);
 | 
						|
   //
 | 
						|
   // Now find the largest integer >= result for which we get an exact root:
 | 
						|
   //
 | 
						|
   while(true)
 | 
						|
   {
 | 
						|
      cc = result + 1;
 | 
						|
      if(cc > support(d).second)
 | 
						|
         break;
 | 
						|
      pp = c ? cdf(complement(d, cc)) : cdf(d, cc);
 | 
						|
      if(pp == p)
 | 
						|
         result = cc;
 | 
						|
      else if(c ? pp < p : pp > p)
 | 
						|
         break;
 | 
						|
      result += 1;
 | 
						|
   }
 | 
						|
 | 
						|
   return result;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef BOOST_MSVC
 | 
						|
#pragma warning(pop)
 | 
						|
#endif
 | 
						|
//
 | 
						|
// Now finally are the public API functions.
 | 
						|
// There is one overload for each policy,
 | 
						|
// each one is responsible for selecting the correct
 | 
						|
// termination condition, and rounding the result
 | 
						|
// to an int where required.
 | 
						|
//
 | 
						|
template <class Dist>
 | 
						|
inline typename Dist::value_type 
 | 
						|
   inverse_discrete_quantile(
 | 
						|
      const Dist& dist,
 | 
						|
      typename Dist::value_type p,
 | 
						|
      bool c,
 | 
						|
      const typename Dist::value_type& guess,
 | 
						|
      const typename Dist::value_type& multiplier,
 | 
						|
      const typename Dist::value_type& adder,
 | 
						|
      const policies::discrete_quantile<policies::real>&,
 | 
						|
      boost::uintmax_t& max_iter)
 | 
						|
{
 | 
						|
   if(p > 0.5)
 | 
						|
   {
 | 
						|
      p = 1 - p;
 | 
						|
      c = !c;
 | 
						|
   }
 | 
						|
   typename Dist::value_type pp = c ? 1 - p : p;
 | 
						|
   if(pp <= pdf(dist, 0))
 | 
						|
      return 0;
 | 
						|
   return do_inverse_discrete_quantile(
 | 
						|
      dist, 
 | 
						|
      p, 
 | 
						|
      c,
 | 
						|
      guess, 
 | 
						|
      multiplier, 
 | 
						|
      adder, 
 | 
						|
      tools::eps_tolerance<typename Dist::value_type>(policies::digits<typename Dist::value_type, typename Dist::policy_type>()),
 | 
						|
      max_iter);
 | 
						|
}
 | 
						|
 | 
						|
template <class Dist>
 | 
						|
inline typename Dist::value_type 
 | 
						|
   inverse_discrete_quantile(
 | 
						|
      const Dist& dist,
 | 
						|
      const typename Dist::value_type& p,
 | 
						|
      bool c,
 | 
						|
      const typename Dist::value_type& guess,
 | 
						|
      const typename Dist::value_type& multiplier,
 | 
						|
      const typename Dist::value_type& adder,
 | 
						|
      const policies::discrete_quantile<policies::integer_round_outwards>&,
 | 
						|
      boost::uintmax_t& max_iter)
 | 
						|
{
 | 
						|
   typedef typename Dist::value_type value_type;
 | 
						|
   BOOST_MATH_STD_USING
 | 
						|
   typename Dist::value_type pp = c ? 1 - p : p;
 | 
						|
   if(pp <= pdf(dist, 0))
 | 
						|
      return 0;
 | 
						|
   //
 | 
						|
   // What happens next depends on whether we're looking for an 
 | 
						|
   // upper or lower quantile:
 | 
						|
   //
 | 
						|
   if(pp < 0.5f)
 | 
						|
      return round_to_floor(dist, do_inverse_discrete_quantile(
 | 
						|
         dist, 
 | 
						|
         p, 
 | 
						|
         c,
 | 
						|
         (guess < 1 ? value_type(1) : (value_type)floor(guess)), 
 | 
						|
         multiplier, 
 | 
						|
         adder, 
 | 
						|
         tools::equal_floor(),
 | 
						|
         max_iter), p, c);
 | 
						|
   // else:
 | 
						|
   return round_to_ceil(dist, do_inverse_discrete_quantile(
 | 
						|
      dist, 
 | 
						|
      p, 
 | 
						|
      c,
 | 
						|
      (value_type)ceil(guess), 
 | 
						|
      multiplier, 
 | 
						|
      adder, 
 | 
						|
      tools::equal_ceil(),
 | 
						|
      max_iter), p, c);
 | 
						|
}
 | 
						|
 | 
						|
template <class Dist>
 | 
						|
inline typename Dist::value_type 
 | 
						|
   inverse_discrete_quantile(
 | 
						|
      const Dist& dist,
 | 
						|
      const typename Dist::value_type& p,
 | 
						|
      bool c,
 | 
						|
      const typename Dist::value_type& guess,
 | 
						|
      const typename Dist::value_type& multiplier,
 | 
						|
      const typename Dist::value_type& adder,
 | 
						|
      const policies::discrete_quantile<policies::integer_round_inwards>&,
 | 
						|
      boost::uintmax_t& max_iter)
 | 
						|
{
 | 
						|
   typedef typename Dist::value_type value_type;
 | 
						|
   BOOST_MATH_STD_USING
 | 
						|
   typename Dist::value_type pp = c ? 1 - p : p;
 | 
						|
   if(pp <= pdf(dist, 0))
 | 
						|
      return 0;
 | 
						|
   //
 | 
						|
   // What happens next depends on whether we're looking for an 
 | 
						|
   // upper or lower quantile:
 | 
						|
   //
 | 
						|
   if(pp < 0.5f)
 | 
						|
      return round_to_ceil(dist, do_inverse_discrete_quantile(
 | 
						|
         dist, 
 | 
						|
         p, 
 | 
						|
         c,
 | 
						|
         ceil(guess), 
 | 
						|
         multiplier, 
 | 
						|
         adder, 
 | 
						|
         tools::equal_ceil(),
 | 
						|
         max_iter), p, c);
 | 
						|
   // else:
 | 
						|
   return round_to_floor(dist, do_inverse_discrete_quantile(
 | 
						|
      dist, 
 | 
						|
      p, 
 | 
						|
      c,
 | 
						|
      (guess < 1 ? value_type(1) : floor(guess)), 
 | 
						|
      multiplier, 
 | 
						|
      adder, 
 | 
						|
      tools::equal_floor(),
 | 
						|
      max_iter), p, c);
 | 
						|
}
 | 
						|
 | 
						|
template <class Dist>
 | 
						|
inline typename Dist::value_type 
 | 
						|
   inverse_discrete_quantile(
 | 
						|
      const Dist& dist,
 | 
						|
      const typename Dist::value_type& p,
 | 
						|
      bool c,
 | 
						|
      const typename Dist::value_type& guess,
 | 
						|
      const typename Dist::value_type& multiplier,
 | 
						|
      const typename Dist::value_type& adder,
 | 
						|
      const policies::discrete_quantile<policies::integer_round_down>&,
 | 
						|
      boost::uintmax_t& max_iter)
 | 
						|
{
 | 
						|
   typedef typename Dist::value_type value_type;
 | 
						|
   BOOST_MATH_STD_USING
 | 
						|
   typename Dist::value_type pp = c ? 1 - p : p;
 | 
						|
   if(pp <= pdf(dist, 0))
 | 
						|
      return 0;
 | 
						|
   return round_to_floor(dist, do_inverse_discrete_quantile(
 | 
						|
      dist, 
 | 
						|
      p, 
 | 
						|
      c,
 | 
						|
      (guess < 1 ? value_type(1) : floor(guess)), 
 | 
						|
      multiplier, 
 | 
						|
      adder, 
 | 
						|
      tools::equal_floor(),
 | 
						|
      max_iter), p, c);
 | 
						|
}
 | 
						|
 | 
						|
template <class Dist>
 | 
						|
inline typename Dist::value_type 
 | 
						|
   inverse_discrete_quantile(
 | 
						|
      const Dist& dist,
 | 
						|
      const typename Dist::value_type& p,
 | 
						|
      bool c,
 | 
						|
      const typename Dist::value_type& guess,
 | 
						|
      const typename Dist::value_type& multiplier,
 | 
						|
      const typename Dist::value_type& adder,
 | 
						|
      const policies::discrete_quantile<policies::integer_round_up>&,
 | 
						|
      boost::uintmax_t& max_iter)
 | 
						|
{
 | 
						|
   BOOST_MATH_STD_USING
 | 
						|
   typename Dist::value_type pp = c ? 1 - p : p;
 | 
						|
   if(pp <= pdf(dist, 0))
 | 
						|
      return 0;
 | 
						|
   return round_to_ceil(dist, do_inverse_discrete_quantile(
 | 
						|
      dist, 
 | 
						|
      p, 
 | 
						|
      c,
 | 
						|
      ceil(guess), 
 | 
						|
      multiplier, 
 | 
						|
      adder, 
 | 
						|
      tools::equal_ceil(),
 | 
						|
      max_iter), p, c);
 | 
						|
}
 | 
						|
 | 
						|
template <class Dist>
 | 
						|
inline typename Dist::value_type 
 | 
						|
   inverse_discrete_quantile(
 | 
						|
      const Dist& dist,
 | 
						|
      const typename Dist::value_type& p,
 | 
						|
      bool c,
 | 
						|
      const typename Dist::value_type& guess,
 | 
						|
      const typename Dist::value_type& multiplier,
 | 
						|
      const typename Dist::value_type& adder,
 | 
						|
      const policies::discrete_quantile<policies::integer_round_nearest>&,
 | 
						|
      boost::uintmax_t& max_iter)
 | 
						|
{
 | 
						|
   typedef typename Dist::value_type value_type;
 | 
						|
   BOOST_MATH_STD_USING
 | 
						|
   typename Dist::value_type pp = c ? 1 - p : p;
 | 
						|
   if(pp <= pdf(dist, 0))
 | 
						|
      return 0;
 | 
						|
   //
 | 
						|
   // Note that we adjust the guess to the nearest half-integer:
 | 
						|
   // this increase the chances that we will bracket the root
 | 
						|
   // with two results that both round to the same integer quickly.
 | 
						|
   //
 | 
						|
   return round_to_floor(dist, do_inverse_discrete_quantile(
 | 
						|
      dist, 
 | 
						|
      p, 
 | 
						|
      c,
 | 
						|
      (guess < 0.5f ? value_type(1.5f) : floor(guess + 0.5f) + 0.5f), 
 | 
						|
      multiplier, 
 | 
						|
      adder, 
 | 
						|
      tools::equal_nearest_integer(),
 | 
						|
      max_iter) + 0.5f, p, c);
 | 
						|
}
 | 
						|
 | 
						|
}}} // namespaces
 | 
						|
 | 
						|
#endif // BOOST_MATH_DISTRIBUTIONS_DETAIL_INV_DISCRETE_QUANTILE
 | 
						|
 |