The R Project SVN R

Rev

Rev 69248 | Rev 79203 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 69248 Rev 77124
Line 9... Line 9...
9
 *    Ding, C. G. (1992)
9
 *    Ding, C. G. (1992)
10
 *    Algorithm AS275: Computing the non-central chi-squared
10
 *    Algorithm AS275: Computing the non-central chi-squared
11
 *    distribution function. Appl.Statist., 41, 478-482.
11
 *    distribution function. Appl.Statist., 41, 478-482.
12
 
12
 
13
 *  Other parts
13
 *  Other parts
14
 *  Copyright (C) 2000-2015  The R Core Team
14
 *  Copyright (C) 2000-2019  The R Core Team
15
 *  Copyright (C) 2003-2015  The R Foundation
15
 *  Copyright (C) 2003-2015  The R Foundation
16
 */
16
 */
17
 
17
 
18
 
18
 
19
 
19
 
Line 54... Line 54...
54
#endif
54
#endif
55
 
55
 
56
    if (df < 0. || ncp < 0.) ML_ERR_return_NAN;
56
    if (df < 0. || ncp < 0.) ML_ERR_return_NAN;
57
 
57
 
58
    ans = pnchisq_raw(x, df, ncp, 1e-12, 8*DBL_EPSILON, 1000000, lower_tail, log_p);
58
    ans = pnchisq_raw(x, df, ncp, 1e-12, 8*DBL_EPSILON, 1000000, lower_tail, log_p);
-
 
59
 
-
 
60
    if (x <= 0. || x == ML_POSINF)
-
 
61
	return ans; // because it's perfect
-
 
62
 
59
    if(ncp >= 80) {
63
    if(ncp >= 80) {
60
	if(lower_tail) {
64
	if(lower_tail) {
61
	    ans = fmin2(ans, R_D__1);  /* e.g., pchisq(555, 1.01, ncp = 80) */
65
	    ans = fmin2(ans, R_D__1);  /* e.g., pchisq(555, 1.01, ncp = 80) */
62
	} else { /* !lower_tail */
66
	} else { /* !lower_tail */
63
	    /* since we computed the other tail cancellation is likely */
67
	    /* since we computed the other tail cancellation is likely */
-
 
68
	    // FIXME: There are cases where  ans == 0. if(!log_p) is perfect
64
	    if(ans < (log_p ? (-10. * M_LN10) : 1e-10)) ML_ERROR(ME_PRECISION, "pnchisq");
69
	    if(ans < (log_p ? (-10. * M_LN10) : 1e-10)) ML_ERROR(ME_PRECISION, "pnchisq");
65
	    if(!log_p) ans = fmax2(ans, 0.0);  /* Precaution PR#7099 */
70
	    if(!log_p && ans < 0.) ans = 0.;  /* Precaution PR#7099 */
66
	}
71
	}
67
    }
72
    }
-
 
73
    /* MM: the following "hack" from c51179 (<--> PR#14216, by Jerry Lewis)
-
 
74
     * -- is "kind of ok" ... but potentially suboptimal: we do  log1p(- p(*, <other tail>, log=FALSE)),
-
 
75
     *    but that  p(*, log=FALSE) may already be an exp(.) or even expm1(..)
-
 
76
     *   <---> "in principle"  this check should happen there, not here  */
68
    if (!log_p || ans < -1e-8)
77
    if (!log_p || ans < -1e-8)
69
	return ans;
78
	return ans;
70
    else { // log_p  &&  ans > -1e-8
79
    else { // log_p  &&  ans >= -1e-8
71
	// prob. = exp(ans) is near one: we can do better using the other tail
80
	// prob. = exp(ans) is near one: we can do better using the other tail
72
#ifdef DEBUG_pnch
81
#ifdef DEBUG_pnch
73
	REprintf("   pnchisq_raw(*, log_p): ans=%g => 2nd call, other tail\n", ans);
82
	REprintf("   pnchisq_raw(*, log_p): ans=%g => 2nd call, other tail\n", ans);
74
#endif
83
#endif
75
	// FIXME: (sum,sum2) will be the same (=> return them as well and reuse here ?)
-
 
76
	ans = pnchisq_raw(x, df, ncp, 1e-12, 8*DBL_EPSILON, 1000000, !lower_tail, FALSE);
84
	ans = pnchisq_raw(x, df, ncp, 1e-12, 8*DBL_EPSILON, 1000000, !lower_tail, FALSE);
77
	return log1p(-ans);
85
	return log1p(-ans);
78
    }
86
    }
79
}
87
}
80
 
88
 
Line 84... Line 92...
84
	    Rboolean lower_tail, Rboolean log_p)
