/src/r-source/src/nmath/qnbeta.c
Line | Count | Source |
1 | | /* |
2 | | * R : A Computer Language for Statistical Data Analysis |
3 | | * Copyright (C) 2006 The R Core Team |
4 | | * |
5 | | * This program is free software; you can redistribute it and/or modify |
6 | | * it under the terms of the GNU General Public License as published by |
7 | | * the Free Software Foundation; either version 2 of the License, or |
8 | | * (at your option) any later version. |
9 | | * |
10 | | * This program is distributed in the hope that it will be useful, |
11 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | | * GNU General Public License for more details. |
14 | | * |
15 | | * You should have received a copy of the GNU General Public License |
16 | | * along with this program; if not, a copy is available at |
17 | | * https://www.R-project.org/Licenses/ |
18 | | */ |
19 | | |
20 | | #include "nmath.h" |
21 | | #include "dpq.h" |
22 | | |
23 | | double qnbeta(double p, double a, double b, double ncp, |
24 | | int lower_tail, int log_p) |
25 | 0 | { |
26 | 0 | const static double accu = 1e-15; |
27 | 0 | const static double Eps = 1e-14; /* must be > accu */ |
28 | |
|
29 | 0 | double ux, lx, nx, pp; |
30 | |
|
31 | 0 | #ifdef IEEE_754 |
32 | 0 | if (ISNAN(p) || ISNAN(a) || ISNAN(b) || ISNAN(ncp)) |
33 | 0 | return p + a + b + ncp; |
34 | 0 | #endif |
35 | 0 | if (!R_FINITE(a)) ML_WARN_return_NAN; |
36 | |
|
37 | 0 | if (ncp < 0. || a <= 0. || b <= 0.) ML_WARN_return_NAN; |
38 | |
|
39 | 0 | R_Q_P01_boundaries(p, 0, 1); |
40 | |
|
41 | 0 | p = R_DT_qIv(p); |
42 | | |
43 | | /* Invert pnbeta(.) : |
44 | | * 1. finding an upper and lower bound */ |
45 | 0 | if(p > 1 - DBL_EPSILON) return 1.0; |
46 | 0 | pp = fmin2(1 - DBL_EPSILON, p * (1 + Eps)); |
47 | 0 | for(ux = 0.5; |
48 | 0 | ux < 1 - DBL_EPSILON && pnbeta(ux, a, b, ncp, TRUE, FALSE) < pp; |
49 | 0 | ux = 0.5*(1+ux)); |
50 | 0 | pp = p * (1 - Eps); |
51 | 0 | for(lx = 0.5; |
52 | 0 | lx > DBL_MIN && pnbeta(lx, a, b, ncp, TRUE, FALSE) > pp; |
53 | 0 | lx *= 0.5); |
54 | | |
55 | | /* 2. interval (lx,ux) halving : */ |
56 | 0 | do { |
57 | 0 | nx = 0.5 * (lx + ux); |
58 | 0 | if (pnbeta(nx, a, b, ncp, TRUE, FALSE) > p) ux = nx; else lx = nx; |
59 | 0 | } |
60 | 0 | while ((ux - lx) / nx > accu); |
61 | |
|
62 | 0 | return 0.5 * (ux + lx); |
63 | 0 | } |