Chris@16
|
1 // Copyright John Maddock 2007.
|
Chris@16
|
2 // Use, modification and distribution are subject to the
|
Chris@16
|
3 // Boost Software License, Version 1.0. (See accompanying file
|
Chris@16
|
4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
5
|
Chris@16
|
6 #ifndef BOOST_MATH_DISTRIBUTIONS_DETAIL_INV_DISCRETE_QUANTILE
|
Chris@16
|
7 #define BOOST_MATH_DISTRIBUTIONS_DETAIL_INV_DISCRETE_QUANTILE
|
Chris@16
|
8
|
Chris@16
|
9 #include <algorithm>
|
Chris@16
|
10
|
Chris@16
|
11 namespace boost{ namespace math{ namespace detail{
|
Chris@16
|
12
|
Chris@16
|
13 //
|
Chris@16
|
14 // Functor for root finding algorithm:
|
Chris@16
|
15 //
|
Chris@16
|
16 template <class Dist>
|
Chris@16
|
17 struct distribution_quantile_finder
|
Chris@16
|
18 {
|
Chris@16
|
19 typedef typename Dist::value_type value_type;
|
Chris@16
|
20 typedef typename Dist::policy_type policy_type;
|
Chris@16
|
21
|
Chris@16
|
22 distribution_quantile_finder(const Dist d, value_type p, bool c)
|
Chris@16
|
23 : dist(d), target(p), comp(c) {}
|
Chris@16
|
24
|
Chris@16
|
25 value_type operator()(value_type const& x)
|
Chris@16
|
26 {
|
Chris@16
|
27 return comp ? value_type(target - cdf(complement(dist, x))) : value_type(cdf(dist, x) - target);
|
Chris@16
|
28 }
|
Chris@16
|
29
|
Chris@16
|
30 private:
|
Chris@16
|
31 Dist dist;
|
Chris@16
|
32 value_type target;
|
Chris@16
|
33 bool comp;
|
Chris@16
|
34 };
|
Chris@16
|
35 //
|
Chris@16
|
36 // The purpose of adjust_bounds, is to toggle the last bit of the
|
Chris@16
|
37 // range so that both ends round to the same integer, if possible.
|
Chris@16
|
38 // If they do both round the same then we terminate the search
|
Chris@16
|
39 // for the root *very* quickly when finding an integer result.
|
Chris@16
|
40 // At the point that this function is called we know that "a" is
|
Chris@16
|
41 // below the root and "b" above it, so this change can not result
|
Chris@16
|
42 // in the root no longer being bracketed.
|
Chris@16
|
43 //
|
Chris@16
|
44 template <class Real, class Tol>
|
Chris@16
|
45 void adjust_bounds(Real& /* a */, Real& /* b */, Tol const& /* tol */){}
|
Chris@16
|
46
|
Chris@16
|
47 template <class Real>
|
Chris@16
|
48 void adjust_bounds(Real& /* a */, Real& b, tools::equal_floor const& /* tol */)
|
Chris@16
|
49 {
|
Chris@16
|
50 BOOST_MATH_STD_USING
|
Chris@16
|
51 b -= tools::epsilon<Real>() * b;
|
Chris@16
|
52 }
|
Chris@16
|
53
|
Chris@16
|
54 template <class Real>
|
Chris@16
|
55 void adjust_bounds(Real& a, Real& /* b */, tools::equal_ceil const& /* tol */)
|
Chris@16
|
56 {
|
Chris@16
|
57 BOOST_MATH_STD_USING
|
Chris@16
|
58 a += tools::epsilon<Real>() * a;
|
Chris@16
|
59 }
|
Chris@16
|
60
|
Chris@16
|
61 template <class Real>
|
Chris@16
|
62 void adjust_bounds(Real& a, Real& b, tools::equal_nearest_integer const& /* tol */)
|
Chris@16
|
63 {
|
Chris@16
|
64 BOOST_MATH_STD_USING
|
Chris@16
|
65 a += tools::epsilon<Real>() * a;
|
Chris@16
|
66 b -= tools::epsilon<Real>() * b;
|
Chris@16
|
67 }
|
Chris@16
|
68 //
|
Chris@16
|
69 // This is where all the work is done:
|
Chris@16
|
70 //
|
Chris@16
|
71 template <class Dist, class Tolerance>
|
Chris@16
|
72 typename Dist::value_type
|
Chris@16
|
73 do_inverse_discrete_quantile(
|
Chris@16
|
74 const Dist& dist,
|
Chris@16
|
75 const typename Dist::value_type& p,
|
Chris@16
|
76 bool comp,
|
Chris@16
|
77 typename Dist::value_type guess,
|
Chris@16
|
78 const typename Dist::value_type& multiplier,
|
Chris@16
|
79 typename Dist::value_type adder,
|
Chris@16
|
80 const Tolerance& tol,
|
Chris@16
|
81 boost::uintmax_t& max_iter)
|
Chris@16
|
82 {
|
Chris@16
|
83 typedef typename Dist::value_type value_type;
|
Chris@16
|
84 typedef typename Dist::policy_type policy_type;
|
Chris@16
|
85
|
Chris@16
|
86 static const char* function = "boost::math::do_inverse_discrete_quantile<%1%>";
|
Chris@16
|
87
|
Chris@16
|
88 BOOST_MATH_STD_USING
|
Chris@16
|
89
|
Chris@16
|
90 distribution_quantile_finder<Dist> f(dist, p, comp);
|
Chris@16
|
91 //
|
Chris@16
|
92 // Max bounds of the distribution:
|
Chris@16
|
93 //
|
Chris@16
|
94 value_type min_bound, max_bound;
|
Chris@16
|
95 boost::math::tie(min_bound, max_bound) = support(dist);
|
Chris@16
|
96
|
Chris@16
|
97 if(guess > max_bound)
|
Chris@16
|
98 guess = max_bound;
|
Chris@16
|
99 if(guess < min_bound)
|
Chris@16
|
100 guess = min_bound;
|
Chris@16
|
101
|
Chris@16
|
102 value_type fa = f(guess);
|
Chris@16
|
103 boost::uintmax_t count = max_iter - 1;
|
Chris@16
|
104 value_type fb(fa), a(guess), b =0; // Compiler warning C4701: potentially uninitialized local variable 'b' used
|
Chris@16
|
105
|
Chris@16
|
106 if(fa == 0)
|
Chris@16
|
107 return guess;
|
Chris@16
|
108
|
Chris@16
|
109 //
|
Chris@16
|
110 // For small expected results, just use a linear search:
|
Chris@16
|
111 //
|
Chris@16
|
112 if(guess < 10)
|
Chris@16
|
113 {
|
Chris@16
|
114 b = a;
|
Chris@16
|
115 while((a < 10) && (fa * fb >= 0))
|
Chris@16
|
116 {
|
Chris@16
|
117 if(fb <= 0)
|
Chris@16
|
118 {
|
Chris@16
|
119 a = b;
|
Chris@16
|
120 b = a + 1;
|
Chris@16
|
121 if(b > max_bound)
|
Chris@16
|
122 b = max_bound;
|
Chris@16
|
123 fb = f(b);
|
Chris@16
|
124 --count;
|
Chris@16
|
125 if(fb == 0)
|
Chris@16
|
126 return b;
|
Chris@16
|
127 if(a == b)
|
Chris@16
|
128 return b; // can't go any higher!
|
Chris@16
|
129 }
|
Chris@16
|
130 else
|
Chris@16
|
131 {
|
Chris@16
|
132 b = a;
|
Chris@16
|
133 a = (std::max)(value_type(b - 1), value_type(0));
|
Chris@16
|
134 if(a < min_bound)
|
Chris@16
|
135 a = min_bound;
|
Chris@16
|
136 fa = f(a);
|
Chris@16
|
137 --count;
|
Chris@16
|
138 if(fa == 0)
|
Chris@16
|
139 return a;
|
Chris@16
|
140 if(a == b)
|
Chris@16
|
141 return a; // We can't go any lower than this!
|
Chris@16
|
142 }
|
Chris@16
|
143 }
|
Chris@16
|
144 }
|
Chris@16
|
145 //
|
Chris@16
|
146 // Try and bracket using a couple of additions first,
|
Chris@16
|
147 // we're assuming that "guess" is likely to be accurate
|
Chris@16
|
148 // to the nearest int or so:
|
Chris@16
|
149 //
|
Chris@16
|
150 else if(adder != 0)
|
Chris@16
|
151 {
|
Chris@16
|
152 //
|
Chris@16
|
153 // If we're looking for a large result, then bump "adder" up
|
Chris@16
|
154 // by a bit to increase our chances of bracketing the root:
|
Chris@16
|
155 //
|
Chris@16
|
156 //adder = (std::max)(adder, 0.001f * guess);
|
Chris@16
|
157 if(fa < 0)
|
Chris@16
|
158 {
|
Chris@16
|
159 b = a + adder;
|
Chris@16
|
160 if(b > max_bound)
|
Chris@16
|
161 b = max_bound;
|
Chris@16
|
162 }
|
Chris@16
|
163 else
|
Chris@16
|
164 {
|
Chris@16
|
165 b = (std::max)(value_type(a - adder), value_type(0));
|
Chris@16
|
166 if(b < min_bound)
|
Chris@16
|
167 b = min_bound;
|
Chris@16
|
168 }
|
Chris@16
|
169 fb = f(b);
|
Chris@16
|
170 --count;
|
Chris@16
|
171 if(fb == 0)
|
Chris@16
|
172 return b;
|
Chris@16
|
173 if(count && (fa * fb >= 0))
|
Chris@16
|
174 {
|
Chris@16
|
175 //
|
Chris@16
|
176 // We didn't bracket the root, try
|
Chris@16
|
177 // once more:
|
Chris@16
|
178 //
|
Chris@16
|
179 a = b;
|
Chris@16
|
180 fa = fb;
|
Chris@16
|
181 if(fa < 0)
|
Chris@16
|
182 {
|
Chris@16
|
183 b = a + adder;
|
Chris@16
|
184 if(b > max_bound)
|
Chris@16
|
185 b = max_bound;
|
Chris@16
|
186 }
|
Chris@16
|
187 else
|
Chris@16
|
188 {
|
Chris@16
|
189 b = (std::max)(value_type(a - adder), value_type(0));
|
Chris@16
|
190 if(b < min_bound)
|
Chris@16
|
191 b = min_bound;
|
Chris@16
|
192 }
|
Chris@16
|
193 fb = f(b);
|
Chris@16
|
194 --count;
|
Chris@16
|
195 }
|
Chris@16
|
196 if(a > b)
|
Chris@16
|
197 {
|
Chris@16
|
198 using std::swap;
|
Chris@16
|
199 swap(a, b);
|
Chris@16
|
200 swap(fa, fb);
|
Chris@16
|
201 }
|
Chris@16
|
202 }
|
Chris@16
|
203 //
|
Chris@16
|
204 // If the root hasn't been bracketed yet, try again
|
Chris@16
|
205 // using the multiplier this time:
|
Chris@16
|
206 //
|
Chris@16
|
207 if((boost::math::sign)(fb) == (boost::math::sign)(fa))
|
Chris@16
|
208 {
|
Chris@16
|
209 if(fa < 0)
|
Chris@16
|
210 {
|
Chris@16
|
211 //
|
Chris@16
|
212 // Zero is to the right of x2, so walk upwards
|
Chris@16
|
213 // until we find it:
|
Chris@16
|
214 //
|
Chris@16
|
215 while(((boost::math::sign)(fb) == (boost::math::sign)(fa)) && (a != b))
|
Chris@16
|
216 {
|
Chris@16
|
217 if(count == 0)
|
Chris@101
|
218 return policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", b, policy_type());
|
Chris@16
|
219 a = b;
|
Chris@16
|
220 fa = fb;
|
Chris@16
|
221 b *= multiplier;
|
Chris@16
|
222 if(b > max_bound)
|
Chris@16
|
223 b = max_bound;
|
Chris@16
|
224 fb = f(b);
|
Chris@16
|
225 --count;
|
Chris@16
|
226 BOOST_MATH_INSTRUMENT_CODE("a = " << a << " b = " << b << " fa = " << fa << " fb = " << fb << " count = " << count);
|
Chris@16
|
227 }
|
Chris@16
|
228 }
|
Chris@16
|
229 else
|
Chris@16
|
230 {
|
Chris@16
|
231 //
|
Chris@16
|
232 // Zero is to the left of a, so walk downwards
|
Chris@16
|
233 // until we find it:
|
Chris@16
|
234 //
|
Chris@16
|
235 while(((boost::math::sign)(fb) == (boost::math::sign)(fa)) && (a != b))
|
Chris@16
|
236 {
|
Chris@16
|
237 if(fabs(a) < tools::min_value<value_type>())
|
Chris@16
|
238 {
|
Chris@16
|
239 // Escape route just in case the answer is zero!
|
Chris@16
|
240 max_iter -= count;
|
Chris@16
|
241 max_iter += 1;
|
Chris@16
|
242 return 0;
|
Chris@16
|
243 }
|
Chris@16
|
244 if(count == 0)
|
Chris@101
|
245 return policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", a, policy_type());
|
Chris@16
|
246 b = a;
|
Chris@16
|
247 fb = fa;
|
Chris@16
|
248 a /= multiplier;
|
Chris@16
|
249 if(a < min_bound)
|
Chris@16
|
250 a = min_bound;
|
Chris@16
|
251 fa = f(a);
|
Chris@16
|
252 --count;
|
Chris@16
|
253 BOOST_MATH_INSTRUMENT_CODE("a = " << a << " b = " << b << " fa = " << fa << " fb = " << fb << " count = " << count);
|
Chris@16
|
254 }
|
Chris@16
|
255 }
|
Chris@16
|
256 }
|
Chris@16
|
257 max_iter -= count;
|
Chris@16
|
258 if(fa == 0)
|
Chris@16
|
259 return a;
|
Chris@16
|
260 if(fb == 0)
|
Chris@16
|
261 return b;
|
Chris@16
|
262 if(a == b)
|
Chris@16
|
263 return b; // Ran out of bounds trying to bracket - there is no answer!
|
Chris@16
|
264 //
|
Chris@16
|
265 // Adjust bounds so that if we're looking for an integer
|
Chris@16
|
266 // result, then both ends round the same way:
|
Chris@16
|
267 //
|
Chris@16
|
268 adjust_bounds(a, b, tol);
|
Chris@16
|
269 //
|
Chris@16
|
270 // We don't want zero or denorm lower bounds:
|
Chris@16
|
271 //
|
Chris@16
|
272 if(a < tools::min_value<value_type>())
|
Chris@16
|
273 a = tools::min_value<value_type>();
|
Chris@16
|
274 //
|
Chris@16
|
275 // Go ahead and find the root:
|
Chris@16
|
276 //
|
Chris@16
|
277 std::pair<value_type, value_type> r = toms748_solve(f, a, b, fa, fb, tol, count, policy_type());
|
Chris@16
|
278 max_iter += count;
|
Chris@16
|
279 BOOST_MATH_INSTRUMENT_CODE("max_iter = " << max_iter << " count = " << count);
|
Chris@16
|
280 return (r.first + r.second) / 2;
|
Chris@16
|
281 }
|
Chris@16
|
282 //
|
Chris@16
|
283 // Some special routine for rounding up and down:
|
Chris@16
|
284 // We want to check and see if we are very close to an integer, and if so test to see if
|
Chris@16
|
285 // that integer is an exact root of the cdf. We do this because our root finder only
|
Chris@16
|
286 // guarantees to find *a root*, and there can sometimes be many consecutive floating
|
Chris@16
|
287 // point values which are all roots. This is especially true if the target probability
|
Chris@16
|
288 // is very close 1.
|
Chris@16
|
289 //
|
Chris@16
|
290 template <class Dist>
|
Chris@16
|
291 inline typename Dist::value_type round_to_floor(const Dist& d, typename Dist::value_type result, typename Dist::value_type p, bool c)
|
Chris@16
|
292 {
|
Chris@16
|
293 BOOST_MATH_STD_USING
|
Chris@16
|
294 typename Dist::value_type cc = ceil(result);
|
Chris@16
|
295 typename Dist::value_type pp = cc <= support(d).second ? c ? cdf(complement(d, cc)) : cdf(d, cc) : 1;
|
Chris@16
|
296 if(pp == p)
|
Chris@16
|
297 result = cc;
|
Chris@16
|
298 else
|
Chris@16
|
299 result = floor(result);
|
Chris@16
|
300 //
|
Chris@16
|
301 // Now find the smallest integer <= result for which we get an exact root:
|
Chris@16
|
302 //
|
Chris@16
|
303 while(result != 0)
|
Chris@16
|
304 {
|
Chris@16
|
305 cc = result - 1;
|
Chris@16
|
306 if(cc < support(d).first)
|
Chris@16
|
307 break;
|
Chris@101
|
308 pp = c ? cdf(complement(d, cc)) : cdf(d, cc);
|
Chris@16
|
309 if(pp == p)
|
Chris@16
|
310 result = cc;
|
Chris@16
|
311 else if(c ? pp > p : pp < p)
|
Chris@16
|
312 break;
|
Chris@16
|
313 result -= 1;
|
Chris@16
|
314 }
|
Chris@16
|
315
|
Chris@16
|
316 return result;
|
Chris@16
|
317 }
|
Chris@101
|
318
|
Chris@101
|
319 #ifdef BOOST_MSVC
|
Chris@101
|
320 #pragma warning(push)
|
Chris@101
|
321 #pragma warning(disable:4127)
|
Chris@101
|
322 #endif
|
Chris@101
|
323
|
Chris@16
|
324 template <class Dist>
|
Chris@16
|
325 inline typename Dist::value_type round_to_ceil(const Dist& d, typename Dist::value_type result, typename Dist::value_type p, bool c)
|
Chris@16
|
326 {
|
Chris@16
|
327 BOOST_MATH_STD_USING
|
Chris@16
|
328 typename Dist::value_type cc = floor(result);
|
Chris@16
|
329 typename Dist::value_type pp = cc >= support(d).first ? c ? cdf(complement(d, cc)) : cdf(d, cc) : 0;
|
Chris@16
|
330 if(pp == p)
|
Chris@16
|
331 result = cc;
|
Chris@16
|
332 else
|
Chris@16
|
333 result = ceil(result);
|
Chris@16
|
334 //
|
Chris@16
|
335 // Now find the largest integer >= result for which we get an exact root:
|
Chris@16
|
336 //
|
Chris@16
|
337 while(true)
|
Chris@16
|
338 {
|
Chris@16
|
339 cc = result + 1;
|
Chris@16
|
340 if(cc > support(d).second)
|
Chris@16
|
341 break;
|
Chris@101
|
342 pp = c ? cdf(complement(d, cc)) : cdf(d, cc);
|
Chris@16
|
343 if(pp == p)
|
Chris@16
|
344 result = cc;
|
Chris@16
|
345 else if(c ? pp < p : pp > p)
|
Chris@16
|
346 break;
|
Chris@16
|
347 result += 1;
|
Chris@16
|
348 }
|
Chris@16
|
349
|
Chris@16
|
350 return result;
|
Chris@16
|
351 }
|
Chris@101
|
352
|
Chris@101
|
353 #ifdef BOOST_MSVC
|
Chris@101
|
354 #pragma warning(pop)
|
Chris@101
|
355 #endif
|
Chris@16
|
356 //
|
Chris@16
|
357 // Now finally are the public API functions.
|
Chris@16
|
358 // There is one overload for each policy,
|
Chris@16
|
359 // each one is responsible for selecting the correct
|
Chris@16
|
360 // termination condition, and rounding the result
|
Chris@16
|
361 // to an int where required.
|
Chris@16
|
362 //
|
Chris@16
|
363 template <class Dist>
|
Chris@16
|
364 inline typename Dist::value_type
|
Chris@16
|
365 inverse_discrete_quantile(
|
Chris@16
|
366 const Dist& dist,
|
Chris@16
|
367 typename Dist::value_type p,
|
Chris@16
|
368 bool c,
|
Chris@16
|
369 const typename Dist::value_type& guess,
|
Chris@16
|
370 const typename Dist::value_type& multiplier,
|
Chris@16
|
371 const typename Dist::value_type& adder,
|
Chris@16
|
372 const policies::discrete_quantile<policies::real>&,
|
Chris@16
|
373 boost::uintmax_t& max_iter)
|
Chris@16
|
374 {
|
Chris@16
|
375 if(p > 0.5)
|
Chris@16
|
376 {
|
Chris@16
|
377 p = 1 - p;
|
Chris@16
|
378 c = !c;
|
Chris@16
|
379 }
|
Chris@16
|
380 typename Dist::value_type pp = c ? 1 - p : p;
|
Chris@16
|
381 if(pp <= pdf(dist, 0))
|
Chris@16
|
382 return 0;
|
Chris@16
|
383 return do_inverse_discrete_quantile(
|
Chris@16
|
384 dist,
|
Chris@16
|
385 p,
|
Chris@16
|
386 c,
|
Chris@16
|
387 guess,
|
Chris@16
|
388 multiplier,
|
Chris@16
|
389 adder,
|
Chris@16
|
390 tools::eps_tolerance<typename Dist::value_type>(policies::digits<typename Dist::value_type, typename Dist::policy_type>()),
|
Chris@16
|
391 max_iter);
|
Chris@16
|
392 }
|
Chris@16
|
393
|
Chris@16
|
394 template <class Dist>
|
Chris@16
|
395 inline typename Dist::value_type
|
Chris@16
|
396 inverse_discrete_quantile(
|
Chris@16
|
397 const Dist& dist,
|
Chris@16
|
398 const typename Dist::value_type& p,
|
Chris@16
|
399 bool c,
|
Chris@16
|
400 const typename Dist::value_type& guess,
|
Chris@16
|
401 const typename Dist::value_type& multiplier,
|
Chris@16
|
402 const typename Dist::value_type& adder,
|
Chris@16
|
403 const policies::discrete_quantile<policies::integer_round_outwards>&,
|
Chris@16
|
404 boost::uintmax_t& max_iter)
|
Chris@16
|
405 {
|
Chris@16
|
406 typedef typename Dist::value_type value_type;
|
Chris@16
|
407 BOOST_MATH_STD_USING
|
Chris@16
|
408 typename Dist::value_type pp = c ? 1 - p : p;
|
Chris@16
|
409 if(pp <= pdf(dist, 0))
|
Chris@16
|
410 return 0;
|
Chris@16
|
411 //
|
Chris@16
|
412 // What happens next depends on whether we're looking for an
|
Chris@16
|
413 // upper or lower quantile:
|
Chris@16
|
414 //
|
Chris@16
|
415 if(pp < 0.5f)
|
Chris@16
|
416 return round_to_floor(dist, do_inverse_discrete_quantile(
|
Chris@16
|
417 dist,
|
Chris@16
|
418 p,
|
Chris@16
|
419 c,
|
Chris@16
|
420 (guess < 1 ? value_type(1) : (value_type)floor(guess)),
|
Chris@16
|
421 multiplier,
|
Chris@16
|
422 adder,
|
Chris@16
|
423 tools::equal_floor(),
|
Chris@16
|
424 max_iter), p, c);
|
Chris@16
|
425 // else:
|
Chris@16
|
426 return round_to_ceil(dist, do_inverse_discrete_quantile(
|
Chris@16
|
427 dist,
|
Chris@16
|
428 p,
|
Chris@16
|
429 c,
|
Chris@16
|
430 (value_type)ceil(guess),
|
Chris@16
|
431 multiplier,
|
Chris@16
|
432 adder,
|
Chris@16
|
433 tools::equal_ceil(),
|
Chris@16
|
434 max_iter), p, c);
|
Chris@16
|
435 }
|
Chris@16
|
436
|
Chris@16
|
437 template <class Dist>
|
Chris@16
|
438 inline typename Dist::value_type
|
Chris@16
|
439 inverse_discrete_quantile(
|
Chris@16
|
440 const Dist& dist,
|
Chris@16
|
441 const typename Dist::value_type& p,
|
Chris@16
|
442 bool c,
|
Chris@16
|
443 const typename Dist::value_type& guess,
|
Chris@16
|
444 const typename Dist::value_type& multiplier,
|
Chris@16
|
445 const typename Dist::value_type& adder,
|
Chris@16
|
446 const policies::discrete_quantile<policies::integer_round_inwards>&,
|
Chris@16
|
447 boost::uintmax_t& max_iter)
|
Chris@16
|
448 {
|
Chris@16
|
449 typedef typename Dist::value_type value_type;
|
Chris@16
|
450 BOOST_MATH_STD_USING
|
Chris@16
|
451 typename Dist::value_type pp = c ? 1 - p : p;
|
Chris@16
|
452 if(pp <= pdf(dist, 0))
|
Chris@16
|
453 return 0;
|
Chris@16
|
454 //
|
Chris@16
|
455 // What happens next depends on whether we're looking for an
|
Chris@16
|
456 // upper or lower quantile:
|
Chris@16
|
457 //
|
Chris@16
|
458 if(pp < 0.5f)
|
Chris@16
|
459 return round_to_ceil(dist, do_inverse_discrete_quantile(
|
Chris@16
|
460 dist,
|
Chris@16
|
461 p,
|
Chris@16
|
462 c,
|
Chris@16
|
463 ceil(guess),
|
Chris@16
|
464 multiplier,
|
Chris@16
|
465 adder,
|
Chris@16
|
466 tools::equal_ceil(),
|
Chris@16
|
467 max_iter), p, c);
|
Chris@16
|
468 // else:
|
Chris@16
|
469 return round_to_floor(dist, do_inverse_discrete_quantile(
|
Chris@16
|
470 dist,
|
Chris@16
|
471 p,
|
Chris@16
|
472 c,
|
Chris@16
|
473 (guess < 1 ? value_type(1) : floor(guess)),
|
Chris@16
|
474 multiplier,
|
Chris@16
|
475 adder,
|
Chris@16
|
476 tools::equal_floor(),
|
Chris@16
|
477 max_iter), p, c);
|
Chris@16
|
478 }
|
Chris@16
|
479
|
Chris@16
|
480 template <class Dist>
|
Chris@16
|
481 inline typename Dist::value_type
|
Chris@16
|
482 inverse_discrete_quantile(
|
Chris@16
|
483 const Dist& dist,
|
Chris@16
|
484 const typename Dist::value_type& p,
|
Chris@16
|
485 bool c,
|
Chris@16
|
486 const typename Dist::value_type& guess,
|
Chris@16
|
487 const typename Dist::value_type& multiplier,
|
Chris@16
|
488 const typename Dist::value_type& adder,
|
Chris@16
|
489 const policies::discrete_quantile<policies::integer_round_down>&,
|
Chris@16
|
490 boost::uintmax_t& max_iter)
|
Chris@16
|
491 {
|
Chris@16
|
492 typedef typename Dist::value_type value_type;
|
Chris@16
|
493 BOOST_MATH_STD_USING
|
Chris@16
|
494 typename Dist::value_type pp = c ? 1 - p : p;
|
Chris@16
|
495 if(pp <= pdf(dist, 0))
|
Chris@16
|
496 return 0;
|
Chris@16
|
497 return round_to_floor(dist, do_inverse_discrete_quantile(
|
Chris@16
|
498 dist,
|
Chris@16
|
499 p,
|
Chris@16
|
500 c,
|
Chris@16
|
501 (guess < 1 ? value_type(1) : floor(guess)),
|
Chris@16
|
502 multiplier,
|
Chris@16
|
503 adder,
|
Chris@16
|
504 tools::equal_floor(),
|
Chris@16
|
505 max_iter), p, c);
|
Chris@16
|
506 }
|
Chris@16
|
507
|
Chris@16
|
508 template <class Dist>
|
Chris@16
|
509 inline typename Dist::value_type
|
Chris@16
|
510 inverse_discrete_quantile(
|
Chris@16
|
511 const Dist& dist,
|
Chris@16
|
512 const typename Dist::value_type& p,
|
Chris@16
|
513 bool c,
|
Chris@16
|
514 const typename Dist::value_type& guess,
|
Chris@16
|
515 const typename Dist::value_type& multiplier,
|
Chris@16
|
516 const typename Dist::value_type& adder,
|
Chris@16
|
517 const policies::discrete_quantile<policies::integer_round_up>&,
|
Chris@16
|
518 boost::uintmax_t& max_iter)
|
Chris@16
|
519 {
|
Chris@16
|
520 BOOST_MATH_STD_USING
|
Chris@16
|
521 typename Dist::value_type pp = c ? 1 - p : p;
|
Chris@16
|
522 if(pp <= pdf(dist, 0))
|
Chris@16
|
523 return 0;
|
Chris@16
|
524 return round_to_ceil(dist, do_inverse_discrete_quantile(
|
Chris@16
|
525 dist,
|
Chris@16
|
526 p,
|
Chris@16
|
527 c,
|
Chris@16
|
528 ceil(guess),
|
Chris@16
|
529 multiplier,
|
Chris@16
|
530 adder,
|
Chris@16
|
531 tools::equal_ceil(),
|
Chris@16
|
532 max_iter), p, c);
|
Chris@16
|
533 }
|
Chris@16
|
534
|
Chris@16
|
535 template <class Dist>
|
Chris@16
|
536 inline typename Dist::value_type
|
Chris@16
|
537 inverse_discrete_quantile(
|
Chris@16
|
538 const Dist& dist,
|
Chris@16
|
539 const typename Dist::value_type& p,
|
Chris@16
|
540 bool c,
|
Chris@16
|
541 const typename Dist::value_type& guess,
|
Chris@16
|
542 const typename Dist::value_type& multiplier,
|
Chris@16
|
543 const typename Dist::value_type& adder,
|
Chris@16
|
544 const policies::discrete_quantile<policies::integer_round_nearest>&,
|
Chris@16
|
545 boost::uintmax_t& max_iter)
|
Chris@16
|
546 {
|
Chris@16
|
547 typedef typename Dist::value_type value_type;
|
Chris@16
|
548 BOOST_MATH_STD_USING
|
Chris@16
|
549 typename Dist::value_type pp = c ? 1 - p : p;
|
Chris@16
|
550 if(pp <= pdf(dist, 0))
|
Chris@16
|
551 return 0;
|
Chris@16
|
552 //
|
Chris@16
|
553 // Note that we adjust the guess to the nearest half-integer:
|
Chris@16
|
554 // this increase the chances that we will bracket the root
|
Chris@16
|
555 // with two results that both round to the same integer quickly.
|
Chris@16
|
556 //
|
Chris@16
|
557 return round_to_floor(dist, do_inverse_discrete_quantile(
|
Chris@16
|
558 dist,
|
Chris@16
|
559 p,
|
Chris@16
|
560 c,
|
Chris@16
|
561 (guess < 0.5f ? value_type(1.5f) : floor(guess + 0.5f) + 0.5f),
|
Chris@16
|
562 multiplier,
|
Chris@16
|
563 adder,
|
Chris@16
|
564 tools::equal_nearest_integer(),
|
Chris@16
|
565 max_iter) + 0.5f, p, c);
|
Chris@16
|
566 }
|
Chris@16
|
567
|
Chris@16
|
568 }}} // namespaces
|
Chris@16
|
569
|
Chris@16
|
570 #endif // BOOST_MATH_DISTRIBUTIONS_DETAIL_INV_DISCRETE_QUANTILE
|
Chris@16
|
571
|