DBL chdtri(DBL df, DBL y) { DBL x; if ((y < 0.0) || (y > 1.0) || (df < 1.0)) throw POV_EXCEPTION_STRING("Illegal values in chdtri()."); x = igami(0.5 * df, y); return (2.0 * x); }
double chdtri (double df, double y) { double x; if (y < 0.0 || y > 1.0 || df < 1.0) { mtherr("chdtri", CEPHES_DOMAIN); return 0.0; } x = igami(0.5 * df, y); return 2.0 * x; }
double pdtri( int k, double y ) { double v; if( (k < 0) || (y < 0.0) || (y >= 1.0) ) { mtherr( "pdtri", DOMAIN ); return( 0.0 ); } v = k+1; v = igami( v, y ); return( v ); }
double gammaincinv(double a, double y) { double lo = 0.0, hi; double flo = -y, fhi = 0.25 - y; double params[2]; double best_x, best_f, errest; fsolve_result_t r; if (a <= 0.0 || y <= 0.0 || y >= 0.25) { return igami(a, 1-y); } /* Note: flo and fhi must have different signs (and be != 0), * otherwise fsolve terminates with an error. */ params[0] = a; params[1] = y; hi = igami(a, 0.75); /* I found Newton to be unreliable. Also, after we generate a small interval by bisection above, false position will do a large step from an interval of width ~1e-4 to ~1e-14 in one step (a=10, x=0.05, but similiar for other values). */ r = false_position(&lo, &flo, &hi, &fhi, (objective_function)gammainc, params, 2*MACHEP, 2*MACHEP, 1e-2*a, &best_x, &best_f, &errest); if (!(r == FSOLVE_CONVERGED || r == FSOLVE_EXACT) && errest > ALLOWED_ATOL + ALLOWED_RTOL*fabs(best_x)) { best_x = GAMMAINCINV_NaN; } return best_x; }
double igamci(double a, double q) { int i; double x, fac, f_fp, fpp_fp; if (npy_isnan(a) || npy_isnan(q)) { return NPY_NAN; } else if ((a < 0.0) || (q < 0.0) || (q > 1.0)) { mtherr("gammainccinv", DOMAIN); } else if (q == 0.0) { return NPY_INFINITY; } else if (q == 1.0) { return 0.0; } else if (q > 0.9) { return igami(a, 1 - q); } x = find_inverse_gamma(a, 1 - q, q); for (i = 0; i < 3; i++) { fac = igam_fac(a, x); if (fac == 0.0) { return x; } f_fp = (igamc(a, x) - q) * x / (-fac); fpp_fp = -1.0 + (a - 1) / x; if (npy_isinf(fpp_fp)) { x = x - f_fp; } else { x = x - f_fp / (1.0 - 0.5 * f_fp * fpp_fp); } } return x; }