package umontreal.iro.lecuyer.gof;
/**
* This class provides methods to compute (or approximate)
* the distribution functions of special types of
* goodness-of-fit test statistics.
*
*/
public class FDist {
private FDist() {}
/**
* Similar to
* {@link umontreal.iro.lecuyer.probdist.KolmogorovSmirnovPlusDist KolmogorovSmirnovPlusDist}
* but for the case where the distribution function F has a jump of size
* a at a given point x0, is zero at the left of x0,
* and is continuous at the right of x0.
* Restriction: 0 < a < 1.
*
* @param N sample size
*
* @param a size of the jump
*
* @param x positive or negative Kolmogorov-Smirnov statistic
*
* @return the distribution function of the statistic evaluated at x
*
*/
public static double kolmogorovSmirnovPlusJumpOne (int N, double a,
double x) {
final double EPSILONLR = 1.E-15;
final double EPSILON = 1.0E-290;
final double NXAPARAM = 6.5; // frontier: alternating series
double LogCom;
double q, p1, q1;
double Sum = 0.0;
double term;
double Njreal;
double jreal;
int Sign;
int j;
int jmax;
if (N < 1)
throw new IllegalArgumentException (
"Calling kolmogorovSmirnovPlusJumpOne "+
"with N < 1");
if (a >= 1.0 || a <= 0.0)
throw new IllegalArgumentException (
"Calling kolmogorovSmirnovPlusJumpOne "+
"with a outside (0, 1)");
if (x <= 0.0)
return 0.0;
if (x + a >= 1.0)
return 1.0;
LogCom = Math.log ((double)N);
//--------------------------------------------------------------------
// the alternating series is stable and fast for N*(x + a) very small
//--------------------------------------------------------------------
if (N*(x + a) < NXAPARAM && a + x < 0.5) {
jmax = (int)(N*(x + a));
for (j = 1; j <= jmax; j++) {
jreal = j;
Njreal = N - j;
q = jreal/N - x;
if ((q < 0.0 && ((j & 1) != 0)) ||
((q > 1.0) && (((N - j - 1) & 1) != 0)))
Sign = -1;
else
Sign = 1;
// we must avoid log (0.0)
q1 = Math.abs (q);
p1 = Math.abs (1.0 - q);
if (q1 > EPSILON && p1 > EPSILON) {
term = LogCom + jreal*Math.log (q1) +
(Njreal - 1.0)*Math.log (p1);
Sum += Sign*Math.exp (term);
}
LogCom += Math.log (Njreal/(jreal + 1.0));
}
// add the term j = 0
Sum += Math.exp ((N - 1)*Math.log (1.0 + x));
return Sum*x;
}
//---------------------------------------------
// For N (x + a) >= NxaParam or (a + x) > 0.5,
// use the non-alternating series.
//---------------------------------------------
// EpsilonLR because the distribution has a jump
jmax = (int)(N*(1.0 - a - x - EPSILONLR));
for (j = 1; j <= jmax; j++) {
jreal = j;
Njreal = N - jreal;
q = jreal/N + x;
if (1.0 - q > EPSILON) {
term = LogCom + (jreal - 1.0)*Math.log (q) + Njreal*Math.log (1.0 - q);
Sum += Math.exp (term);
}
LogCom += Math.log (Njreal/(jreal + 1.0));
}
Sum *= x;
// add the term j = 0
if (1.0 - x > EPSILON)
Sum += Math.exp (N*Math.log (1.0 - x));
return 1.0 - Sum;
}
/**
* Returns F(m), the distribution function of the scan statistic
* with parameters N and d, evaluated at m.
* For a description of this statistic and its distribution, see
* {@link FBar#scan(int,double,int) scan},
* which computes its complementary distribution
*
* bar(F)(m) = 1 - F(m - 1).
*
* @param N sample size ( >= 2)
*
* @param d length of the test interval (∈(0, 1))
*
* @param m scan statistic
*
* @return the distribution function of the statistic evaluated at m
*/
public static double scan (int N, double d, int m) {
return 1.0 - FBar.scan (N, d, m);
}
}
Ads help maintain this website.