The R Project SVN R

Rev

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

Rev 34244 Rev 34588
Line 22... Line 22...
22
 *
22
 *
23
 *
23
 *
24
 *  DESCRIPTION
24
 *  DESCRIPTION
25
 *
25
 *
26
 *    The density function of the F distribution.
26
 *    The density function of the F distribution.
27
 *    To evaluate it, write it as a Binomial probability with p = x*m/(n+x*m). 
27
 *    To evaluate it, write it as a Binomial probability with p = x*m/(n+x*m).
28
 *    For m >= 2, we use the simplest conversion.
28
 *    For m >= 2, we use the simplest conversion.
29
 *    For m < 2, (m-2)/2 < 0 so the conversion will not work, and we must use
29
 *    For m < 2, (m-2)/2 < 0 so the conversion will not work, and we must use
30
 *               a second conversion. 
30
 *               a second conversion.
31
 *    Note the division by p; this seems unavoidable
31
 *    Note the division by p; this seems unavoidable
32
 *    for m < 2, since the F density has a singularity as x (or p) -> 0.
32
 *    for m < 2, since the F density has a singularity as x (or p) -> 0.
33
 */
33
 */
34
 
34
 
35
#include "nmath.h"
35
#include "nmath.h"
36
#include "dpq.h"
36
#include "dpq.h"
37
 
37
 
38
double df(double x, double m, double n, int give_log)
38
double df(double x, double m, double n, int give_log)
39
{ 
39
{
40
    double p, q, f, dens;
40
    double p, q, f, dens;
41
 
41
 
42
#ifdef IEEE_754
42
#ifdef IEEE_754
43
    if (ISNAN(x) || ISNAN(m) || ISNAN(n))
43
    if (ISNAN(x) || ISNAN(m) || ISNAN(n))
44
	return x + m + n;
44
	return x + m + n;
45
#endif
45
#endif
46
    if (m <= 0 || n <= 0) ML_ERR_return_NAN;
46
    if (m <= 0 || n <= 0) ML_ERR_return_NAN;
47
    if (x <= 0.) return(R_D__0);
47
    if (x <= 0.) return(R_D__0);
48
    if (!R_FINITE(m) && !R_FINITE(n)) /* both +Inf */
48
    if (!R_FINITE(m) && !R_FINITE(n)) { /* both +Inf */
-
 
49
	if(x == 1.) return ML_POSINF;
49
	ML_ERR_return_NAN;
50
	/* else */  return R_D__0;
-
 
51
    }
50
    if (!R_FINITE(n)) /* must be +Inf by now */
52
    if (!R_FINITE(n)) /* must be +Inf by now */
51
	return(dgamma(x, m/2, 2./m, give_log));
53
	return(dgamma(x, m/2, 2./m, give_log));
52
    if (m > 1e14) {/* includes +Inf: code below is inaccurate there */
54
    if (m > 1e14) {/* includes +Inf: code below is inaccurate there */
53
	dens = dgamma(1./x, n/2, 2./n, give_log);
55
	dens = dgamma(1./x, n/2, 2./n, give_log);
54
	return give_log ? dens - 2*log(x): dens/(x*x);
56
	return give_log ? dens - 2*log(x): dens/(x*x);
Line 56... Line 58...
56
 
58
 
57
    f = 1./(n+x*m);
59
    f = 1./(n+x*m);
58
    q = n*f;
60
    q = n*f;
59
    p = x*m*f;
61
    p = x*m*f;
60
 
62
 
61
    if (m >= 2) { 
63
    if (m >= 2) {
62
	f = m*q/2;
64
	f = m*q/2;
63
	dens = dbinom_raw((m-2)/2, (m+n-2)/2, p, q, give_log);
65
	dens = dbinom_raw((m-2)/2, (m+n-2)/2, p, q, give_log);
64
    }
66
    }
65
    else { 
67
    else {
66
	f = m*m*q / (2*p*(m+n));
68
	f = m*m*q / (2*p*(m+n));
67
	dens = dbinom_raw(m/2, (m+n)/2, p, q, give_log);
69
	dens = dbinom_raw(m/2, (m+n)/2, p, q, give_log);
68
    }
70
    }
69
    return(give_log ? log(f)+dens : f*dens);
71
    return(give_log ? log(f)+dens : f*dens);
70
}
72
}