The R Project SVN R

Rev

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

Rev 3921 Rev 4562
Line 1... Line 1...
1
/*
1
/*
2
 *  Mathlib : A C Library of Special Functions
2
 *  Mathlib : A C Library of Special Functions
3
 *  Copyright (C) 1998 Ross Ihaka
3
 *  Copyright (C) 1998 Ross Ihaka
-
 
4
 *  Copyright (C) 1999 R Core Team
4
 *
5
 *
5
 *  This program is free software; you can redistribute it and/or modify
6
 *  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
 *  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
 *  the Free Software Foundation; either version 2 of the License, or
8
 *  (at your option) any later version.
9
 *  (at your option) any later version.
Line 28... Line 29...
28
 
29
 
29
#include "Mathlib.h"
30
#include "Mathlib.h"
30
 
31
 
31
double phyper(double x, double NR, double NB, double n)
32
double phyper(double x, double NR, double NB, double n)
32
{
33
{
33
    double N, xstart, xend, xr, xb, sum, ltrm;
34
/* Sample of  n balls from  NR red  and  NB black ones;  x are red */
34
 
35
 
-
 
36
/* basically the same code is used also in  ./qhyper.c -- keep in sync! */
-
 
37
    double N, xstart, xend, xr, xb, sum, term;
-
 
38
    int small_N;
35
#ifdef IEEE_754
39
#ifdef IEEE_754
36
    if(ISNAN(x) || ISNAN(NR) || ISNAN(NB) || ISNAN(n))
40
    if(ISNAN(x) || ISNAN(NR) || ISNAN(NB) || ISNAN(n))
37
	return x + NR + NB + n;
41
	return x + NR + NB + n;
38
    if(!finite(x) || !finite(NR) || !finite(NB) || !finite(n)) {
42
    if(!finite(x) || !finite(NR) || !finite(NB) || !finite(n)) {
39
	ML_ERROR(ME_DOMAIN);
43
	ML_ERROR(ME_DOMAIN);
Line 48... Line 52...
48
    n = floor(n + 0.5);
52
    n = floor(n + 0.5);
49
    if (NR < 0 || NB < 0 || n < 0 || n > N) {
53
    if (NR < 0 || NB < 0 || n < 0 || n > N) {
50
	ML_ERROR(ME_DOMAIN);
54
	ML_ERROR(ME_DOMAIN);
51
	return ML_NAN;
55
	return ML_NAN;
52
    }
56
    }
-
 
57
    small_N = (N < 1000); /* won't have underflow in product below */
53
    xstart = fmax2(0, n - NB);
58
    xstart = fmax2(0, n - NB);
54
    xend = fmin2(n, NR);
59
    xend = fmin2(n, NR);
55
    if(x < xstart) return 0.0;
60
    if(x < xstart) return 0.0;
56
    if(x >= xend) return 1.0;
61
    if(x >= xend) return 1.0;
57
    xr = xstart;
62
    xr = xstart;
58
    xb = n - xr;
63
    xb = n - xr;
-
 
64
    /* if N is small,  term := product.ratio( bin.coef );
-
 
65
       otherwise work with its logarithm to protect against underflow */
59
    ltrm = lfastchoose(NR, xr) + lfastchoose(NB, xb) - lfastchoose(N, n);
66
    term = lfastchoose(NR, xr) + lfastchoose(NB, xb) - lfastchoose(N, n);
-
 
67
    if(small_N) term = exp(term);
60
    NR = NR - xr;
68
    NR -= xr;
61
    NB = NB - xb;
69
    NB -= xb;
62
    sum = 0.0;
70
    sum = 0.0;
63
    while(xr <= x) {
71
    while(xr <= x) {
64
	sum += exp(ltrm);
72
	sum += (small_N ? term : exp(term));
65
	xr++;
73
	xr++;
66
	NB++;
74
	NB++;
-
 
75
	if(small_N) term *= (NR / xr) * (xb / NB);
67
	ltrm += log((NR / xr) * (xb / NB));
76
	else	term += log((NR / xr) * (xb / NB));
68
	xb--;
77
	xb--;
69
	NR--;
78
	NR--;
70
    }
79
    }
71
    return sum;
80
    return sum;
72
}
81
}