Ticket #9183: math-discrete-distro.patch
File math-discrete-distro.patch, 15.7 KB (added by , 9 years ago) |
---|
-
math/distributions/binomial.hpp
196 196 } 197 197 198 198 template <class RealType, class Policy> 199 RealType quantile_imp(const binomial_distribution<RealType, Policy>& dist, const RealType& p, const RealType& q )199 RealType quantile_imp(const binomial_distribution<RealType, Policy>& dist, const RealType& p, const RealType& q, bool comp) 200 200 { // Quantile or Percent Point Binomial function. 201 201 // Return the number of expected successes k, 202 202 // for a given probability p. … … 264 264 boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>(); 265 265 return detail::inverse_discrete_quantile( 266 266 dist, 267 p,268 q,267 comp ? q : p, 268 comp, 269 269 guess, 270 270 factor, 271 271 RealType(1), … … 653 653 template <class RealType, class Policy> 654 654 inline RealType quantile(const binomial_distribution<RealType, Policy>& dist, const RealType& p) 655 655 { 656 return binomial_detail::quantile_imp(dist, p, RealType(1-p) );656 return binomial_detail::quantile_imp(dist, p, RealType(1-p), false); 657 657 } // quantile 658 658 659 659 template <class RealType, class Policy> 660 660 RealType quantile(const complemented2_type<binomial_distribution<RealType, Policy>, RealType>& c) 661 661 { 662 return binomial_detail::quantile_imp(c.dist, RealType(1-c.param), c.param );662 return binomial_detail::quantile_imp(c.dist, RealType(1-c.param), c.param, true); 663 663 } // quantile 664 664 665 665 template <class RealType, class Policy> -
math/distributions/detail/inv_discrete_quantile.hpp
19 19 typedef typename Dist::value_type value_type; 20 20 typedef typename Dist::policy_type policy_type; 21 21 22 distribution_quantile_finder(const Dist d, value_type p, value_type q)23 : dist(d), target(p < q ? p : q), comp(p < q ? false : true) {}22 distribution_quantile_finder(const Dist d, value_type p, bool c) 23 : dist(d), target(p), comp(c) {} 24 24 25 25 value_type operator()(value_type const& x) 26 26 { … … 73 73 do_inverse_discrete_quantile( 74 74 const Dist& dist, 75 75 const typename Dist::value_type& p, 76 const typename Dist::value_type& q,76 bool comp, 77 77 typename Dist::value_type guess, 78 78 const typename Dist::value_type& multiplier, 79 79 typename Dist::value_type adder, … … 87 87 88 88 BOOST_MATH_STD_USING 89 89 90 distribution_quantile_finder<Dist> f(dist, p, q);90 distribution_quantile_finder<Dist> f(dist, p, comp); 91 91 // 92 92 // Max bounds of the distribution: 93 93 // … … 280 280 return (r.first + r.second) / 2; 281 281 } 282 282 // 283 // Some special routine for rounding up and down: 284 // We want to check and see if we are very close to an integer, and if so test to see if 285 // that integer is an exact root of the cdf. We do this because our root finder only 286 // guarantees to find *a root*, and there can sometimes be many consecutive floating 287 // point values which are all roots. This is especially true if the target probability 288 // is very close 1. 289 // 290 template <class Dist> 291 inline typename Dist::value_type round_to_floor(const Dist& d, typename Dist::value_type result, typename Dist::value_type p, bool c) 292 { 293 BOOST_MATH_STD_USING 294 typename Dist::value_type cc = ceil(result); 295 typename Dist::value_type pp = cc <= support(d).second ? c ? cdf(complement(d, cc)) : cdf(d, cc) : 1; 296 if(pp == p) 297 result = cc; 298 else 299 result = floor(result); 300 // 301 // Now find the smallest integer <= result for which we get an exact root: 302 // 303 while(result != 0) 304 { 305 cc = result - 1; 306 if(cc < support(d).first) 307 break; 308 typename Dist::value_type pp = c ? cdf(complement(d, cc)) : cdf(d, cc); 309 if(pp == p) 310 result = cc; 311 else if(c ? pp > p : pp < p) 312 break; 313 result -= 1; 314 } 315 316 return result; 317 } 318 template <class Dist> 319 inline typename Dist::value_type round_to_ceil(const Dist& d, typename Dist::value_type result, typename Dist::value_type p, bool c) 320 { 321 BOOST_MATH_STD_USING 322 typename Dist::value_type cc = floor(result); 323 typename Dist::value_type pp = cc >= support(d).first ? c ? cdf(complement(d, cc)) : cdf(d, cc) : 0; 324 if(pp == p) 325 result = cc; 326 else 327 result = ceil(result); 328 // 329 // Now find the largest integer >= result for which we get an exact root: 330 // 331 while(true) 332 { 333 cc = result + 1; 334 if(cc > support(d).second) 335 break; 336 typename Dist::value_type pp = c ? cdf(complement(d, cc)) : cdf(d, cc); 337 if(pp == p) 338 result = cc; 339 else if(c ? pp < p : pp > p) 340 break; 341 result += 1; 342 } 343 344 return result; 345 } 346 // 283 347 // Now finally are the public API functions. 284 348 // There is one overload for each policy, 285 349 // each one is responsible for selecting the correct … … 290 354 inline typename Dist::value_type 291 355 inverse_discrete_quantile( 292 356 const Dist& dist, 293 const typename Dist::value_type&p,294 const typename Dist::value_type& q,357 typename Dist::value_type p, 358 bool c, 295 359 const typename Dist::value_type& guess, 296 360 const typename Dist::value_type& multiplier, 297 361 const typename Dist::value_type& adder, 298 362 const policies::discrete_quantile<policies::real>&, 299 363 boost::uintmax_t& max_iter) 300 364 { 301 if(p <= pdf(dist, 0)) 365 if(p > 0.5) 366 { 367 p = 1 - p; 368 c = !c; 369 } 370 typename Dist::value_type pp = c ? 1 - p : p; 371 if(pp <= pdf(dist, 0)) 302 372 return 0; 303 373 return do_inverse_discrete_quantile( 304 374 dist, 305 375 p, 306 q,376 c, 307 377 guess, 308 378 multiplier, 309 379 adder, … … 316 386 inverse_discrete_quantile( 317 387 const Dist& dist, 318 388 const typename Dist::value_type& p, 319 const typename Dist::value_type& q,389 bool c, 320 390 const typename Dist::value_type& guess, 321 391 const typename Dist::value_type& multiplier, 322 392 const typename Dist::value_type& adder, … … 325 395 { 326 396 typedef typename Dist::value_type value_type; 327 397 BOOST_MATH_STD_USING 328 if(p <= pdf(dist, 0)) 398 typename Dist::value_type pp = c ? 1 - p : p; 399 if(pp <= pdf(dist, 0)) 329 400 return 0; 330 401 // 331 402 // What happens next depends on whether we're looking for an 332 403 // upper or lower quantile: 333 404 // 334 if(p < 0.5f)335 return floor(do_inverse_discrete_quantile(405 if(pp < 0.5f) 406 return round_to_floor(dist, do_inverse_discrete_quantile( 336 407 dist, 337 408 p, 338 q,409 c, 339 410 (guess < 1 ? value_type(1) : (value_type)floor(guess)), 340 411 multiplier, 341 412 adder, 342 413 tools::equal_floor(), 343 max_iter) );414 max_iter), p, c); 344 415 // else: 345 return ceil(do_inverse_discrete_quantile(416 return round_to_ceil(dist, do_inverse_discrete_quantile( 346 417 dist, 347 418 p, 348 q,419 c, 349 420 (value_type)ceil(guess), 350 421 multiplier, 351 422 adder, 352 423 tools::equal_ceil(), 353 max_iter) );424 max_iter), p, c); 354 425 } 355 426 356 427 template <class Dist> … … 358 429 inverse_discrete_quantile( 359 430 const Dist& dist, 360 431 const typename Dist::value_type& p, 361 const typename Dist::value_type& q,432 bool c, 362 433 const typename Dist::value_type& guess, 363 434 const typename Dist::value_type& multiplier, 364 435 const typename Dist::value_type& adder, … … 367 438 { 368 439 typedef typename Dist::value_type value_type; 369 440 BOOST_MATH_STD_USING 370 if(p <= pdf(dist, 0)) 441 typename Dist::value_type pp = c ? 1 - p : p; 442 if(pp <= pdf(dist, 0)) 371 443 return 0; 372 444 // 373 445 // What happens next depends on whether we're looking for an 374 446 // upper or lower quantile: 375 447 // 376 if(p < 0.5f)377 return ceil(do_inverse_discrete_quantile(448 if(pp < 0.5f) 449 return round_to_ceil(dist, do_inverse_discrete_quantile( 378 450 dist, 379 451 p, 380 q,452 c, 381 453 ceil(guess), 382 454 multiplier, 383 455 adder, 384 456 tools::equal_ceil(), 385 max_iter) );457 max_iter), p, c); 386 458 // else: 387 return floor(do_inverse_discrete_quantile(459 return round_to_floor(dist, do_inverse_discrete_quantile( 388 460 dist, 389 461 p, 390 q,462 c, 391 463 (guess < 1 ? value_type(1) : floor(guess)), 392 464 multiplier, 393 465 adder, 394 466 tools::equal_floor(), 395 max_iter) );467 max_iter), p, c); 396 468 } 397 469 398 470 template <class Dist> … … 400 472 inverse_discrete_quantile( 401 473 const Dist& dist, 402 474 const typename Dist::value_type& p, 403 const typename Dist::value_type& q,475 bool c, 404 476 const typename Dist::value_type& guess, 405 477 const typename Dist::value_type& multiplier, 406 478 const typename Dist::value_type& adder, … … 409 481 { 410 482 typedef typename Dist::value_type value_type; 411 483 BOOST_MATH_STD_USING 412 if(p <= pdf(dist, 0)) 484 typename Dist::value_type pp = c ? 1 - p : p; 485 if(pp <= pdf(dist, 0)) 413 486 return 0; 414 return floor(do_inverse_discrete_quantile(487 return round_to_floor(dist, do_inverse_discrete_quantile( 415 488 dist, 416 489 p, 417 q,490 c, 418 491 (guess < 1 ? value_type(1) : floor(guess)), 419 492 multiplier, 420 493 adder, 421 494 tools::equal_floor(), 422 max_iter) );495 max_iter), p, c); 423 496 } 424 497 425 498 template <class Dist> … … 427 500 inverse_discrete_quantile( 428 501 const Dist& dist, 429 502 const typename Dist::value_type& p, 430 const typename Dist::value_type& q,503 bool c, 431 504 const typename Dist::value_type& guess, 432 505 const typename Dist::value_type& multiplier, 433 506 const typename Dist::value_type& adder, … … 435 508 boost::uintmax_t& max_iter) 436 509 { 437 510 BOOST_MATH_STD_USING 438 if(p <= pdf(dist, 0)) 511 typename Dist::value_type pp = c ? 1 - p : p; 512 if(pp <= pdf(dist, 0)) 439 513 return 0; 440 return ceil(do_inverse_discrete_quantile(514 return round_to_ceil(dist, do_inverse_discrete_quantile( 441 515 dist, 442 516 p, 443 q,517 c, 444 518 ceil(guess), 445 519 multiplier, 446 520 adder, 447 521 tools::equal_ceil(), 448 max_iter) );522 max_iter), p, c); 449 523 } 450 524 451 525 template <class Dist> … … 453 527 inverse_discrete_quantile( 454 528 const Dist& dist, 455 529 const typename Dist::value_type& p, 456 const typename Dist::value_type& q,530 bool c, 457 531 const typename Dist::value_type& guess, 458 532 const typename Dist::value_type& multiplier, 459 533 const typename Dist::value_type& adder, … … 462 536 { 463 537 typedef typename Dist::value_type value_type; 464 538 BOOST_MATH_STD_USING 465 if(p <= pdf(dist, 0)) 539 typename Dist::value_type pp = c ? 1 - p : p; 540 if(pp <= pdf(dist, 0)) 466 541 return 0; 467 542 // 468 543 // Note that we adjust the guess to the nearest half-integer: 469 544 // this increase the chances that we will bracket the root 470 545 // with two results that both round to the same integer quickly. 471 546 // 472 return floor(do_inverse_discrete_quantile(547 return round_to_floor(dist, do_inverse_discrete_quantile( 473 548 dist, 474 549 p, 475 q,550 c, 476 551 (guess < 0.5f ? value_type(1.5f) : floor(guess + 0.5f) + 0.5f), 477 552 multiplier, 478 553 adder, 479 554 tools::equal_nearest_integer(), 480 max_iter) + 0.5f );555 max_iter) + 0.5f, p, c); 481 556 } 482 557 483 558 }}} // namespaces 484 559 485 560 #endif // BOOST_MATH_DISTRIBUTIONS_DETAIL_INV_DISCRETE_QUANTILE 486 561 487 -
math/distributions/negative_binomial.hpp
488 488 return detail::inverse_discrete_quantile( 489 489 dist, 490 490 P, 491 1-P,491 false, 492 492 guess, 493 493 factor, 494 494 RealType(1), … … 564 564 typedef typename Policy::discrete_quantile_type discrete_type; 565 565 return detail::inverse_discrete_quantile( 566 566 dist, 567 1-Q,568 567 Q, 568 true, 569 569 guess, 570 570 factor, 571 571 RealType(1), -
math/distributions/poisson.hpp
52 52 { 53 53 namespace math 54 54 { 55 namespace detail{56 template <class Dist>57 inline typename Dist::value_type58 inverse_discrete_quantile(59 const Dist& dist,60 const typename Dist::value_type& p,61 const typename Dist::value_type& guess,62 const typename Dist::value_type& multiplier,63 const typename Dist::value_type& adder,64 const policies::discrete_quantile<policies::integer_round_nearest>&,65 boost::uintmax_t& max_iter);66 template <class Dist>67 inline typename Dist::value_type68 inverse_discrete_quantile(69 const Dist& dist,70 const typename Dist::value_type& p,71 const typename Dist::value_type& guess,72 const typename Dist::value_type& multiplier,73 const typename Dist::value_type& adder,74 const policies::discrete_quantile<policies::integer_round_up>&,75 boost::uintmax_t& max_iter);76 template <class Dist>77 inline typename Dist::value_type78 inverse_discrete_quantile(79 const Dist& dist,80 const typename Dist::value_type& p,81 const typename Dist::value_type& guess,82 const typename Dist::value_type& multiplier,83 const typename Dist::value_type& adder,84 const policies::discrete_quantile<policies::integer_round_down>&,85 boost::uintmax_t& max_iter);86 template <class Dist>87 inline typename Dist::value_type88 inverse_discrete_quantile(89 const Dist& dist,90 const typename Dist::value_type& p,91 const typename Dist::value_type& guess,92 const typename Dist::value_type& multiplier,93 const typename Dist::value_type& adder,94 const policies::discrete_quantile<policies::integer_round_outwards>&,95 boost::uintmax_t& max_iter);96 template <class Dist>97 inline typename Dist::value_type98 inverse_discrete_quantile(99 const Dist& dist,100 const typename Dist::value_type& p,101 const typename Dist::value_type& guess,102 const typename Dist::value_type& multiplier,103 const typename Dist::value_type& adder,104 const policies::discrete_quantile<policies::integer_round_inwards>&,105 boost::uintmax_t& max_iter);106 template <class Dist>107 inline typename Dist::value_type108 inverse_discrete_quantile(109 const Dist& dist,110 const typename Dist::value_type& p,111 const typename Dist::value_type& guess,112 const typename Dist::value_type& multiplier,113 const typename Dist::value_type& adder,114 const policies::discrete_quantile<policies::real>&,115 boost::uintmax_t& max_iter);116 }117 55 namespace poisson_detail 118 56 { 119 57 // Common error checking routines for Poisson distribution functions. … … 496 434 return detail::inverse_discrete_quantile( 497 435 dist, 498 436 p, 499 1-p,437 false, 500 438 guess, 501 439 factor, 502 440 RealType(1), … … 565 503 566 504 return detail::inverse_discrete_quantile( 567 505 dist, 568 1-q,569 506 q, 507 true, 570 508 guess, 571 509 factor, 572 510 RealType(1),