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