92
	    Rboolean lower_tail, Rboolean log_p)
85
{
93
{
86
    double lam, x2, f2, term, bound, f_x_2n, f_2n;
94
    double lam, x2, f2, term, bound, f_x_2n, f_2n;
87
    double l_lam = -1., l_x = -1.; /* initialized for -Wall */
95
    double l_lam = -1., l_x = -1.; /* initialized for -Wall */
88
    int n;
96
    int n;
89
    Rboolean lamSml, tSml, is_r, is_b, is_it;
97
    Rboolean lamSml, tSml, is_r, is_b;
90
    LDOUBLE ans, u, v, t, lt, lu =-1;
98
    LDOUBLE ans, u, v, t, lt, lu =-1;
91
 
99
 
92
    if (x <= 0.) {
100
    if (x <= 0.) {
93
	if(x == 0. && f == 0.) {
101
	if(x == 0. && f == 0.) { // chi^2_0(.) has point mass at zero
94
#define _L  (-0.5 * theta) // = -lambda
102
#define _L  (-0.5 * theta) // = -lambda
95
	    return lower_tail ? R_D_exp(_L) : (log_p ? R_Log1_Exp(_L) : -expm1(_L));
103
	    return lower_tail ? R_D_exp(_L) : (log_p ? R_Log1_Exp(_L) : -expm1(_L));
96
	}
104
	}
97
	/* x < 0  or {x==0, f > 0} */
105
	/* x < 0  or {x==0, f > 0} */
98
	return R_DT_0;
106
	return R_DT_0;
Line 132... Line 140...
132
		     x,f,theta, i, (double)sum, (double)sum2);
140
		     x,f,theta, i, (double)sum, (double)sum2);
133
#endif
141
#endif
134
	    return (double) (log_p ? ans : EXP(ans));
142
	    return (double) (log_p ? ans : EXP(ans));
135
	}
143
	}
