File indexing completed on 2025-01-18 09:40:06
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef BOOST_MATH_SP_DETAIL_BETA_INV_AB
0014 #define BOOST_MATH_SP_DETAIL_BETA_INV_AB
0015
0016 #ifdef _MSC_VER
0017 #pragma once
0018 #endif
0019
0020 #include <cstdint>
0021 #include <utility>
0022 #include <boost/math/tools/toms748_solve.hpp>
0023
0024 namespace boost{ namespace math{ namespace detail{
0025
0026 template <class T, class Policy>
0027 struct beta_inv_ab_t
0028 {
0029 beta_inv_ab_t(T b_, T z_, T p_, bool invert_, bool swap_ab_) : b(b_), z(z_), p(p_), invert(invert_), swap_ab(swap_ab_) {}
0030 T operator()(T a)
0031 {
0032 return invert ?
0033 p - boost::math::ibetac(swap_ab ? b : a, swap_ab ? a : b, z, Policy())
0034 : boost::math::ibeta(swap_ab ? b : a, swap_ab ? a : b, z, Policy()) - p;
0035 }
0036 private:
0037 T b, z, p;
0038 bool invert, swap_ab;
0039 };
0040
0041 template <class T, class Policy>
0042 T inverse_negative_binomial_cornish_fisher(T n, T sf, T sfc, T p, T q, const Policy& pol)
0043 {
0044 BOOST_MATH_STD_USING
0045
0046 T m = n * (sfc) / sf;
0047 T t = sqrt(n * (sfc));
0048
0049 T sigma = t / sf;
0050
0051 T sk = (1 + sfc) / t;
0052
0053 T k = (6 - sf * (5+sfc)) / (n * (sfc));
0054
0055 T x = boost::math::erfc_inv(p > q ? 2 * q : 2 * p, pol) * constants::root_two<T>();
0056
0057 if(p < 0.5)
0058 x = -x;
0059 T x2 = x * x;
0060
0061 T w = x + sk * (x2 - 1) / 6;
0062
0063
0064
0065 if(n >= 10)
0066 w += k * x * (x2 - 3) / 24 + sk * sk * x * (2 * x2 - 5) / -36;
0067
0068 w = m + sigma * w;
0069 if(w < tools::min_value<T>())
0070 return tools::min_value<T>();
0071 return w;
0072 }
0073
0074 template <class T, class Policy>
0075 T ibeta_inv_ab_imp(const T& b, const T& z, const T& p, const T& q, bool swap_ab, const Policy& pol)
0076 {
0077 BOOST_MATH_STD_USING
0078
0079
0080
0081 BOOST_MATH_INSTRUMENT_CODE("b = " << b << " z = " << z << " p = " << p << " q = " << " swap = " << swap_ab);
0082 if(p == 0)
0083 {
0084 return swap_ab ? tools::min_value<T>() : tools::max_value<T>();
0085 }
0086 if(q == 0)
0087 {
0088 return swap_ab ? tools::max_value<T>() : tools::min_value<T>();
0089 }
0090
0091
0092
0093
0094 beta_inv_ab_t<T, Policy> f(b, z, (p < q) ? p : q, (p < q) ? false : true, swap_ab);
0095
0096
0097
0098 tools::eps_tolerance<T> tol(policies::digits<T, Policy>());
0099
0100
0101
0102
0103
0104
0105
0106 T guess = 0;
0107 T factor = 5;
0108
0109
0110
0111 T n = b;
0112 T sf = swap_ab ? z : 1-z;
0113 T sfc = swap_ab ? 1-z : z;
0114 T u = swap_ab ? p : q;
0115 T v = swap_ab ? q : p;
0116 if(u <= pow(sf, n))
0117 {
0118
0119
0120
0121
0122 if((p < q) != swap_ab)
0123 {
0124 guess = (std::min)(T(b * 2), T(1));
0125 }
0126 else
0127 {
0128 guess = (std::min)(T(b / 2), T(1));
0129 }
0130 }
0131 if(n * n * n * u * sf > 0.005)
0132 guess = 1 + inverse_negative_binomial_cornish_fisher(n, sf, sfc, u, v, pol);
0133
0134 if(guess < 10)
0135 {
0136
0137
0138
0139 if((p < q) != swap_ab)
0140 {
0141 guess = (std::min)(T(b * 2), T(10));
0142 }
0143 else
0144 {
0145 guess = (std::min)(T(b / 2), T(10));
0146 }
0147 }
0148 else
0149 factor = (v < sqrt(tools::epsilon<T>())) ? 2 : (guess < 20 ? 1.2f : 1.1f);
0150 BOOST_MATH_INSTRUMENT_CODE("guess = " << guess);
0151
0152
0153
0154 std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
0155 std::pair<T, T> r = bracket_and_solve_root(f, guess, factor, swap_ab ? true : false, tol, max_iter, pol);
0156 if(max_iter >= policies::get_max_root_iterations<Policy>())
0157 return policies::raise_evaluation_error<T>("boost::math::ibeta_invab_imp<%1%>(%1%,%1%,%1%)", "Unable to locate the root within a reasonable number of iterations, closest approximation so far was %1%", r.first, pol);
0158 return (r.first + r.second) / 2;
0159 }
0160
0161 }
0162
0163 template <class RT1, class RT2, class RT3, class Policy>
0164 typename tools::promote_args<RT1, RT2, RT3>::type
0165 ibeta_inva(RT1 b, RT2 x, RT3 p, const Policy& pol)
0166 {
0167 typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type;
0168 typedef typename policies::evaluation<result_type, Policy>::type value_type;
0169 typedef typename policies::normalise<
0170 Policy,
0171 policies::promote_float<false>,
0172 policies::promote_double<false>,
0173 policies::discrete_quantile<>,
0174 policies::assert_undefined<> >::type forwarding_policy;
0175
0176 static const char* function = "boost::math::ibeta_inva<%1%>(%1%,%1%,%1%)";
0177 if(p == 0)
0178 {
0179 return policies::raise_overflow_error<result_type>(function, 0, Policy());
0180 }
0181 if(p == 1)
0182 {
0183 return tools::min_value<result_type>();
0184 }
0185
0186 return policies::checked_narrowing_cast<result_type, forwarding_policy>(
0187 detail::ibeta_inv_ab_imp(
0188 static_cast<value_type>(b),
0189 static_cast<value_type>(x),
0190 static_cast<value_type>(p),
0191 static_cast<value_type>(1 - static_cast<value_type>(p)),
0192 false, pol),
0193 function);
0194 }
0195
0196 template <class RT1, class RT2, class RT3, class Policy>
0197 typename tools::promote_args<RT1, RT2, RT3>::type
0198 ibetac_inva(RT1 b, RT2 x, RT3 q, const Policy& pol)
0199 {
0200 typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type;
0201 typedef typename policies::evaluation<result_type, Policy>::type value_type;
0202 typedef typename policies::normalise<
0203 Policy,
0204 policies::promote_float<false>,
0205 policies::promote_double<false>,
0206 policies::discrete_quantile<>,
0207 policies::assert_undefined<> >::type forwarding_policy;
0208
0209 static const char* function = "boost::math::ibetac_inva<%1%>(%1%,%1%,%1%)";
0210 if(q == 1)
0211 {
0212 return policies::raise_overflow_error<result_type>(function, 0, Policy());
0213 }
0214 if(q == 0)
0215 {
0216 return tools::min_value<result_type>();
0217 }
0218
0219 return policies::checked_narrowing_cast<result_type, forwarding_policy>(
0220 detail::ibeta_inv_ab_imp(
0221 static_cast<value_type>(b),
0222 static_cast<value_type>(x),
0223 static_cast<value_type>(1 - static_cast<value_type>(q)),
0224 static_cast<value_type>(q),
0225 false, pol),
0226 function);
0227 }
0228
0229 template <class RT1, class RT2, class RT3, class Policy>
0230 typename tools::promote_args<RT1, RT2, RT3>::type
0231 ibeta_invb(RT1 a, RT2 x, RT3 p, const Policy& pol)
0232 {
0233 typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type;
0234 typedef typename policies::evaluation<result_type, Policy>::type value_type;
0235 typedef typename policies::normalise<
0236 Policy,
0237 policies::promote_float<false>,
0238 policies::promote_double<false>,
0239 policies::discrete_quantile<>,
0240 policies::assert_undefined<> >::type forwarding_policy;
0241
0242 static const char* function = "boost::math::ibeta_invb<%1%>(%1%,%1%,%1%)";
0243 if(p == 0)
0244 {
0245 return tools::min_value<result_type>();
0246 }
0247 if(p == 1)
0248 {
0249 return policies::raise_overflow_error<result_type>(function, 0, Policy());
0250 }
0251
0252 return policies::checked_narrowing_cast<result_type, forwarding_policy>(
0253 detail::ibeta_inv_ab_imp(
0254 static_cast<value_type>(a),
0255 static_cast<value_type>(x),
0256 static_cast<value_type>(p),
0257 static_cast<value_type>(1 - static_cast<value_type>(p)),
0258 true, pol),
0259 function);
0260 }
0261
0262 template <class RT1, class RT2, class RT3, class Policy>
0263 typename tools::promote_args<RT1, RT2, RT3>::type
0264 ibetac_invb(RT1 a, RT2 x, RT3 q, const Policy& pol)
0265 {
0266 static const char* function = "boost::math::ibeta_invb<%1%>(%1%, %1%, %1%)";
0267 typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type;
0268 typedef typename policies::evaluation<result_type, Policy>::type value_type;
0269 typedef typename policies::normalise<
0270 Policy,
0271 policies::promote_float<false>,
0272 policies::promote_double<false>,
0273 policies::discrete_quantile<>,
0274 policies::assert_undefined<> >::type forwarding_policy;
0275
0276 if(q == 1)
0277 {
0278 return tools::min_value<result_type>();
0279 }
0280 if(q == 0)
0281 {
0282 return policies::raise_overflow_error<result_type>(function, 0, Policy());
0283 }
0284
0285 return policies::checked_narrowing_cast<result_type, forwarding_policy>(
0286 detail::ibeta_inv_ab_imp(
0287 static_cast<value_type>(a),
0288 static_cast<value_type>(x),
0289 static_cast<value_type>(1 - static_cast<value_type>(q)),
0290 static_cast<value_type>(q),
0291 true, pol),
0292 function);
0293 }
0294
0295 template <class RT1, class RT2, class RT3>
0296 inline typename tools::promote_args<RT1, RT2, RT3>::type
0297 ibeta_inva(RT1 b, RT2 x, RT3 p)
0298 {
0299 return boost::math::ibeta_inva(b, x, p, policies::policy<>());
0300 }
0301
0302 template <class RT1, class RT2, class RT3>
0303 inline typename tools::promote_args<RT1, RT2, RT3>::type
0304 ibetac_inva(RT1 b, RT2 x, RT3 q)
0305 {
0306 return boost::math::ibetac_inva(b, x, q, policies::policy<>());
0307 }
0308
0309 template <class RT1, class RT2, class RT3>
0310 inline typename tools::promote_args<RT1, RT2, RT3>::type
0311 ibeta_invb(RT1 a, RT2 x, RT3 p)
0312 {
0313 return boost::math::ibeta_invb(a, x, p, policies::policy<>());
0314 }
0315
0316 template <class RT1, class RT2, class RT3>
0317 inline typename tools::promote_args<RT1, RT2, RT3>::type
0318 ibetac_invb(RT1 a, RT2 x, RT3 q)
0319 {
0320 return boost::math::ibetac_invb(a, x, q, policies::policy<>());
0321 }
0322
0323 }
0324 }
0325
0326 #endif
0327
0328
0329