double qpois(double p, double lambda, int lower_tail, int log_p) { double mu, sigma, gamma, z, y; #ifdef IEEE_754 if (ISNAN(p) || ISNAN(lambda)) return p + lambda; #endif if(!R_FINITE(lambda)) ML_ERR_return_NAN; if(lambda < 0) ML_ERR_return_NAN; R_Q_P01_check(p); if(lambda == 0) return 0; if(p == R_DT_0) return 0; if(p == R_DT_1) return ML_POSINF; mu = lambda; sigma = sqrt(lambda); /* gamma = sigma; PR#8058 should be kurtosis which is mu^-0.5 */ gamma = 1.0/sigma; /* Note : "same" code in qpois.c, qbinom.c, qnbinom.c -- * FIXME: This is far from optimal [cancellation for p ~= 1, etc]: */ if(!lower_tail || log_p) { p = R_DT_qIv(p); /* need check again (cancellation!): */ if (p == 0.) return 0; if (p == 1.) return ML_POSINF; } /* temporary hack --- FIXME --- */ if (p + 1.01*DBL_EPSILON >= 1.) return ML_POSINF; /* y := approx.value (Cornish-Fisher expansion) : */ z = qnorm(p, 0., 1., /*lower_tail*/TRUE, /*log_p*/FALSE); #ifdef HAVE_NEARBYINT y = nearbyint(mu + sigma * (z + gamma * (z*z - 1) / 6)); #else y = round(mu + sigma * (z + gamma * (z*z - 1) / 6)); #endif z = ppois(y, lambda, /*lower_tail*/TRUE, /*log_p*/FALSE); /* fuzz to ensure left continuity; 1 - 1e-7 may lose too much : */ p *= 1 - 64*DBL_EPSILON; /* If the mean is not too large a simple search is OK */ if(lambda < 1e5) return do_search(y, &z, p, lambda, 1); /* Otherwise be a bit cleverer in the search */ { double incr = floor(y * 0.001), oldincr; do { oldincr = incr; y = do_search(y, &z, p, lambda, incr); incr = fmax2(1, floor(incr/100)); } while(oldincr > 1 && incr > lambda*1e-15); return y; } }
double qunif(double p, double a, double b, int lower_tail, int log_p) { #ifdef IEEE_754 if (ISNAN(p) || ISNAN(a) || ISNAN(b)) return p + a + b; #endif R_Q_P01_check(p); if (b <= a ) ML_ERR_return_NAN; return a + R_DT_qIv(p) * (b - a); }
double qwilcox(double x, double m, double n, int lower_tail, int log_p) { double c, p; #ifdef IEEE_754 if (ISNAN(x) || ISNAN(m) || ISNAN(n)) return(x + m + n); #endif if(!R_FINITE(x) || !R_FINITE(m) || !R_FINITE(n)) ML_ERR_return_NAN; R_Q_P01_check(x); m = R_forceint(m); n = R_forceint(n); if (m <= 0 || n <= 0) ML_ERR_return_NAN; if (x == R_DT_0) return(0); if (x == R_DT_1) return(m * n); if(log_p || !lower_tail) x = R_DT_qIv(x); /* lower_tail,non-log "p" */ int mm = (int) m, nn = (int) n; w_init_maybe(mm, nn); c = choose(m + n, n); p = 0; int q = 0; if (x <= 0.5) { x = x - 10 * DBL_EPSILON; for (;;) { p += cwilcox(q, mm, nn) / c; if (p >= x) break; q++; } } else { x = 1 - x + 10 * DBL_EPSILON; for (;;) { p += cwilcox(q, mm, nn) / c; if (p > x) { q = (int) (m * n - q); break; } q++; } } return(q); }
double qsignrank(double x, double n, int lower_tail, int log_p) { double f, p; #ifdef IEEE_754 if (ISNAN(x) || ISNAN(n)) return(x + n); #endif if (!R_FINITE(x) || !R_FINITE(n)) ML_ERR_return_NAN; R_Q_P01_check(x); n = floor(n + 0.5); if (n <= 0) ML_ERR_return_NAN; if (x == R_DT_0) return(0); if (x == R_DT_1) return(n * (n + 1) / 2); if(log_p || !lower_tail) x = R_DT_qIv(x); /* lower_tail,non-log "p" */ int nn = (int) n; w_init_maybe(nn); f = exp(- n * M_LN2); p = 0; int q = 0; if (x <= 0.5) { x = x - 10 * DBL_EPSILON; for (;;) { p += csignrank(q, nn) * f; if (p >= x) break; q++; } } else { x = 1 - x + 10 * DBL_EPSILON; for (;;) { p += csignrank(q, nn) * f; if (p > x) { q = (int)(n * (n + 1) / 2 - q); break; } q++; } } return(q); }
double qnbinom(double p, double size, double prob, int lower_tail, int log_p) { double P, Q, mu, sigma, gamma, z, y; #ifdef IEEE_754 if (ISNAN(p) || ISNAN(size) || ISNAN(prob)) return p + size + prob; #endif if (prob <= 0 || prob > 1 || size <= 0) ML_ERR_return_NAN; /* FIXME: size = 0 is well defined ! */ if (prob == 1) return 0; R_Q_P01_boundaries(p, 0, ML_POSINF); Q = 1.0 / prob; P = (1.0 - prob) * Q; mu = size * P; sigma = sqrt(size * P * Q); gamma = (Q + P)/sigma; /* Note : "same" code in qpois.c, qbinom.c, qnbinom.c -- * FIXME: This is far from optimal [cancellation for p ~= 1, etc]: */ if(!lower_tail || log_p) { p = R_DT_qIv(p); /* need check again (cancellation!): */ if (p == R_DT_0) return 0; if (p == R_DT_1) return ML_POSINF; } /* temporary hack --- FIXME --- */ if (p + 1.01*DBL_EPSILON >= 1.) return ML_POSINF; /* y := approx.value (Cornish-Fisher expansion) : */ z = qnorm(p, 0., 1., /*lower_tail*/TRUE, /*log_p*/FALSE); y = floor(mu + sigma * (z + gamma * (z*z - 1) / 6) + 0.5); z = pnbinom(y, size, prob, /*lower_tail*/TRUE, /*log_p*/FALSE); /* fuzz to ensure left continuity: */ p *= 1 - 64*DBL_EPSILON; /* If the C-F value is not too large a simple search is OK */ if(y < 1e5) return do_search(y, &z, p, size, prob, 1); /* Otherwise be a bit cleverer in the search */ { double incr = floor(y * 0.001), oldincr; do { oldincr = incr; y = do_search(y, &z, p, size, prob, incr); incr = fmax2(1, floor(incr/100)); } while(oldincr > 1 && incr > y*1e-15); return y; } }
double qcauchy(double p, double location, double scale, int lower_tail, int log_p) { #ifdef IEEE_754 if (ISNAN(p) || ISNAN(location) || ISNAN(scale)) return p + location + scale; #endif if(!R_FINITE(p) || !R_FINITE(location) || !R_FINITE(scale)) ML_ERR_return_NAN; R_Q_P01_check(p); if (scale <= 0) ML_ERR_return_NAN; return location + scale * tan(M_PI * (R_DT_qIv(p) - 0.5)); }
double qnt(double p, double df, double ncp, int lower_tail, int log_p) { const static double accu = 1e-13; const static double Eps = 1e-11; /* must be > accu */ double ux, lx, nx, pp; #ifdef IEEE_754 if (ISNAN(p) || ISNAN(df) || ISNAN(ncp)) return p + df + ncp; #endif if (!R_FINITE(df)) ML_ERR_return_NAN; /* Was * df = floor(df + 0.5); * if (df < 1 || ncp < 0) ML_ERR_return_NAN; */ if (df <= 0.0) ML_ERR_return_NAN; if(ncp == 0.0 && df >= 1.0) return qt(p, df, lower_tail, log_p); R_Q_P01_boundaries(p, ML_NEGINF, ML_POSINF); p = R_DT_qIv(p); /* Invert pnt(.) : * 1. finding an upper and lower bound */ if(p > 1 - DBL_EPSILON) return ML_POSINF; pp = fmin2(1 - DBL_EPSILON, p * (1 + Eps)); for(ux = fmax2(1., ncp); ux < DBL_MAX && pnt(ux, df, ncp, TRUE, FALSE) < pp; ux *= 2); pp = p * (1 - Eps); for(lx = fmin2(-1., -ncp); lx > -DBL_MAX && pnt(lx, df, ncp, TRUE, FALSE) > pp; lx *= 2); /* 2. interval (lx,ux) halving : */ do { nx = 0.5 * (lx + ux); if (pnt(nx, df, ncp, TRUE, FALSE) > p) ux = nx; else lx = nx; } while ((ux - lx) / fabs(nx) > accu); return 0.5 * (lx + ux); }
double qnbeta(double p, double a, double b, double ncp, int lower_tail, int log_p) { const static double accu = 1e-15; const static double Eps = 1e-14; /* must be > accu */ double ux, lx, nx, pp; #ifdef IEEE_754 if (ISNAN(p) || ISNAN(a) || ISNAN(b) || ISNAN(ncp)) return p + a + b + ncp; #endif if (!R_FINITE(a)) ML_ERR_return_NAN; if (ncp < 0. || a <= 0. || b <= 0.) ML_ERR_return_NAN; R_Q_P01_boundaries(p, 0, 1); p = R_DT_qIv(p); /* Invert pnbeta(.) : * 1. finding an upper and lower bound */ if(p > 1 - DBL_EPSILON) return 1.0; pp = fmin2(1 - DBL_EPSILON, p * (1 + Eps)); for(ux = 0.5; ux < 1 - DBL_EPSILON && pnbeta(ux, a, b, ncp, TRUE, FALSE) < pp; ux = 0.5*(1+ux)); pp = p * (1 - Eps); for(lx = 0.5; lx > DBL_MIN && pnbeta(lx, a, b, ncp, TRUE, FALSE) > pp; lx *= 0.5); /* 2. interval (lx,ux) halving : */ do { nx = 0.5 * (lx + ux); if (pnbeta(nx, a, b, ncp, TRUE, FALSE) > p) ux = nx; else lx = nx; } while ((ux - lx) / nx > accu); return 0.5 * (ux + lx); }
// Returns both qbeta() and its "mirror" 1-qbeta(). Useful notably when qbeta() ~= 1 attribute_hidden void qbeta_raw(double alpha, double p, double q, int lower_tail, int log_p, int swap_01, // {TRUE, NA, FALSE}: if NA, algorithm decides swap_tail double log_q_cut, /* if == Inf: return log(qbeta(..)); otherwise, if finite: the bound for switching to log(x)-scale; see use_log_x */ int n_N, // number of "unconstrained" Newton steps before switching to constrained double *qb) // = qb[0:1] = { qbeta(), 1 - qbeta() } { Rboolean swap_choose = (swap_01 == MLOGICAL_NA), swap_tail, log_, give_log_q = (log_q_cut == ML_POSINF), use_log_x = give_log_q, // or u < log_q_cut below warned = FALSE, add_N_step = TRUE; int i_pb, i_inn; double a, la, logbeta, g, h, pp, p_, qq, r, s, t, w, y = -1.; volatile double u, xinbta; // Assuming p >= 0, q >= 0 here ... // Deal with boundary cases here: if(alpha == R_DT_0) { #define return_q_0 \ if(give_log_q) { qb[0] = ML_NEGINF; qb[1] = 0; } \ else { qb[0] = 0; qb[1] = 1; } \ return return_q_0; } if(alpha == R_DT_1) { #define return_q_1 \ if(give_log_q) { qb[0] = 0; qb[1] = ML_NEGINF; } \ else { qb[0] = 1; qb[1] = 0; } \ return return_q_1; } // check alpha {*before* transformation which may all accuracy}: if((log_p && alpha > 0) || (!log_p && (alpha < 0 || alpha > 1))) { // alpha is outside R_ifDEBUG_printf("qbeta(alpha=%g, %g, %g, .., log_p=%d): %s%s\n", alpha, p,q, log_p, "alpha not in ", log_p ? "[-Inf, 0]" : "[0,1]"); // ML_ERR_return_NAN : ML_ERROR(ME_DOMAIN, ""); qb[0] = qb[1] = ML_NAN; return; } // p==0, q==0, p = Inf, q = Inf <==> treat as one- or two-point mass if(p == 0 || q == 0 || !R_FINITE(p) || !R_FINITE(q)) { // We know 0 < T(alpha) < 1 : pbeta() is constant and trivial in {0, 1/2, 1} R_ifDEBUG_printf( "qbeta(%g, %g, %g, lower_t=%d, log_p=%d): (p,q)-boundary: trivial\n", alpha, p,q, lower_tail, log_p); if(p == 0 && q == 0) { // point mass 1/2 at each of {0,1} : if(alpha < R_D_half) { return_q_0; } if(alpha > R_D_half) { return_q_1; } // else: alpha == "1/2" #define return_q_half \ if(give_log_q) qb[0] = qb[1] = -M_LN2; \ else qb[0] = qb[1] = 0.5; \ return return_q_half; } else if (p == 0 || p/q == 0) { // point mass 1 at 0 - "flipped around" return_q_0; } else if (q == 0 || q/p == 0) { // point mass 1 at 0 - "flipped around" return_q_1; } // else: p = q = Inf : point mass 1 at 1/2 return_q_half; } /* initialize */ p_ = R_DT_qIv(alpha);/* lower_tail prob (in any case) */ // Conceptually, 0 < p_ < 1 (but can be 0 or 1 because of cancellation!) logbeta = lbeta(p, q); swap_tail = (swap_choose) ? (p_ > 0.5) : swap_01; // change tail; default (swap_01 = NA): afterwards 0 < a <= 1/2 if(swap_tail) { /* change tail, swap p <-> q :*/ a = R_DT_CIv(alpha); // = 1 - p_ < 1/2 /* la := log(a), but without numerical cancellation: */ la = R_DT_Clog(alpha); pp = q; qq = p; } else { a = p_; la = R_DT_log(alpha); pp = p; qq = q; } /* calculate the initial approximation */ /* Desired accuracy for Newton iterations (below) should depend on (a,p) * This is from Remark .. on AS 109, adapted. * However, it's not clear if this is "optimal" for IEEE double prec. * acu = fmax2(acu_min, pow(10., -25. - 5./(pp * pp) - 1./(a * a))); * NEW: 'acu' accuracy NOT for squared adjustment, but simple; * ---- i.e., "new acu" = sqrt(old acu) */ double acu = fmax2(acu_min, pow(10., -13. - 2.5/(pp * pp) - 0.5/(a * a))); // try to catch "extreme left tail" early double tx, u0 = (la + log(pp) + logbeta) / pp; // = log(x_0) static const double log_eps_c = M_LN2 * (1. - DBL_MANT_DIG);// = log(DBL_EPSILON) = -36.04.. r = pp*(1.-qq)/(pp+1.); t = 0.2; // FIXME: Factor 0.2 is a bit arbitrary; '1' is clearly much too much. R_ifDEBUG_printf( "qbeta(%g, %g, %g, lower_t=%d, log_p=%d):%s\n" " swap_tail=%d, la=%g, u0=%g (bnd: %g (%g)) ", alpha, p,q, lower_tail, log_p, (log_p && (p_ == 0. || p_ == 1.)) ? (p_==0.?" p_=0":" p_=1") : "", swap_tail, la, u0, (t*log_eps_c - log(fabs(pp*(1.-qq)*(2.-qq)/(2.*(pp+2.)))))/2., t*log_eps_c - log(fabs(r)) ); if(M_LN2 * DBL_MIN_EXP < u0 && // cannot allow exp(u0) = 0 ==> exp(u1) = exp(u0) = 0 u0 < -0.01 && // (must: u0 < 0, but too close to 0 <==> x = exp(u0) = 0.99..) // qq <= 2 && // <--- "arbitrary" // u0 < t*log_eps_c - log(fabs(r)) && u0 < (t*log_eps_c - log(fabs(pp*(1.-qq)*(2.-qq)/(2.*(pp+2.)))))/2.) { // TODO: maybe jump here from below, when initial u "fails" ? // L_tail_u: // MM's one-step correction (cheaper than 1 Newton!) r = r*exp(u0);// = r*x0 if(r > -1.) { u = u0 - log1p(r)/pp; R_ifDEBUG_printf("u1-u0=%9.3g --> choosing u = u1\n", u-u0); } else { u = u0; R_ifDEBUG_printf("cannot cheaply improve u0\n"); } tx = xinbta = exp(u); use_log_x = TRUE; // or (u < log_q_cut) ?? goto L_Newton; } // y := y_\alpha in AS 64 := Hastings(1955) approximation of qnorm(1 - a) : r = sqrt(-2 * la); y = r - (const1 + const2 * r) / (1. + (const3 + const4 * r) * r); if (pp > 1 && qq > 1) { // use Carter(1947), see AS 109, remark '5.' r = (y * y - 3.) / 6.; s = 1. / (pp + pp - 1.); t = 1. / (qq + qq - 1.); h = 2. / (s + t); w = y * sqrt(h + r) / h - (t - s) * (r + 5. / 6. - 2. / (3. * h)); R_ifDEBUG_printf("p,q > 1 => w=%g", w); if(w > 300) { // exp(w+w) is huge or overflows t = w+w + log(qq) - log(pp); // = argument of log1pexp(.) u = // log(xinbta) = - log1p(qq/pp * exp(w+w)) = -log(1 + exp(t)) (t <= 18) ? -log1p(exp(t)) : -t - exp(-t); xinbta = exp(u); } else { xinbta = pp / (pp + qq * exp(w + w)); u = // log(xinbta) - log1p(qq/pp * exp(w+w)); } } else { // use the original AS 64 proposal, Scheffé-Tukey (1944) and Wilson-Hilferty r = qq + qq; /* A slightly more stable version of t := \chi^2_{alpha} of AS 64 * t = 1. / (9. * qq); t = r * R_pow_di(1. - t + y * sqrt(t), 3); */ t = 1. / (3. * sqrt(qq)); t = r * R_pow_di(1. + t*(-t + y), 3);// = \chi^2_{alpha} of AS 64 s = 4. * pp + r - 2.;// 4p + 2q - 2 = numerator of new t = (...) / chi^2 R_ifDEBUG_printf("min(p,q) <= 1: t=%g", t); if (t == 0 || (t < 0. && s >= t)) { // cannot use chisq approx // x0 = 1 - { (1-a)*q*B(p,q) } ^{1/q} {AS 65} // xinbta = 1. - exp((log(1-a)+ log(qq) + logbeta) / qq); double l1ma;/* := log(1-a), directly from alpha (as 'la' above): * FIXME: not worth it? log1p(-a) always the same ?? */ if(swap_tail) l1ma = R_DT_log(alpha); else l1ma = R_DT_Clog(alpha); R_ifDEBUG_printf(" t <= 0 : log1p(-a)=%.15g, better l1ma=%.15g\n", log1p(-a), l1ma); double xx = (l1ma + log(qq) + logbeta) / qq; if(xx <= 0.) { xinbta = -expm1(xx); u = R_Log1_Exp (xx);// = log(xinbta) = log(1 - exp(...A...)) } else { // xx > 0 ==> 1 - e^xx < 0 .. is nonsense R_ifDEBUG_printf(" xx=%g > 0: xinbta:= 1-e^xx < 0\n", xx); xinbta = 0; u = ML_NEGINF; /// FIXME can do better? } } else { t = s / t; R_ifDEBUG_printf(" t > 0 or s < t < 0: new t = %g ( > 1 ?)\n", t); if (t <= 1.) { // cannot use chisq, either u = (la + log(pp) + logbeta) / pp; xinbta = exp(u); } else { // (1+x0)/(1-x0) = t, solved for x0 : xinbta = 1. - 2. / (t + 1.); u = log1p(-2. / (t + 1.)); } } } // Problem: If initial u is completely wrong, we make a wrong decision here if(swap_choose && (( swap_tail && u >= -exp( log_q_cut)) || // ==> "swap back" (!swap_tail && u >= -exp(4*log_q_cut) && pp / qq < 1000.))) { // ==> "swap now" (much less easily) // "revert swap" -- and use_log_x swap_tail = !swap_tail; R_ifDEBUG_printf(" u = %g (e^u = xinbta = %.16g) ==> ", u, xinbta); if(swap_tail) { a = R_DT_CIv(alpha); // needed ? la = R_DT_Clog(alpha); pp = q; qq = p; } else { a = p_; la = R_DT_log(alpha); pp = p; qq = q; } R_ifDEBUG_printf("\"%s\"; la = %g\n", (swap_tail ? "swap now" : "swap back"), la); // we could redo computations above, but this should be stable u = R_Log1_Exp(u); xinbta = exp(u); /* Careful: "swap now" should not fail if 1) the above initial xinbta is "completely wrong" 2) The correction step can go outside (u_n > 0 ==> e^u > 1 is illegal) e.g., for qbeta(0.2066, 0.143891, 0.05) */ } if(!use_log_x) use_log_x = (u < log_q_cut);//(per default) <==> xinbta = e^u < 4.54e-5 Rboolean bad_u = !R_FINITE(u), bad_init = bad_u || xinbta > p_hi; R_ifDEBUG_printf(" -> u = %g, e^u = xinbta = %.16g, (Newton acu=%g%s)\n", u, xinbta, acu, (bad_u ? ", ** bad u **" : (use_log_x ? ", on u = log(x) scale" : ""))); double u_n = 1.; // -Wall tx = xinbta; // keeping "original initial x" (for now) if(bad_u || u < log_q_cut) { /* e.g. qbeta(0.21, .001, 0.05) try "left border" quickly, i.e., try at smallest positive number: */ w = pbeta_raw(DBL_very_MIN, pp, qq, TRUE, log_p); if(w > (log_p ? la : a)) { R_ifDEBUG_printf(" quantile is left of smallest positive number; \"convergence\"\n"); if(log_p || fabs(w - a) < fabs(0 - a)) { // DBL_very_MIN is better than 0 tx = DBL_very_MIN; u_n = DBL_log_v_MIN;// = log(DBL_very_MIN) } else { tx = 0.; u_n = ML_NEGINF; } use_log_x = log_p; add_N_step = FALSE; goto L_return; } else { R_ifDEBUG_printf(" pbeta(smallest pos.) = %g <= %g --> continuing\n", w, (log_p ? la : a)); if(u < DBL_log_v_MIN) { u = DBL_log_v_MIN;// = log(DBL_very_MIN) xinbta = DBL_very_MIN; } } } /* Sometimes the approximation is negative (and == 0 is also not "ok") */ if (bad_init && !(use_log_x && tx > 0)) { if(u == ML_NEGINF) { R_ifDEBUG_printf(" u = -Inf;"); u = M_LN2 * DBL_MIN_EXP; xinbta = DBL_MIN; } else { R_ifDEBUG_printf(" bad_init: u=%g, xinbta=%g;", u,xinbta); xinbta = (xinbta > 1.1) // i.e. "way off" ? 0.5 // otherwise, keep the respective boundary: : ((xinbta < p_lo) ? exp(u) : p_hi); if(bad_u) u = log(xinbta); // otherwise: not changing "potentially better" u than the above } R_ifDEBUG_printf(" -> (partly)new u=%g, xinbta=%g\n", u,xinbta); } L_Newton: /* -------------------------------------------------------------------- * Solve for x by a modified Newton-Raphson method, using pbeta_raw() */ r = 1 - pp; t = 1 - qq; double wprev = 0., prev = 1., adj = 1.; // -Wall if(use_log_x) { // find log(xinbta) -- work in u := log(x) scale // if(bad_init && tx > 0) xinbta = tx;// may have been better for (i_pb=0; i_pb < 1000; i_pb++) { // using log_p == TRUE unconditionally here // FIXME: if exp(u) = xinbta underflows to 0, like different formula pbeta_log(u, *) y = pbeta_raw(xinbta, pp, qq, /*lower_tail = */ TRUE, TRUE); /* w := Newton step size for L(u) = log F(e^u) =!= 0; u := log(x) * = (L(.) - la) / L'(.); L'(u)= (F'(e^u) * e^u ) / F(e^u) * = (L(.) - la)*F(.) / {F'(e^u) * e^u } = * = (L(.) - la) * e^L(.) * e^{-log F'(e^u) - u} * = ( y - la) * e^{ y - u -log F'(e^u)} and -log F'(x)= -log f(x) = + logbeta + (1-p) log(x) + (1-q) log(1-x) = logbeta + (1-p) u + (1-q) log(1-e^u) */ w = (y == ML_NEGINF) // y = -Inf well possible: we are on log scale! ? 0. : (y - la) * exp(y - u + logbeta + r * u + t * R_Log1_Exp(u)); if(!R_FINITE(w)) break; if (i_pb >= n_N && w * wprev <= 0.) prev = fmax2(fabs(adj),fpu); R_ifDEBUG_printf("N(i=%2d): u=%#20.16g, pb(e^u)=%#12.6g, w=%#15.9g, %s prev=%11g,", i_pb, u, y, w, (w * wprev <= 0.) ? "new" : "old", prev); g = 1; for (i_inn=0; i_inn < 1000; i_inn++) { adj = g * w; // take full Newton steps at the beginning; only then safe guard: if (i_pb < n_N || fabs(adj) < prev) { u_n = u - adj; // u_{n+1} = u_n - g*w if (u_n <= 0.) { // <==> 0 < xinbta := e^u <= 1 if (prev <= acu || fabs(w) <= acu) { /* R_ifDEBUG_printf(" -adj=%g, %s <= acu ==> convergence\n", */ /* -adj, (prev <= acu) ? "prev" : "|w|"); */ R_ifDEBUG_printf(" it{in}=%d, -adj=%g, %s <= acu ==> convergence\n", i_inn, -adj, (prev <= acu) ? "prev" : "|w|"); goto L_converged; } // if (u_n != ML_NEGINF && u_n != 1) break; } } g /= 3; } // (cancellation in (u_n -u) => may differ from adj: double D = fmin2(fabs(adj), fabs(u_n - u)); /* R_ifDEBUG_printf(" delta(u)=%g\n", u_n - u); */ R_ifDEBUG_printf(" it{in}=%d, delta(u)=%9.3g, D/|.|=%.3g\n", i_inn, u_n - u, D/fabs(u_n + u)); if (D <= 4e-16 * fabs(u_n + u)) goto L_converged; u = u_n; xinbta = exp(u); wprev = w; } // for(i ) } else for (i_pb=0; i_pb < 1000; i_pb++) { y = pbeta_raw(xinbta, pp, qq, /*lower_tail = */ TRUE, log_p); // delta{y} : d_y = y - (log_p ? la : a); #ifdef IEEE_754 if(!R_FINITE(y) && !(log_p && y == ML_NEGINF))// y = -Inf is ok if(log_p) #else if (errno) #endif { // ML_ERR_return_NAN : ML_ERROR(ME_DOMAIN, ""); qb[0] = qb[1] = ML_NAN; return; } /* w := Newton step size (F(.) - a) / F'(.) or, * -- log: (lF - la) / (F' / F) = exp(lF) * (lF - la) / F' */ w = log_p ? (y - la) * exp(y + logbeta + r * log(xinbta) + t * log1p(-xinbta)) : (y - a) * exp( logbeta + r * log(xinbta) + t * log1p(-xinbta)); if (i_pb >= n_N && w * wprev <= 0.) prev = fmax2(fabs(adj),fpu); R_ifDEBUG_printf("N(i=%2d): x0=%#17.15g, pb(x0)=%#17.15g, w=%#17.15g, %s prev=%g,", i_pb, xinbta, y, w, (w * wprev <= 0.) ? "new" : "old", prev); g = 1; for (i_inn=0; i_inn < 1000;i_inn++) { adj = g * w; // take full Newton steps at the beginning; only then safe guard: if (i_pb < n_N || fabs(adj) < prev) { tx = xinbta - adj; // x_{n+1} = x_n - g*w if (0. <= tx && tx <= 1.) { if (prev <= acu || fabs(w) <= acu) { R_ifDEBUG_printf(" it{in}=%d, delta(x)=%g, %s <= acu ==> convergence\n", i_inn, -adj, (prev <= acu) ? "prev" : "|w|"); goto L_converged; } if (tx != 0. && tx != 1) break; } } g /= 3; } R_ifDEBUG_printf(" it{in}=%d, delta(x)=%g\n", i_inn, tx - xinbta); if (fabs(tx - xinbta) <= 4e-16 * (tx + xinbta)) // "<=" : (.) == 0 goto L_converged; xinbta = tx; if(tx == 0) // "we have lost" break; wprev = w; } /*-- NOT converged: Iteration count --*/ warned = TRUE; ML_ERROR(ME_PRECISION, "qbeta"); L_converged: log_ = log_p || use_log_x; // only for printing R_ifDEBUG_printf(" %s: Final delta(y) = %g%s\n", warned ? "_NO_ convergence" : "converged", y - (log_ ? la : a), (log_ ? " (log_)" : "")); if((log_ && y == ML_NEGINF) || (!log_ && y == 0)) { // stuck at left, try if smallest positive number is "better" w = pbeta_raw(DBL_very_MIN, pp, qq, TRUE, log_); if(log_ || fabs(w - a) <= fabs(y - a)) { tx = DBL_very_MIN; u_n = DBL_log_v_MIN;// = log(DBL_very_MIN) } add_N_step = FALSE; // not trying to do better anymore } else if(!warned && (log_ ? fabs(y - la) > 3 : fabs(y - a) > 1e-4)) { if(!(log_ && y == ML_NEGINF && // e.g. qbeta(-1e-10, .2, .03, log=TRUE) cannot get accurate ==> do NOT warn pbeta_raw(DBL_1__eps, // = 1 - eps pp, qq, TRUE, TRUE) > la + 2)) MATHLIB_WARNING2( // low accuracy for more platform independent output: "qbeta(a, *) =: x0 with |pbeta(x0,*%s) - alpha| = %.5g is not accurate", (log_ ? ", log_" : ""), fabs(y - (log_ ? la : a))); } L_return: if(give_log_q) { // ==> use_log_x , too if(!use_log_x) // (see if claim above is true) MATHLIB_WARNING( "qbeta() L_return, u_n=%g; give_log_q=TRUE but use_log_x=FALSE -- please report!", u_n); double r = R_Log1_Exp(u_n); if(swap_tail) { qb[0] = r; qb[1] = u_n; } else { qb[0] = u_n; qb[1] = r; } } else { if(use_log_x) { if(add_N_step) { /* add one last Newton step on original x scale, e.g., for qbeta(2^-98, 0.125, 2^-96) */ xinbta = exp(u_n); y = pbeta_raw(xinbta, pp, qq, /*lower_tail = */ TRUE, log_p); w = log_p ? (y - la) * exp(y + logbeta + r * log(xinbta) + t * log1p(-xinbta)) : (y - a) * exp( logbeta + r * log(xinbta) + t * log1p(-xinbta)); tx = xinbta - w; R_ifDEBUG_printf( "Final Newton correction(non-log scale): xinbta=%.16g, y=%g, w=%g. => new tx=%.16g\n", xinbta, y, w, tx); } else { if(swap_tail) { qb[0] = -expm1(u_n); qb[1] = exp (u_n); } else { qb[0] = exp (u_n); qb[1] = -expm1(u_n); } return; } } if(swap_tail) { qb[0] = 1 - tx; qb[1] = tx; } else { qb[0] = tx; qb[1] = 1 - tx; } } return; }
double qbinom(double p, double n, double pr, int lower_tail, int log_p) { double q, mu, sigma, gamma, z, y; #ifdef IEEE_754 if (ISNAN(p) || ISNAN(n) || ISNAN(pr)) return p + n + pr; #endif if(!R_FINITE(n) || !R_FINITE(pr)) ML_ERR_return_NAN; /* if log_p is true, p = -Inf is a legitimate value */ if(!R_FINITE(p) && !log_p) ML_ERR_return_NAN; if(n != floor(n + 0.5)) ML_ERR_return_NAN; if (pr < 0 || pr > 1 || n < 0) ML_ERR_return_NAN; R_Q_P01_boundaries(p, 0, n); if (pr == 0. || n == 0) return 0.; q = 1 - pr; if(q == 0.) return n; /* covers the full range of the distribution */ mu = n * pr; sigma = sqrt(n * pr * q); gamma = (q - pr) / sigma; #ifdef DEBUG_qbinom REprintf("qbinom(p=%7g, n=%g, pr=%7g, l.t.=%d, log=%d): sigm=%g, gam=%g\n", p,n,pr, lower_tail, log_p, sigma, gamma); #endif /* Note : "same" code in qpois.c, qbinom.c, qnbinom.c -- * FIXME: This is far from optimal [cancellation for p ~= 1, etc]: */ if(!lower_tail || log_p) { p = R_DT_qIv(p); /* need check again (cancellation!): */ if (p == 0.) return 0.; if (p == 1.) return n; } /* temporary hack --- FIXME --- */ if (p + 1.01*DBL_EPSILON >= 1.) return n; /* y := approx.value (Cornish-Fisher expansion) : */ z = qnorm(p, 0., 1., /*lower_tail*/TRUE, /*log_p*/FALSE); y = floor(mu + sigma * (z + gamma * (z*z - 1) / 6) + 0.5); if(y > n) /* way off */ y = n; #ifdef DEBUG_qbinom REprintf(" new (p,1-p)=(%7g,%7g), z=qnorm(..)=%7g, y=%5g\n", p, 1-p, z, y); #endif z = pbinom(y, n, pr, /*lower_tail*/TRUE, /*log_p*/FALSE); /* fuzz to ensure left continuity: */ p *= 1 - 64*DBL_EPSILON; if(n < 1e5) return do_search(y, &z, p, n, pr, 1); /* Otherwise be a bit cleverer in the search */ { double incr = floor(n * 0.001), oldincr; do { oldincr = incr; y = do_search(y, &z, p, n, pr, incr); incr = fmax2(1, floor(incr/100)); } while(oldincr > 1 && incr > n*1e-15); return y; } }
double qbinom(double p, double n, double pr, int lower_tail, int log_p) { double q, mu, sigma, gamma, z, y; #ifdef IEEE_754 if (ISNAN(p) || ISNAN(n) || ISNAN(pr)) return p + n + pr; #endif if(!R_FINITE(p) || !R_FINITE(n) || !R_FINITE(pr)) ML_ERR_return_NAN; R_Q_P01_check(p); if(n != floor(n + 0.5)) ML_ERR_return_NAN; if (pr < 0 || pr > 1 || n < 0) ML_ERR_return_NAN; if (pr == 0. || n == 0) return 0.; if (p == R_DT_0) return 0.; if (p == R_DT_1) return n; q = 1 - pr; if(q == 0.) return n; /* covers the full range of the distribution */ mu = n * pr; sigma = sqrt(n * pr * q); gamma = (q - pr) / sigma; #ifdef DEBUG_qbinom REprintf("qbinom(p=%7g, n=%g, pr=%7g, l.t.=%d, log=%d): sigm=%g, gam=%g\n", p,n,pr, lower_tail, log_p, sigma, gamma); #endif /* Note : "same" code in qpois.c, qbinom.c, qnbinom.c -- * FIXME: This is far from optimal [cancellation for p ~= 1, etc]: */ if(!lower_tail || log_p) { p = R_DT_qIv(p); /* need check again (cancellation!): */ if (p == 0.) return 0.; if (p == 1.) return n; } /* temporary hack --- FIXME --- */ if (p + 1.01*DBL_EPSILON >= 1.) return n; /* y := approx.value (Cornish-Fisher expansion) : */ z = qnorm(p, 0., 1., /*lower_tail*/TRUE, /*log_p*/FALSE); y = floor(mu + sigma * (z + gamma * (z*z - 1) / 6) + 0.5); if(y > n) /* way off */ y = n; #ifdef DEBUG_qbinom REprintf(" new (p,1-p)=(%7g,%7g), z=qnorm(..)=%7g, y=%5g\n", p, 1-p, z, y); #endif z = pbinom(y, n, pr, /*lower_tail*/TRUE, /*log_p*/FALSE); /* fuzz to ensure left continuity: */ p *= 1 - 64*DBL_EPSILON; /*-- Fixme, here y can be way off -- should use interval search instead of primitive stepping down or up */ #ifdef maybe_future if((lower_tail && z >= p) || (!lower_tail && z <= p)) { #else if(z >= p) { #endif /* search to the left */ #ifdef DEBUG_qbinom REprintf("\tnew z=%7g >= p = %7g --> search to left (y--) ..\n", z,p); #endif for(;;) { if(y == 0 || (z = pbinom(y - 1, n, pr, /*l._t.*/TRUE, /*log_p*/FALSE)) < p) return y; y = y - 1; } } else { /* search to the right */ #ifdef DEBUG_qbinom REprintf("\tnew z=%7g < p = %7g --> search to right (y++) ..\n", z,p); #endif for(;;) { y = y + 1; if(y == n || (z = pbinom(y, n, pr, /*l._t.*/TRUE, /*log_p*/FALSE)) >= p) return y; } } }
double qnorm5(double p, double mu, double sigma, int lower_tail, int log_p) { double p_, q, r, val; #ifdef IEEE_754 if (ISNAN(p) || ISNAN(mu) || ISNAN(sigma)) return p + mu + sigma; #endif R_Q_P01_boundaries(p, ML_NEGINF, ML_POSINF); if(sigma < 0) ML_ERR_return_NAN; if(sigma == 0) return mu; p_ = R_DT_qIv(p);/* real lower_tail prob. p */ q = p_ - 0.5; #ifdef DEBUG_qnorm REprintf("qnorm(p=%10.7g, m=%g, s=%g, l.t.= %d, log= %d): q = %g\n", p,mu,sigma, lower_tail, log_p, q); #endif /*-- use AS 241 --- */ /* double ppnd16_(double *p, long *ifault)*/ /* ALGORITHM AS241 APPL. STATIST. (1988) VOL. 37, NO. 3 Produces the normal deviate Z corresponding to a given lower tail area of P; Z is accurate to about 1 part in 10**16. (original fortran code used PARAMETER(..) for the coefficients and provided hash codes for checking them...) */ if (fabs(q) <= .425) {/* 0.075 <= p <= 0.925 */ r = .180625 - q * q; val = q * (((((((r * 2509.0809287301226727 + 33430.575583588128105) * r + 67265.770927008700853) * r + 45921.953931549871457) * r + 13731.693765509461125) * r + 1971.5909503065514427) * r + 133.14166789178437745) * r + 3.387132872796366608) / (((((((r * 5226.495278852854561 + 28729.085735721942674) * r + 39307.89580009271061) * r + 21213.794301586595867) * r + 5394.1960214247511077) * r + 687.1870074920579083) * r + 42.313330701600911252) * r + 1.); } else { /* closer than 0.075 from {0,1} boundary */ /* r = min(p, 1-p) < 0.075 */ if (q > 0) r = R_DT_CIv(p);/* 1-p */ else r = p_;/* = R_DT_Iv(p) ^= p */ r = sqrt(- ((log_p && ((lower_tail && q <= 0) || (!lower_tail && q > 0))) ? p : /* else */ log(r))); /* r = sqrt(-log(r)) <==> min(p, 1-p) = exp( - r^2 ) */ #ifdef DEBUG_qnorm REprintf("\t close to 0 or 1: r = %7g\n", r); #endif if (r <= 5.) { /* <==> min(p,1-p) >= exp(-25) ~= 1.3888e-11 */ r += -1.6; val = (((((((r * 7.7454501427834140764e-4 + .0227238449892691845833) * r + .24178072517745061177) * r + 1.27045825245236838258) * r + 3.64784832476320460504) * r + 5.7694972214606914055) * r + 4.6303378461565452959) * r + 1.42343711074968357734) / (((((((r * 1.05075007164441684324e-9 + 5.475938084995344946e-4) * r + .0151986665636164571966) * r + .14810397642748007459) * r + .68976733498510000455) * r + 1.6763848301838038494) * r + 2.05319162663775882187) * r + 1.); } else { /* very close to 0 or 1 */ r += -5.; val = (((((((r * 2.01033439929228813265e-7 + 2.71155556874348757815e-5) * r + .0012426609473880784386) * r + .026532189526576123093) * r + .29656057182850489123) * r + 1.7848265399172913358) * r + 5.4637849111641143699) * r + 6.6579046435011037772) / (((((((r * 2.04426310338993978564e-15 + 1.4215117583164458887e-7)* r + 1.8463183175100546818e-5) * r + 7.868691311456132591e-4) * r + .0148753612908506148525) * r + .13692988092273580531) * r + .59983220655588793769) * r + 1.); } if(q < 0.0) val = -val; /* return (q >= 0.)? r : -r ;*/ } return mu + sigma * val; }
double qt(double p, double ndf, int lower_tail, int log_p) { const static double eps = 1.e-12; double P, q; Rboolean neg; #ifdef IEEE_754 if (ISNAN(p) || ISNAN(ndf)) return p + ndf; #endif R_Q_P01_boundaries(p, ML_NEGINF, ML_POSINF); if (ndf <= 0) ML_ERR_return_NAN; if (ndf < 1) { /* based on qnt */ const static double accu = 1e-13; const static double Eps = 1e-11; /* must be > accu */ double ux, lx, nx, pp; int iter = 0; p = R_DT_qIv(p); /* Invert pt(.) : * 1. finding an upper and lower bound */ if(p > 1 - DBL_EPSILON) return ML_POSINF; pp = fmin2(1 - DBL_EPSILON, p * (1 + Eps)); for(ux = 1.; ux < DBL_MAX && pt(ux, ndf, TRUE, FALSE) < pp; ux *= 2); pp = p * (1 - Eps); for(lx =-1.; lx > -DBL_MAX && pt(lx, ndf, TRUE, FALSE) > pp; lx *= 2); /* 2. interval (lx,ux) halving regula falsi failed on qt(0.1, 0.1) */ do { nx = 0.5 * (lx + ux); if (pt(nx, ndf, TRUE, FALSE) > p) ux = nx; else lx = nx; } while ((ux - lx) / fabs(nx) > accu && ++iter < 1000); if(iter >= 1000) ML_ERROR(ME_PRECISION, "qt"); return 0.5 * (lx + ux); } /* Old comment: * FIXME: "This test should depend on ndf AND p !! * ----- and in fact should be replaced by * something like Abramowitz & Stegun 26.7.5 (p.949)" * * That would say that if the qnorm value is x then * the result is about x + (x^3+x)/4df + (5x^5+16x^3+3x)/96df^2 * The differences are tiny even if x ~ 1e5, and qnorm is not * that accurate in the extreme tails. */ if (ndf > 1e20) return qnorm(p, 0., 1., lower_tail, log_p); P = R_D_qIv(p); /* if exp(p) underflows, we fix below */ neg = (!lower_tail || P < 0.5) && (lower_tail || P > 0.5); if(neg) P = 2 * (log_p ? (lower_tail ? P : -expm1(p)) : R_D_Lval(p)); else P = 2 * (log_p ? (lower_tail ? -expm1(p) : P) : R_D_Cval(p)); /* 0 <= P <= 1 ; P = 2*min(P', 1 - P') in all cases */ /* Use this if(log_p) only : */ #define P_is_exp_2p (lower_tail == neg) /* both TRUE or FALSE == !xor */ if (fabs(ndf - 2) < eps) { /* df ~= 2 */ if(P > DBL_MIN) { if(3* P < DBL_EPSILON) /* P ~= 0 */ q = 1 / sqrt(P); else if (P > 0.9) /* P ~= 1 */ q = (1 - P) * sqrt(2 /(P * (2 - P))); else /* eps/3 <= P <= 0.9 */ q = sqrt(2 / (P * (2 - P)) - 2); } else { /* P << 1, q = 1/sqrt(P) = ... */ if(log_p) q = P_is_exp_2p ? exp(- p/2) / M_SQRT2 : 1/sqrt(-expm1(p)); else q = ML_POSINF; } } else if (ndf < 1 + eps) { /* df ~= 1 (df < 1 excluded above): Cauchy */ if(P > 0) q = 1/tan(P * M_PI_2);/* == - tan((P+1) * M_PI_2) -- suffers for P ~= 0 */ else { /* P = 0, but maybe = 2*exp(p) ! */ if(log_p) /* 1/tan(e) ~ 1/e */ q = P_is_exp_2p ? M_1_PI * exp(-p) : -1./(M_PI * expm1(p)); else q = ML_POSINF; } } else { /*-- usual case; including, e.g., df = 1.1 */ double x = 0., y, log_P2 = 0./* -Wall */, a = 1 / (ndf - 0.5), b = 48 / (a * a), c = ((20700 * a / b - 98) * a - 16) * a + 96.36, d = ((94.5 / (b + c) - 3) / b + 1) * sqrt(a * M_PI_2) * ndf; Rboolean P_ok1 = P > DBL_MIN || !log_p, P_ok = P_ok1; if(P_ok1) { y = pow(d * P, 2 / ndf); P_ok = (y >= DBL_EPSILON); } if(!P_ok) { /* log_p && P very small */ log_P2 = P_is_exp_2p ? p : R_Log1_Exp(p); /* == log(P / 2) */ x = (log(d) + M_LN2 + log_P2) / ndf; y = exp(2 * x); } if ((ndf < 2.1 && P > 0.5) || y > 0.05 + a) { /* P > P0(df) */ /* Asymptotic inverse expansion about normal */ if(P_ok) x = qnorm(0.5 * P, 0., 1., /*lower_tail*/TRUE, /*log_p*/FALSE); else /* log_p && P underflowed */ x = qnorm(log_P2, 0., 1., lower_tail, /*log_p*/ TRUE); y = x * x; if (ndf < 5) c += 0.3 * (ndf - 4.5) * (x + 0.6); c = (((0.05 * d * x - 5) * x - 7) * x - 2) * x + b + c; y = (((((0.4 * y + 6.3) * y + 36) * y + 94.5) / c - y - 3) / b + 1) * x; y = expm1(a * y * y); q = sqrt(ndf * y); } else { /* re-use 'y' from above */ if(!P_ok && x < - M_LN2 * DBL_MANT_DIG) {/* 0.5* log(DBL_EPSILON) */ /* y above might have underflown */ q = sqrt(ndf) * exp(-x); } else { y = ((1 / (((ndf + 6) / (ndf * y) - 0.089 * d - 0.822) * (ndf + 2) * 3) + 0.5 / (ndf + 4)) * y - 1) * (ndf + 1) / (ndf + 2) + 1 / y; q = sqrt(ndf * y); } } /* Now apply 2-term Taylor expansion improvement (1-term = Newton): * as by Hill (1981) [ref.above] */ /* FIXME: This can be far from optimal when log_p = TRUE * but is still needed, e.g. for qt(-2, df=1.01, log=TRUE). * Probably also improvable when lower_tail = FALSE */ if(P_ok1) { int it=0; while(it++ < 10 && (y = dt(q, ndf, FALSE)) > 0 && R_FINITE(x = (pt(q, ndf, FALSE, FALSE) - P/2) / y) && fabs(x) > 1e-14*fabs(q)) /* Newton (=Taylor 1 term): * q += x; * Taylor 2-term : */ q += x * (1. + x * q * (ndf + 1) / (2 * (q * q + ndf))); } } if(neg) q = -q; return q; }
double qbeta(double alpha, double p, double q, int lower_tail, int log_p) { int swap_tail, i_pb, i_inn; double a, adj, logbeta, g, h, pp, p_, prev, qq, r, s, t, tx, w, y, yprev; double acu; volatile double xinbta; /* test for admissibility of parameters */ if (isnan(p) || isnan(q) || isnan(alpha)){ return p + q + alpha; } if(p < 0. || q < 0.){ report_error("shape parameters for qbeta must be > 0."); } R_Q_P01_boundaries(alpha, 0, 1); p_ = R_DT_qIv(alpha);/* lower_tail prob (in any case) */ if(log_p && (p_ == 0. || p_ == 1.)) return p_; /* better than NaN or infinite loop; FIXME: suboptimal, since -Inf < alpha ! */ /* initialize */ logbeta = lbeta(p, q); /* change tail if necessary; afterwards 0 < a <= 1/2 */ if (p_ <= 0.5) { a = p_; pp = p; qq = q; swap_tail = 0; } else { /* change tail, swap p <-> q :*/ a = (!lower_tail && !log_p)? alpha : 1 - p_; pp = q; qq = p; swap_tail = 1; } /* calculate the initial approximation */ /* y := {fast approximation of} qnorm(1 - a) :*/ r = sqrt(-2 * log(a)); y = r - (const1 + const2 * r) / (1. + (const3 + const4 * r) * r); if (pp > 1 && qq > 1) { r = (y * y - 3.) / 6.; s = 1. / (pp + pp - 1.); t = 1. / (qq + qq - 1.); h = 2. / (s + t); w = y * sqrt(h + r) / h - (t - s) * (r + 5. / 6. - 2. / (3. * h)); xinbta = pp / (pp + qq * exp(w + w)); } else { r = qq + qq; t = 1. / (9. * qq); t = r * pow(1. - t + y * sqrt(t), 3.0); if (t <= 0.) xinbta = 1. - exp((log1p(-a)+ log(qq) + logbeta) / qq); else { t = (4. * pp + r - 2.) / t; if (t <= 1.) xinbta = exp((log(a * pp) + logbeta) / pp); else xinbta = 1. - 2. / (t + 1.); } } /* solve for x by a modified newton-raphson method, */ /* using the function pbeta_raw */ r = 1 - pp; t = 1 - qq; yprev = 0.; adj = 1; /* Sometimes the approximation is negative! */ if (xinbta < lower) xinbta = 0.5; else if (xinbta > upper) xinbta = 0.5; /* Desired accuracy should depend on (a,p) * This is from Remark .. on AS 109, adapted. * However, it's not clear if this is "optimal" for IEEE double prec. * acu = std::max<double>(acu_min, pow(10., -25. - 5./(pp * pp) - 1./(a * a))); * NEW: 'acu' accuracy NOT for squared adjustment, but simple; * ---- i.e., "new acu" = sqrt(old acu) */ acu = std::max<double>(acu_min, pow(10., -13 - 2.5/(pp * pp) - 0.5/(a * a))); tx = prev = 0.; /* keep -Wall happy */ for (i_pb=0; i_pb < 1000; i_pb++) { y = pbeta_raw(xinbta, pp, qq, /*lower_tail = */ true, false); if(!std::isfinite(y)){ report_error("algorithm blew up ni qbeta"); } y = (y - a) * exp(logbeta + r * log(xinbta) + t * log1p(-xinbta)); if (y * yprev <= 0.) prev = std::max<double>(fabs(adj),fpu); g = 1; for (i_inn=0; i_inn < 1000;i_inn++) { adj = g * y; if (fabs(adj) < prev) { tx = xinbta - adj; /* trial new x */ if (tx >= 0. && tx <= 1) { if (prev <= acu) goto L_converged; if (fabs(y) <= acu) goto L_converged; if (tx != 0. && tx != 1) break; } } g /= 3; } if (fabs(tx - xinbta) < 1e-15*xinbta) goto L_converged; xinbta = tx; yprev = y; } /*-- NOT converged: Iteration count --*/ report_error("algorithm did not converge in qbeta"); L_converged: return swap_tail ? 1 - xinbta : xinbta; }
double qgamma(double p, double alpha, double scale, int lower_tail, int log_p) /* shape = alpha */ { #define C7 4.67 #define C8 6.66 #define C9 6.73 #define C10 13.32 #define EPS1 1e-2 #define EPS2 5e-7/* final precision */ #define MAXIT 1000/* was 20 */ #define pMIN 1e-100 /* was 0.000002 = 2e-6 */ #define pMAX (1-1e-12)/* was 0.999998 = 1 - 2e-6 */ const double i420 = 1./ 420., i2520 = 1./ 2520., i5040 = 1./ 5040; double p_, a, b, c, ch, g, p1, v; double p2, q, s1, s2, s3, s4, s5, s6, t, x; int i; /* test arguments and initialise */ #ifdef IEEE_754 if (ISNAN(p) || ISNAN(alpha) || ISNAN(scale)) return p + alpha + scale; #endif R_Q_P01_check(p); if (alpha <= 0) ML_ERR_return_NAN; /* FIXME: This (cutoff to {0, +Inf}) is far from optimal when log_p: */ p_ = R_DT_qIv(p);/* lower_tail prob (in any case) */ if (/* 0 <= */ p_ < pMIN) return 0; if (/* 1 >= */ p_ > pMAX) return BOOM::infinity(); v = 2*alpha; c = alpha-1; g = lgammafn(alpha);/* log Gamma(v/2) */ /*----- Phase I : Starting Approximation */ #ifdef DEBUG_qgamma REprintf("qgamma(p=%7g, alpha=%7g, scale=%7g, l.t.=%2d, log_p=%2d): ", p,alpha,scale, lower_tail, log_p); #endif if(v < (-1.24)*R_DT_log(p)) { /* for small chi-squared */ #ifdef DEBUG_qgamma REprintf(" small chi-sq.\n"); #endif /* FIXME: Improve this "if (log_p)" : * (A*exp(b)) ^ 1/al */ ch = pow(p_* alpha*exp(g+alpha*M_LN2), 1/alpha); if(ch < EPS2) {/* Corrected according to AS 91; MM, May 25, 1999 */ goto END; } } else if(v > 0.32) { /* using Wilson and Hilferty estimate */ x = qnorm(p, 0, 1, lower_tail, log_p); p1 = 0.222222/v; ch = v*pow(x*sqrt(p1)+1-p1, 3); #ifdef DEBUG_qgamma REprintf(" v > .32: Wilson-Hilferty; x = %7g\n", x); #endif /* starting approximation for p tending to 1 */ if( ch > 2.2*v + 6 ) ch = -2*(R_DT_Clog(p) - c*log(0.5*ch) + g); } else { /* for v <= 0.32 */ ch = 0.4; a = R_DT_Clog(p) + g + c*M_LN2; #ifdef DEBUG_qgamma REprintf(" v <= .32: a = %7g\n", a); #endif do { q = ch; p1 = 1. / (1+ch*(C7+ch)); p2 = ch*(C9+ch*(C8+ch)); t = -0.5 +(C7+2*ch)*p1 - (C9+ch*(C10+3*ch))/p2; ch -= (1- exp(a+0.5*ch)*p2*p1)/t; } while(fabs(q - ch) > EPS1*fabs(ch)); } #ifdef DEBUG_qgamma REprintf("\t==> ch = %10g:", ch); #endif /*----- Phase II: Iteration * Call pgamma() [AS 239] and calculate seven term taylor series */ for( i=1 ; i <= MAXIT ; i++ ) { q = ch; p1 = 0.5*ch; p2 = p_ - pgamma(p1, alpha, 1, /*lower_tail*/true, /*log_p*/false); #ifdef IEEE_754 if(!R_FINITE(p2)) #else if(errno != 0) #endif return numeric_limits<double>::quiet_NaN(); t = p2*exp(alpha*M_LN2+g+p1-c*log(ch)); b = t/ch; a = 0.5*t - b*c; s1 = (210+a*(140+a*(105+a*(84+a*(70+60*a))))) * i420; s2 = (420+a*(735+a*(966+a*(1141+1278*a)))) * i2520; s3 = (210+a*(462+a*(707+932*a))) * i2520; s4 = (252+a*(672+1182*a)+c*(294+a*(889+1740*a))) * i5040; s5 = (84+2264*a+c*(1175+606*a)) * i2520; s6 = (120+c*(346+127*c)) * i5040; ch += t*(1+0.5*t*s1-b*c*(s1-b*(s2-b*(s3-b*(s4-b*(s5-b*s6)))))); if(fabs(q - ch) < EPS2*ch) goto END; } ML_ERROR(ME_PRECISION);/* no convergence in MAXIT iterations */ END: return 0.5*scale*ch; }
double qtukey(double p, double rr, double cc, double df, int lower_tail, int log_p) { const static double eps = 0.0001; const int maxiter = 50; double ans = 0.0, valx0, valx1, x0, x1, xabs; int iter; #ifdef IEEE_754 if (ISNAN(p) || ISNAN(rr) || ISNAN(cc) || ISNAN(df)) { ML_ERROR(ME_DOMAIN, "qtukey"); return p + rr + cc + df; } #endif /* df must be > 1 ; there must be at least two values */ if (df < 2 || rr < 1 || cc < 2) ML_ERR_return_NAN; R_Q_P01_boundaries(p, 0, ML_POSINF); p = R_DT_qIv(p); /* lower_tail,non-log "p" */ /* Initial value */ x0 = qinv(p, cc, df); /* Find prob(value < x0) */ valx0 = ptukey(x0, rr, cc, df, /*LOWER*/TRUE, /*LOG_P*/FALSE) - p; /* Find the second iterate and prob(value < x1). */ /* If the first iterate has probability value */ /* exceeding p then second iterate is 1 less than */ /* first iterate; otherwise it is 1 greater. */ if (valx0 > 0.0) x1 = fmax2(0.0, x0 - 1.0); else x1 = x0 + 1.0; valx1 = ptukey(x1, rr, cc, df, /*LOWER*/TRUE, /*LOG_P*/FALSE) - p; /* Find new iterate */ for(iter=1 ; iter < maxiter ; iter++) { ans = x1 - ((valx1 * (x1 - x0)) / (valx1 - valx0)); valx0 = valx1; /* New iterate must be >= 0 */ x0 = x1; if (ans < 0.0) { ans = 0.0; valx1 = -p; } /* Find prob(value < new iterate) */ valx1 = ptukey(ans, rr, cc, df, /*LOWER*/TRUE, /*LOG_P*/FALSE) - p; x1 = ans; /* If the difference between two successive */ /* iterates is less than eps, stop */ xabs = fabs(x1 - x0); if (xabs < eps) return ans; } /* The process did not converge in 'maxiter' iterations */ ML_ERROR(ME_NOCONV, "qtukey"); return ans; }
double qnbinom(double p, double n, double pr, int lower_tail, int log_p) { double P, Q, mu, sigma, gamma, z, y; #ifdef IEEE_754 if (ISNAN(p) || ISNAN(n) || ISNAN(pr)) return p + n + pr; #endif R_Q_P01_check(p); if (pr <= 0 || pr >= 1 || n <= 0) ML_ERR_return_NAN; if (p == R_DT_0) return 0; if (p == R_DT_1) return ML_POSINF; Q = 1.0 / pr; P = (1.0 - pr) * Q; mu = n * P; sigma = sqrt(n * P * Q); gamma = (Q + P)/sigma; /* Note : "same" code in qpois.c, qbinom.c, qnbinom.c -- * FIXME: This is far from optimal [cancellation for p ~= 1, etc]: */ if(!lower_tail || log_p) { p = R_DT_qIv(p); /* need check again (cancellation!): */ if (p == R_DT_0) return 0; if (p == R_DT_1) return ML_POSINF; } /* temporary hack --- FIXME --- */ if (p + 1.01*DBL_EPSILON >= 1.) return ML_POSINF; /* y := approx.value (Cornish-Fisher expansion) : */ z = qnorm(p, 0., 1., /*lower_tail*/TRUE, /*log_p*/FALSE); y = floor(mu + sigma * (z + gamma * (z*z - 1) / 6) + 0.5); z = pnbinom(y, n, pr, /*lower_tail*/TRUE, /*log_p*/FALSE); /* fuzz to ensure left continuity: */ p *= 1 - 64*DBL_EPSILON; /*-- Fixme, here y can be way off -- should use interval search instead of primitive stepping down or up */ #ifdef maybe_future if((lower_tail && z >= p) || (!lower_tail && z <= p)) { #else if(z >= p) { #endif /* search to the left */ for(;;) { if(y == 0 || (z = pnbinom(y - 1, n, pr, /*l._t.*/TRUE, /*log_p*/FALSE)) < p) return y; y = y - 1; } } else { /* search to the right */ for(;;) { y = y + 1; if((z = pnbinom(y, n, pr, /*l._t.*/TRUE, /*log_p*/FALSE)) >= p) return y; } } }