136
	else {
144
	else {
137
	    LDOUBLE lambda = 0.5 * theta;
145
	    LDOUBLE lambda = 0.5 * theta; // < 40
138
	    LDOUBLE sum = 0, sum2 = 0, pr = EXP(-lambda); // does this need a feature test?
146
	    LDOUBLE sum = 0, sum2 = 0, pr = EXP(-lambda); // does this need a feature test?
139
	    /* we need to renormalize here: the result could be very close to 1 */
147
	    /* we need to renormalize here: the result could be very close to 1 */
140
	    for(i = 0; i < 110;  pr *= lambda/++i) {
148
	    for(i = 0; i < 110;  pr *= lambda/++i) {
141
		// pr == exp(-lambda) lambda^i / i!  ==  dpois(i, lambda)
149
		// pr == exp(-lambda) lambda^i / i!  ==  dpois(i, lambda)
142
		sum2 += pr;
150
		sum2 += pr;
Line 156... Line 164...
156
 
164
 
157
    // else: theta == ncp >= 80 --------------------------------------------
165
    // else: theta == ncp >= 80 --------------------------------------------
158
#ifdef DEBUG_pnch
166
#ifdef DEBUG_pnch
159
    REprintf("pnchisq(x=%g, f=%g, theta=%g >= 80): ",x,f,theta);
167
    REprintf("pnchisq(x=%g, f=%g, theta=%g >= 80): ",x,f,theta);
160
#endif
168
#endif
161
    // Series expansion ------- FIXME: log_p=TRUE, lower_tail=FALSE only applied at end
169
    // Series expansion ------- FIXME: log_p=TRUE, lower_tail=FALSE only applied at end ==> underflow
162
 
170
 
163
    lam = .5 * theta;
171
    lam = .5 * theta; // = lambda = ncp/2
164
    lamSml = (-lam < _dbl_min_exp);
172
    lamSml = (-lam < _dbl_min_exp);
165
    if(lamSml) {
173
    if(lamSml) {
166
	/* MATHLIB_ERROR(
174
	/* MATHLIB_ERROR(
167
	   "non centrality parameter (= %g) too large for current algorithm",
175
	   "non centrality parameter (= %g) too large for current algorithm",
168
	   theta) */
176
p 	   theta) */
169
        u = 0;
177
        u = 0;
170
        lu = -lam;/* == ln(u) */
178
        lu = -lam;/* == ln(u) */
171
        l_lam = log(lam);
179
        l_lam = log(lam);
172
    } else {
180
    } else {
173
	u = exp(-lam);
181
	u = exp(-lam);
Line 219... Line 227...
219
 	REprintf(", t=exp(lt)= %g\n", t);
227
 	REprintf(", t=exp(lt)= %g\n", t);
220
#endif
228
#endif
221
	ans = term = (double) (v * t);
229
	ans = term = (double) (v * t);
222
    }
230
    }
223
 
231
 
224
    for (n = 1, f_2n = f + 2., f_x_2n += 2.;  ; n++, f_2n += 2, f_x_2n += 2) {
232
    for (n = 1, f_2n = f + 2., f_x_2n += 2.; n <= itrmax ; n++, f_2n += 2, f_x_2n += 2) {
225
#ifdef DEBUG_pnch_n
233
#ifdef DEBUG_pnch_n
226
	REprintf("\n _OL_: n=%d",n);
234
	REprintf("\n _OL_: n=%d",n);
227
#endif
235
#endif
228
#ifndef MATHLIB_STANDALONE
236
#ifndef MATHLIB_STANDALONE
229
	if(n % 1000) R_CheckUserInterrupt();
237
	if(n % 1000 == 0) R_CheckUserInterrupt();
230
#endif
238
#endif
231
	/* f_2n    === f + 2*n
239
	/* f_2n    === f + 2*n
232
	 * f_x_2n  === f - x + 2*n   > 0  <==> (f+2n)  >   x */
240
	 * f_x_2n  === f - x + 2*n   > 0  <==> (f+2n)  >   x */
233
	if (f_x_2n > 0) {
241
	if (f_x_2n > 0) {
234
	    /* find the error bound and check for convergence */
242
	    /* find the error bound and check for convergence */
235
 
243
 
236
	    bound = (double) (t * x / f_x_2n);
244
	    bound = (double) (t * x / f_x_2n);
237
#ifdef DEBUG_pnch_n
245
#ifdef DEBUG_pnch_n
238
	    REprintf("\n L10: n=%d; term= %g; bound= %g",n,term,bound);
246
	    REprintf("\n L10: n=%d; term= %g; bound= %g",n,term,bound);
239
#endif
247
#endif
240
	    is_r = is_it = FALSE;
248
	    is_r = FALSE;
241
	    /* convergence only if BOTH absolute and relative error < 'bnd' */
249
	    /* convergence only if BOTH absolute and relative error < 'bnd' */
242
	    if (((is_b = (bound <= errmax)) &&
250
	    if (((is_b = (bound <= errmax)) &&
243
                 (is_r = (term <= reltol * ans))) || (is_it = (n > itrmax)))
251
                 (is_r = (term <= reltol * ans))))
244
            {
252
            {
245
#ifdef DEBUG_pnch
253
#ifdef DEBUG_pnch
246
                REprintf("BREAK n=%d %s; bound= %g %s, rel.err= %g %s\n",
254
                REprintf("BREAK out of for(n = 1 ..): n=%d; bound= %g %s, rel.err= %g %s\n",
247
			 n, (is_it ? "> itrmax" : ""),
255
			 n,
248
			 bound, (is_b ? "<= errmax" : ""),
256
			 bound, (is_b ? "<= errmax" : ""),
249
			 term/ans, (is_r ? "<= reltol" : ""));
257
			 term/ans, (is_r ? "<= reltol" : ""));
250
#endif
258
#endif
251
		break; /* out completely */
259
		break; /* out completely */
252
            }
260
            }
253
 
-
 
254
	}
261
	}
255
 
262
 
256
	/* evaluate the next term of the */
263
	/* evaluate the next term of the */
257
	/* expansion and then the partial sum */
264
	/* expansion and then the partial sum */
258
 
265
 
Line 289... Line 296...
289
	    ans += term;
296
	    ans += term;
290
	}
297
	}
291
 
298
 
292
    } /* for(n ...) */
299
    } /* for(n ...) */
293
 
300
 
294
    if (is_it) {
301
    if (n > itrmax) {
295
	MATHLIB_WARNING2(_("pnchisq(x=%g, ..): not converged in %d iter."),
302
	MATHLIB_WARNING4(_("pnchisq(x=%g, f=%g, theta=%g, ..): not converged in %d iter."),
296
			 x, itrmax);
303
			 x, f, theta, itrmax);
297
    }
304
    }
298
#ifdef DEBUG_pnch
305
#ifdef DEBUG_pnch
299
    REprintf("\n == L_End: n=%d; term= %g; bound=%g\n",n,term,bound);
306
    REprintf("\n == L_End: n=%d; term= %g; bound=%g: ans=%Lg\n",
-
 
307
	     n, term, bound, ans);
300
#endif
308
#endif
301
    double dans = (double) ans;
309
    double dans = (double) ans;
302
    return R_DT_val(dans);
310
    return R_DT_val(dans);
303
}
311
}