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