double proj_auth_inv(double beta, const void *a) { int max; double dl, c, phi; c = sin(beta); phi = beta; for (max = MAX_ITER ; max ; --max) { dl = (c - betaf(phi, a))/betap(phi, a); phi += dl; if (fabs(dl) < TOLER) return(phi); } /* it will usually not fall out of the loop, in fact tests * have never made it fall through. But there are convergence * limits at argument approaches 90 degrees */ return(phi); }
T non_central_t2_p(T v, T delta, T x, T y, const Policy& pol, T init_val) { BOOST_MATH_STD_USING // // Variables come first: // boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>(); T errtol = policies::get_epsilon<T, Policy>(); T d2 = delta * delta / 2; // // k is the starting point for iteration, and is the // maximum of the poisson weighting term, we don't // ever allow k == 0 as this can lead to catastrophic // cancellation errors later (test case is v = 1621286869049072.3 // delta = 0.16212868690490723, x = 0.86987415482475994). // int k = itrunc(d2); T pois; if(k == 0) k = 1; // Starting Poisson weight: pois = gamma_p_derivative(T(k+1), d2, pol) * tgamma_delta_ratio(T(k + 1), T(0.5f)) * delta / constants::root_two<T>(); if(pois == 0) return init_val; T xterm, beta; // Recurrance & starting beta terms: beta = x < y ? detail::ibeta_imp(T(k + 1), T(v / 2), x, pol, false, true, &xterm) : detail::ibeta_imp(T(v / 2), T(k + 1), y, pol, true, true, &xterm); xterm *= y / (v / 2 + k); T poisf(pois), betaf(beta), xtermf(xterm); T sum = init_val; if((xterm == 0) && (beta == 0)) return init_val; // // Backwards recursion first, this is the stable // direction for recursion: // boost::uintmax_t count = 0; T last_term = 0; for(int i = k; i >= 0; --i) { T term = beta * pois; sum += term; // Don't terminate on first term in case we "fixed" k above: if((fabs(last_term) > fabs(term)) && fabs(term/sum) < errtol) break; last_term = term; pois *= (i + 0.5f) / d2; beta += xterm; xterm *= (i) / (x * (v / 2 + i - 1)); ++count; } last_term = 0; for(int i = k + 1; ; ++i) { poisf *= d2 / (i + 0.5f); xtermf *= (x * (v / 2 + i - 1)) / (i); betaf -= xtermf; T term = poisf * betaf; sum += term; if((fabs(last_term) > fabs(term)) && (fabs(term/sum) < errtol)) break; last_term = term; ++count; if(count > max_iter) { return policies::raise_evaluation_error( "cdf(non_central_t_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol); } } return sum; }
T non_central_t2_q(T v, T delta, T x, T y, const Policy& pol, T init_val) { BOOST_MATH_STD_USING // // Variables come first: // boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>(); T errtol = boost::math::policies::get_epsilon<T, Policy>(); T d2 = delta * delta / 2; // // k is the starting point for iteration, and is the // maximum of the poisson weighting term, we don't allow // k == 0 as this can cause catastrophic cancellation errors // (test case is v = 561908036470413.25, delta = 0.056190803647041321, // x = 1.6155232703966216): // int k = itrunc(d2); if(k == 0) k = 1; // Starting Poisson weight: T pois; if((k < (int)(max_factorial<T>::value)) && (d2 < tools::log_max_value<T>()) && (log(d2) * k < tools::log_max_value<T>())) { // // For small k we can optimise this calculation by using // a simpler reduced formula: // pois = exp(-d2); pois *= pow(d2, static_cast<T>(k)); pois /= boost::math::tgamma(T(k + 1 + 0.5), pol); pois *= delta / constants::root_two<T>(); } else { pois = gamma_p_derivative(T(k+1), d2, pol) * tgamma_delta_ratio(T(k + 1), T(0.5f)) * delta / constants::root_two<T>(); } if(pois == 0) return init_val; // Recurance term: T xterm; T beta; // Starting beta term: if(k != 0) { beta = x < y ? detail::ibeta_imp(T(k + 1), T(v / 2), x, pol, true, true, &xterm) : detail::ibeta_imp(T(v / 2), T(k + 1), y, pol, false, true, &xterm); xterm *= y / (v / 2 + k); } else { beta = pow(y, v / 2); xterm = beta; } T poisf(pois), betaf(beta), xtermf(xterm); T sum = init_val; if((xterm == 0) && (beta == 0)) return init_val; // // Fused forward and backwards recursion: // boost::uintmax_t count = 0; T last_term = 0; for(int i = k + 1, j = k; ; ++i, --j) { poisf *= d2 / (i + 0.5f); xtermf *= (x * (v / 2 + i - 1)) / (i); betaf += xtermf; T term = poisf * betaf; if(j >= 0) { term += beta * pois; pois *= (j + 0.5f) / d2; beta -= xterm; xterm *= (j) / (x * (v / 2 + j - 1)); } sum += term; // Don't terminate on first term in case we "fixed" the value of k above: if((fabs(last_term) > fabs(term)) && fabs(term/sum) < errtol) break; last_term = term; if(count > max_iter) { return policies::raise_evaluation_error( "cdf(non_central_t_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol); } ++count; } return sum; }
inline float beta(float a, float b) { return betaf(a, b); }
double proj_auth_lat(double phi, const void *a) { return(asin(betaf(phi, a))); }