File indexing completed on 2025-06-30 08:18:23
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_MATH_SPECIAL_NON_CENTRAL_BETA_HPP
0011 #define BOOST_MATH_SPECIAL_NON_CENTRAL_BETA_HPP
0012
0013 #include <boost/math/distributions/fwd.hpp>
0014 #include <boost/math/special_functions/beta.hpp> // for incomplete gamma. gamma_q
0015 #include <boost/math/distributions/complement.hpp> // complements
0016 #include <boost/math/distributions/beta.hpp> // central distribution
0017 #include <boost/math/distributions/detail/generic_mode.hpp>
0018 #include <boost/math/distributions/detail/common_error_handling.hpp> // error checks
0019 #include <boost/math/special_functions/fpclassify.hpp> // isnan.
0020 #include <boost/math/special_functions/trunc.hpp>
0021 #include <boost/math/tools/roots.hpp> // for root finding.
0022 #include <boost/math/tools/series.hpp>
0023
0024 namespace boost
0025 {
0026 namespace math
0027 {
0028
0029 template <class RealType, class Policy>
0030 class non_central_beta_distribution;
0031
0032 namespace detail{
0033
0034 template <class T, class Policy>
0035 T non_central_beta_p(T a, T b, T lam, T x, T y, const Policy& pol, T init_val = 0)
0036 {
0037 BOOST_MATH_STD_USING
0038 using namespace boost::math;
0039
0040
0041
0042 std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
0043 T errtol = boost::math::policies::get_epsilon<T, Policy>();
0044 T l2 = lam / 2;
0045
0046
0047
0048
0049
0050
0051
0052 long long k = lltrunc(l2);
0053 if(k == 0)
0054 k = 1;
0055
0056 T pois = gamma_p_derivative(T(k+1), l2, pol);
0057 if(pois == 0)
0058 return init_val;
0059
0060 T xterm;
0061
0062 T beta = x < y
0063 ? detail::ibeta_imp(T(a + k), b, x, pol, false, true, &xterm)
0064 : detail::ibeta_imp(b, T(a + k), y, pol, true, true, &xterm);
0065
0066 while (fabs(beta * pois) < tools::min_value<T>())
0067 {
0068 if ((k == 0) || (pois == 0))
0069 return init_val;
0070 k /= 2;
0071 pois = gamma_p_derivative(T(k + 1), l2, pol);
0072 beta = x < y
0073 ? detail::ibeta_imp(T(a + k), b, x, pol, false, true, &xterm)
0074 : detail::ibeta_imp(b, T(a + k), y, pol, true, true, &xterm);
0075 }
0076
0077 xterm *= y / (a + b + k - 1);
0078 T poisf(pois), betaf(beta), xtermf(xterm);
0079 T sum = init_val;
0080
0081 if((beta == 0) && (xterm == 0))
0082 return init_val;
0083
0084
0085
0086
0087
0088 T last_term = 0;
0089 std::uintmax_t count = k;
0090 for(auto i = k; i >= 0; --i)
0091 {
0092 T term = beta * pois;
0093 sum += term;
0094 if(((fabs(term/sum) < errtol) && (fabs(last_term) >= fabs(term))) || (term == 0))
0095 {
0096 count = k - i;
0097 break;
0098 }
0099 pois *= i / l2;
0100 beta += xterm;
0101
0102 if (a + b + i != 2)
0103 {
0104 xterm *= (a + i - 1) / (x * (a + b + i - 2));
0105 }
0106
0107 last_term = term;
0108 }
0109 last_term = 0;
0110 for(auto i = k + 1; ; ++i)
0111 {
0112 poisf *= l2 / i;
0113 xtermf *= (x * (a + b + i - 2)) / (a + i - 1);
0114 betaf -= xtermf;
0115
0116 T term = poisf * betaf;
0117 sum += term;
0118 if(((fabs(term/sum) < errtol) && (fabs(last_term) >= fabs(term))) || (term == 0))
0119 {
0120 break;
0121 }
0122 last_term = term;
0123 if(static_cast<std::uintmax_t>(count + i - k) > max_iter)
0124 {
0125 return policies::raise_evaluation_error("cdf(non_central_beta_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol);
0126 }
0127 }
0128 return sum;
0129 }
0130
0131 template <class T, class Policy>
0132 T non_central_beta_q(T a, T b, T lam, T x, T y, const Policy& pol, T init_val = 0)
0133 {
0134 BOOST_MATH_STD_USING
0135 using namespace boost::math;
0136
0137
0138
0139 std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
0140 T errtol = boost::math::policies::get_epsilon<T, Policy>();
0141 T l2 = lam / 2;
0142
0143
0144
0145
0146 long long k = lltrunc(l2);
0147 T pois;
0148 if(k <= 30)
0149 {
0150
0151
0152
0153 if(a + b > 1)
0154 k = 0;
0155 else if(k == 0)
0156 k = 1;
0157 }
0158 if(k == 0)
0159 {
0160
0161 pois = exp(-l2);
0162 }
0163 else
0164 {
0165
0166 pois = gamma_p_derivative(T(k+1), l2, pol);
0167 }
0168 if(pois == 0)
0169 return init_val;
0170
0171 T xterm;
0172
0173 T beta = x < y
0174 ? detail::ibeta_imp(T(a + k), b, x, pol, true, true, &xterm)
0175 : detail::ibeta_imp(b, T(a + k), y, pol, false, true, &xterm);
0176
0177 xterm *= y / (a + b + k - 1);
0178 T poisf(pois), betaf(beta), xtermf(xterm);
0179 T sum = init_val;
0180 if((beta == 0) && (xterm == 0))
0181 return init_val;
0182
0183
0184
0185
0186
0187 T last_term = 0;
0188 std::uintmax_t count = 0;
0189 for(auto i = k + 1; ; ++i)
0190 {
0191 poisf *= l2 / i;
0192 xtermf *= (x * (a + b + i - 2)) / (a + i - 1);
0193 betaf += xtermf;
0194
0195 T term = poisf * betaf;
0196 sum += term;
0197 if((fabs(term/sum) < errtol) && (last_term >= term))
0198 {
0199 count = i - k;
0200 break;
0201 }
0202 if(static_cast<std::uintmax_t>(i - k) > max_iter)
0203 {
0204 return policies::raise_evaluation_error("cdf(non_central_beta_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol);
0205 }
0206 last_term = term;
0207 }
0208 for(auto i = k; i >= 0; --i)
0209 {
0210 T term = beta * pois;
0211 sum += term;
0212 if(fabs(term/sum) < errtol)
0213 {
0214 break;
0215 }
0216 if(static_cast<std::uintmax_t>(count + k - i) > max_iter)
0217 {
0218 return policies::raise_evaluation_error("cdf(non_central_beta_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol);
0219 }
0220 pois *= i / l2;
0221 beta -= xterm;
0222 if (a + b + i - 2 != 0)
0223 {
0224 xterm *= (a + i - 1) / (x * (a + b + i - 2));
0225 }
0226 }
0227 return sum;
0228 }
0229
0230 template <class RealType, class Policy>
0231 inline RealType non_central_beta_cdf(RealType x, RealType y, RealType a, RealType b, RealType l, bool invert, const Policy&)
0232 {
0233 typedef typename policies::evaluation<RealType, Policy>::type value_type;
0234 typedef typename policies::normalise<
0235 Policy,
0236 policies::promote_float<false>,
0237 policies::promote_double<false>,
0238 policies::discrete_quantile<>,
0239 policies::assert_undefined<> >::type forwarding_policy;
0240
0241 BOOST_MATH_STD_USING
0242
0243 if(x == 0)
0244 return invert ? 1.0f : 0.0f;
0245 if(y == 0)
0246 return invert ? 0.0f : 1.0f;
0247 value_type result;
0248 value_type c = a + b + l / 2;
0249 value_type cross = 1 - (b / c) * (1 + l / (2 * c * c));
0250 if(l == 0)
0251 result = cdf(boost::math::beta_distribution<RealType, Policy>(a, b), x);
0252 else if(x > cross)
0253 {
0254
0255 result = detail::non_central_beta_q(
0256 static_cast<value_type>(a),
0257 static_cast<value_type>(b),
0258 static_cast<value_type>(l),
0259 static_cast<value_type>(x),
0260 static_cast<value_type>(y),
0261 forwarding_policy(),
0262 static_cast<value_type>(invert ? 0 : -1));
0263 invert = !invert;
0264 }
0265 else
0266 {
0267 result = detail::non_central_beta_p(
0268 static_cast<value_type>(a),
0269 static_cast<value_type>(b),
0270 static_cast<value_type>(l),
0271 static_cast<value_type>(x),
0272 static_cast<value_type>(y),
0273 forwarding_policy(),
0274 static_cast<value_type>(invert ? -1 : 0));
0275 }
0276 if(invert)
0277 result = -result;
0278 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
0279 result,
0280 "boost::math::non_central_beta_cdf<%1%>(%1%, %1%, %1%)");
0281 }
0282
0283 template <class T, class Policy>
0284 struct nc_beta_quantile_functor
0285 {
0286 nc_beta_quantile_functor(const non_central_beta_distribution<T,Policy>& d, T t, bool c)
0287 : dist(d), target(t), comp(c) {}
0288
0289 T operator()(const T& x)
0290 {
0291 return comp ?
0292 T(target - cdf(complement(dist, x)))
0293 : T(cdf(dist, x) - target);
0294 }
0295
0296 private:
0297 non_central_beta_distribution<T,Policy> dist;
0298 T target;
0299 bool comp;
0300 };
0301
0302
0303
0304
0305
0306
0307 template <class F, class T, class Tol, class Policy>
0308 std::pair<T, T> bracket_and_solve_root_01(F f, const T& guess, T factor, bool rising, Tol tol, std::uintmax_t& max_iter, const Policy& pol)
0309 {
0310 BOOST_MATH_STD_USING
0311 static const char* function = "boost::math::tools::bracket_and_solve_root_01<%1%>";
0312
0313
0314
0315 T a = guess;
0316 T b = a;
0317 T fa = f(a);
0318 T fb = fa;
0319
0320
0321
0322 std::uintmax_t count = max_iter - 1;
0323
0324 if((fa < 0) == (guess < 0 ? !rising : rising))
0325 {
0326
0327
0328
0329
0330 while((boost::math::sign)(fb) == (boost::math::sign)(fa))
0331 {
0332 if(count == 0)
0333 {
0334 b = policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", b, pol);
0335 return std::make_pair(a, b);
0336 }
0337
0338
0339
0340
0341 if((max_iter - count) % 20 == 0)
0342 factor *= 2;
0343
0344
0345
0346
0347 a = b;
0348 fa = fb;
0349 b = 1 - ((1 - b) / factor);
0350 fb = f(b);
0351 --count;
0352 BOOST_MATH_INSTRUMENT_CODE("a = " << a << " b = " << b << " fa = " << fa << " fb = " << fb << " count = " << count);
0353 }
0354 }
0355 else
0356 {
0357
0358
0359
0360
0361 while((boost::math::sign)(fb) == (boost::math::sign)(fa))
0362 {
0363 if(fabs(a) < tools::min_value<T>())
0364 {
0365
0366 max_iter -= count;
0367 max_iter += 1;
0368 return a > 0 ? std::make_pair(T(0), T(a)) : std::make_pair(T(a), T(0));
0369 }
0370 if(count == 0)
0371 {
0372 a = policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", a, pol);
0373 return std::make_pair(a, b);
0374 }
0375
0376
0377
0378
0379 if((max_iter - count) % 20 == 0)
0380 factor *= 2;
0381
0382
0383
0384 b = a;
0385 fb = fa;
0386 a /= factor;
0387 fa = f(a);
0388 --count;
0389 BOOST_MATH_INSTRUMENT_CODE("a = " << a << " b = " << b << " fa = " << fa << " fb = " << fb << " count = " << count);
0390 }
0391 }
0392 max_iter -= count;
0393 max_iter += 1;
0394 std::pair<T, T> r = toms748_solve(
0395 f,
0396 (a < 0 ? b : a),
0397 (a < 0 ? a : b),
0398 (a < 0 ? fb : fa),
0399 (a < 0 ? fa : fb),
0400 tol,
0401 count,
0402 pol);
0403 max_iter += count;
0404 BOOST_MATH_INSTRUMENT_CODE("max_iter = " << max_iter << " count = " << count);
0405 return r;
0406 }
0407
0408 template <class RealType, class Policy>
0409 RealType nc_beta_quantile(const non_central_beta_distribution<RealType, Policy>& dist, const RealType& p, bool comp)
0410 {
0411 static const char* function = "quantile(non_central_beta_distribution<%1%>, %1%)";
0412 typedef typename policies::evaluation<RealType, Policy>::type value_type;
0413 typedef typename policies::normalise<
0414 Policy,
0415 policies::promote_float<false>,
0416 policies::promote_double<false>,
0417 policies::discrete_quantile<>,
0418 policies::assert_undefined<> >::type forwarding_policy;
0419
0420 value_type a = dist.alpha();
0421 value_type b = dist.beta();
0422 value_type l = dist.non_centrality();
0423 value_type r;
0424 if(!beta_detail::check_alpha(
0425 function,
0426 a, &r, Policy())
0427 ||
0428 !beta_detail::check_beta(
0429 function,
0430 b, &r, Policy())
0431 ||
0432 !detail::check_non_centrality(
0433 function,
0434 l,
0435 &r,
0436 Policy())
0437 ||
0438 !detail::check_probability(
0439 function,
0440 static_cast<value_type>(p),
0441 &r,
0442 Policy()))
0443 return static_cast<RealType>(r);
0444
0445
0446
0447 if(p == 0)
0448 return comp
0449 ? 1.0f
0450 : 0.0f;
0451 if(p == 1)
0452 return !comp
0453 ? 1.0f
0454 : 0.0f;
0455
0456 value_type c = a + b + l / 2;
0457 value_type mean = 1 - (b / c) * (1 + l / (2 * c * c));
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504 value_type guess = mean;
0505 detail::nc_beta_quantile_functor<value_type, Policy>
0506 f(non_central_beta_distribution<value_type, Policy>(a, b, l), p, comp);
0507 tools::eps_tolerance<value_type> tol(policies::digits<RealType, Policy>());
0508 std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
0509
0510 std::pair<value_type, value_type> ir
0511 = bracket_and_solve_root_01(
0512 f, guess, value_type(2.5), true, tol,
0513 max_iter, Policy());
0514 value_type result = ir.first + (ir.second - ir.first) / 2;
0515
0516 if(max_iter >= policies::get_max_root_iterations<Policy>())
0517 {
0518
0519 return policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
0520 " either there is no answer to quantile of the non central beta distribution"
0521 " or the answer is infinite. Current best guess is %1%",
0522 policies::checked_narrowing_cast<RealType, forwarding_policy>(
0523 result,
0524 function), Policy());
0525
0526 }
0527 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
0528 result,
0529 function);
0530 }
0531
0532 template <class T, class Policy>
0533 T non_central_beta_pdf(T a, T b, T lam, T x, T y, const Policy& pol)
0534 {
0535 BOOST_MATH_STD_USING
0536
0537
0538
0539 if((x == 0) || (y == 0))
0540 return 0;
0541
0542
0543
0544 std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
0545 T errtol = boost::math::policies::get_epsilon<T, Policy>();
0546 T l2 = lam / 2;
0547
0548
0549
0550
0551 long long k = lltrunc(l2);
0552
0553 T pois = gamma_p_derivative(T(k+1), l2, pol);
0554
0555 T beta = x < y ?
0556 ibeta_derivative(a + k, b, x, pol)
0557 : ibeta_derivative(b, a + k, y, pol);
0558
0559 while (fabs(beta * pois) < tools::min_value<T>())
0560 {
0561 if ((k == 0) || (pois == 0))
0562 return 0;
0563
0564
0565
0566
0567 k /= 2;
0568 pois = gamma_p_derivative(T(k + 1), l2, pol);
0569
0570 beta = x < y ?
0571 ibeta_derivative(a + k, b, x, pol)
0572 : ibeta_derivative(b, a + k, y, pol);
0573 }
0574
0575
0576 T sum = 0;
0577 T poisf(pois);
0578 T betaf(beta);
0579
0580
0581
0582
0583 std::uintmax_t count = k;
0584 T ratio = 0;
0585 T old_ratio = 0;
0586 for(auto i = k; i >= 0; --i)
0587 {
0588 T term = beta * pois;
0589 sum += term;
0590 ratio = fabs(term / sum);
0591 if(((ratio < errtol) && (ratio < old_ratio)) || (term == 0))
0592 {
0593 count = k - i;
0594 break;
0595 }
0596 ratio = old_ratio;
0597 pois *= i / l2;
0598
0599 if (a + b + i != 1)
0600 {
0601 beta *= (a + i - 1) / (x * (a + i + b - 1));
0602 }
0603 }
0604 old_ratio = 0;
0605 for(auto i = k + 1; ; ++i)
0606 {
0607 poisf *= l2 / i;
0608 betaf *= x * (a + b + i - 1) / (a + i - 1);
0609
0610 T term = poisf * betaf;
0611 sum += term;
0612 ratio = fabs(term / sum);
0613 if(((ratio < errtol) && (ratio < old_ratio)) || (term == 0))
0614 {
0615 break;
0616 }
0617 old_ratio = ratio;
0618 if(static_cast<std::uintmax_t>(count + i - k) > max_iter)
0619 {
0620 return policies::raise_evaluation_error("pdf(non_central_beta_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol);
0621 }
0622 }
0623 return sum;
0624 }
0625
0626 template <class RealType, class Policy>
0627 RealType nc_beta_pdf(const non_central_beta_distribution<RealType, Policy>& dist, const RealType& x)
0628 {
0629 BOOST_MATH_STD_USING
0630 static const char* function = "pdf(non_central_beta_distribution<%1%>, %1%)";
0631 typedef typename policies::evaluation<RealType, Policy>::type value_type;
0632 typedef typename policies::normalise<
0633 Policy,
0634 policies::promote_float<false>,
0635 policies::promote_double<false>,
0636 policies::discrete_quantile<>,
0637 policies::assert_undefined<> >::type forwarding_policy;
0638
0639 value_type a = dist.alpha();
0640 value_type b = dist.beta();
0641 value_type l = dist.non_centrality();
0642 value_type r;
0643 if(!beta_detail::check_alpha(
0644 function,
0645 a, &r, Policy())
0646 ||
0647 !beta_detail::check_beta(
0648 function,
0649 b, &r, Policy())
0650 ||
0651 !detail::check_non_centrality(
0652 function,
0653 l,
0654 &r,
0655 Policy())
0656 ||
0657 !beta_detail::check_x(
0658 function,
0659 static_cast<value_type>(x),
0660 &r,
0661 Policy()))
0662 return static_cast<RealType>(r);
0663
0664 if(l == 0)
0665 return pdf(boost::math::beta_distribution<RealType, Policy>(dist.alpha(), dist.beta()), x);
0666 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
0667 non_central_beta_pdf(a, b, l, static_cast<value_type>(x), value_type(1 - static_cast<value_type>(x)), forwarding_policy()),
0668 "function");
0669 }
0670
0671 template <class T>
0672 struct hypergeometric_2F2_sum
0673 {
0674 typedef T result_type;
0675 hypergeometric_2F2_sum(T a1_, T a2_, T b1_, T b2_, T z_) : a1(a1_), a2(a2_), b1(b1_), b2(b2_), z(z_), term(1), k(0) {}
0676 T operator()()
0677 {
0678 T result = term;
0679 term *= a1 * a2 / (b1 * b2);
0680 a1 += 1;
0681 a2 += 1;
0682 b1 += 1;
0683 b2 += 1;
0684 k += 1;
0685 term /= k;
0686 term *= z;
0687 return result;
0688 }
0689 T a1, a2, b1, b2, z, term, k;
0690 };
0691
0692 template <class T, class Policy>
0693 T hypergeometric_2F2(T a1, T a2, T b1, T b2, T z, const Policy& pol)
0694 {
0695 typedef typename policies::evaluation<T, Policy>::type value_type;
0696
0697 const char* function = "boost::math::detail::hypergeometric_2F2<%1%>(%1%,%1%,%1%,%1%,%1%)";
0698
0699 hypergeometric_2F2_sum<value_type> s(a1, a2, b1, b2, z);
0700 std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
0701
0702 value_type result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<value_type, Policy>(), max_iter);
0703
0704 policies::check_series_iterations<T>(function, max_iter, pol);
0705 return policies::checked_narrowing_cast<T, Policy>(result, function);
0706 }
0707
0708 }
0709
0710 template <class RealType = double, class Policy = policies::policy<> >
0711 class non_central_beta_distribution
0712 {
0713 public:
0714 typedef RealType value_type;
0715 typedef Policy policy_type;
0716
0717 non_central_beta_distribution(RealType a_, RealType b_, RealType lambda) : a(a_), b(b_), ncp(lambda)
0718 {
0719 const char* function = "boost::math::non_central_beta_distribution<%1%>::non_central_beta_distribution(%1%,%1%)";
0720 RealType r;
0721 beta_detail::check_alpha(
0722 function,
0723 a, &r, Policy());
0724 beta_detail::check_beta(
0725 function,
0726 b, &r, Policy());
0727 detail::check_non_centrality(
0728 function,
0729 lambda,
0730 &r,
0731 Policy());
0732 }
0733
0734 RealType alpha() const
0735 {
0736 return a;
0737 }
0738 RealType beta() const
0739 {
0740 return b;
0741 }
0742 RealType non_centrality() const
0743 {
0744 return ncp;
0745 }
0746 private:
0747
0748 RealType a;
0749 RealType b;
0750 RealType ncp;
0751 };
0752
0753 typedef non_central_beta_distribution<double> non_central_beta;
0754
0755 #ifdef __cpp_deduction_guides
0756 template <class RealType>
0757 non_central_beta_distribution(RealType,RealType,RealType)->non_central_beta_distribution<typename boost::math::tools::promote_args<RealType>::type>;
0758 #endif
0759
0760
0761
0762 template <class RealType, class Policy>
0763 inline const std::pair<RealType, RealType> range(const non_central_beta_distribution<RealType, Policy>& )
0764 {
0765 using boost::math::tools::max_value;
0766 return std::pair<RealType, RealType>(static_cast<RealType>(0), static_cast<RealType>(1));
0767 }
0768
0769 template <class RealType, class Policy>
0770 inline const std::pair<RealType, RealType> support(const non_central_beta_distribution<RealType, Policy>& )
0771 {
0772
0773 using boost::math::tools::max_value;
0774 return std::pair<RealType, RealType>(static_cast<RealType>(0), static_cast<RealType>(1));
0775 }
0776
0777 template <class RealType, class Policy>
0778 inline RealType mode(const non_central_beta_distribution<RealType, Policy>& dist)
0779 {
0780 static const char* function = "mode(non_central_beta_distribution<%1%> const&)";
0781
0782 RealType a = dist.alpha();
0783 RealType b = dist.beta();
0784 RealType l = dist.non_centrality();
0785 RealType r;
0786 if(!beta_detail::check_alpha(
0787 function,
0788 a, &r, Policy())
0789 ||
0790 !beta_detail::check_beta(
0791 function,
0792 b, &r, Policy())
0793 ||
0794 !detail::check_non_centrality(
0795 function,
0796 l,
0797 &r,
0798 Policy()))
0799 return static_cast<RealType>(r);
0800 RealType c = a + b + l / 2;
0801 RealType mean = 1 - (b / c) * (1 + l / (2 * c * c));
0802 return detail::generic_find_mode_01(
0803 dist,
0804 mean,
0805 function);
0806 }
0807
0808
0809
0810
0811
0812
0813
0814 template <class RealType, class Policy>
0815 inline RealType mean(const non_central_beta_distribution<RealType, Policy>& dist)
0816 {
0817 BOOST_MATH_STD_USING
0818 RealType a = dist.alpha();
0819 RealType b = dist.beta();
0820 RealType d = dist.non_centrality();
0821 RealType apb = a + b;
0822 return exp(-d / 2) * a * detail::hypergeometric_2F2<RealType, Policy>(1 + a, apb, a, 1 + apb, d / 2, Policy()) / apb;
0823 }
0824
0825 template <class RealType, class Policy>
0826 inline RealType variance(const non_central_beta_distribution<RealType, Policy>& dist)
0827 {
0828
0829
0830
0831
0832 BOOST_MATH_STD_USING
0833 RealType a = dist.alpha();
0834 RealType b = dist.beta();
0835 RealType d = dist.non_centrality();
0836 RealType apb = a + b;
0837 RealType result = detail::hypergeometric_2F2(RealType(1 + a), apb, a, RealType(1 + apb), RealType(d / 2), Policy());
0838 result *= result * -exp(-d) * a * a / (apb * apb);
0839 result += exp(-d / 2) * a * (1 + a) * detail::hypergeometric_2F2(RealType(2 + a), apb, a, RealType(2 + apb), RealType(d / 2), Policy()) / (apb * (1 + apb));
0840 return result;
0841 }
0842
0843
0844
0845 template <class RealType, class Policy>
0846 inline RealType skewness(const non_central_beta_distribution<RealType, Policy>& )
0847 {
0848 const char* function = "boost::math::non_central_beta_distribution<%1%>::skewness()";
0849 typedef typename Policy::assert_undefined_type assert_type;
0850 static_assert(assert_type::value == 0, "Assert type is undefined.");
0851
0852 return policies::raise_evaluation_error<RealType>(function, "This function is not yet implemented, the only sensible result is %1%.",
0853 std::numeric_limits<RealType>::quiet_NaN(), Policy());
0854 }
0855
0856 template <class RealType, class Policy>
0857 inline RealType kurtosis_excess(const non_central_beta_distribution<RealType, Policy>& )
0858 {
0859 const char* function = "boost::math::non_central_beta_distribution<%1%>::kurtosis_excess()";
0860 typedef typename Policy::assert_undefined_type assert_type;
0861 static_assert(assert_type::value == 0, "Assert type is undefined.");
0862
0863 return policies::raise_evaluation_error<RealType>(function, "This function is not yet implemented, the only sensible result is %1%.",
0864 std::numeric_limits<RealType>::quiet_NaN(), Policy());
0865 }
0866
0867 template <class RealType, class Policy>
0868 inline RealType kurtosis(const non_central_beta_distribution<RealType, Policy>& dist)
0869 {
0870 return kurtosis_excess(dist) + 3;
0871 }
0872
0873 template <class RealType, class Policy>
0874 inline RealType pdf(const non_central_beta_distribution<RealType, Policy>& dist, const RealType& x)
0875 {
0876 return detail::nc_beta_pdf(dist, x);
0877 }
0878
0879 template <class RealType, class Policy>
0880 RealType cdf(const non_central_beta_distribution<RealType, Policy>& dist, const RealType& x)
0881 {
0882 const char* function = "boost::math::non_central_beta_distribution<%1%>::cdf(%1%)";
0883 RealType a = dist.alpha();
0884 RealType b = dist.beta();
0885 RealType l = dist.non_centrality();
0886 RealType r;
0887 if(!beta_detail::check_alpha(
0888 function,
0889 a, &r, Policy())
0890 ||
0891 !beta_detail::check_beta(
0892 function,
0893 b, &r, Policy())
0894 ||
0895 !detail::check_non_centrality(
0896 function,
0897 l,
0898 &r,
0899 Policy())
0900 ||
0901 !beta_detail::check_x(
0902 function,
0903 x,
0904 &r,
0905 Policy()))
0906 return static_cast<RealType>(r);
0907
0908 if(l == 0)
0909 return cdf(beta_distribution<RealType, Policy>(a, b), x);
0910
0911 return detail::non_central_beta_cdf(x, RealType(1 - x), a, b, l, false, Policy());
0912 }
0913
0914 template <class RealType, class Policy>
0915 RealType cdf(const complemented2_type<non_central_beta_distribution<RealType, Policy>, RealType>& c)
0916 {
0917 const char* function = "boost::math::non_central_beta_distribution<%1%>::cdf(%1%)";
0918 non_central_beta_distribution<RealType, Policy> const& dist = c.dist;
0919 RealType a = dist.alpha();
0920 RealType b = dist.beta();
0921 RealType l = dist.non_centrality();
0922 RealType x = c.param;
0923 RealType r;
0924 if(!beta_detail::check_alpha(
0925 function,
0926 a, &r, Policy())
0927 ||
0928 !beta_detail::check_beta(
0929 function,
0930 b, &r, Policy())
0931 ||
0932 !detail::check_non_centrality(
0933 function,
0934 l,
0935 &r,
0936 Policy())
0937 ||
0938 !beta_detail::check_x(
0939 function,
0940 x,
0941 &r,
0942 Policy()))
0943 return static_cast<RealType>(r);
0944
0945 if(l == 0)
0946 return cdf(complement(beta_distribution<RealType, Policy>(a, b), x));
0947
0948 return detail::non_central_beta_cdf(x, RealType(1 - x), a, b, l, true, Policy());
0949 }
0950
0951 template <class RealType, class Policy>
0952 inline RealType quantile(const non_central_beta_distribution<RealType, Policy>& dist, const RealType& p)
0953 {
0954 return detail::nc_beta_quantile(dist, p, false);
0955 }
0956
0957 template <class RealType, class Policy>
0958 inline RealType quantile(const complemented2_type<non_central_beta_distribution<RealType, Policy>, RealType>& c)
0959 {
0960 return detail::nc_beta_quantile(c.dist, c.param, true);
0961 }
0962
0963 }
0964 }
0965
0966
0967
0968
0969 #include <boost/math/distributions/detail/derived_accessors.hpp>
0970
0971 #endif
0972