/*
* Mathlib : A C Library of Special Functions
* Copyright (C) 1998 Ross Ihaka
* Copyright (C) 2000-9 The R Development Core Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, a copy is available at
* http://www.r-project.org/Licenses/
*/
package jdistlib;
import static java.lang.Math.*;
import static jdistlib.math.MathFunctions.*;
import jdistlib.generic.GenericDistribution;
import jdistlib.math.MathFunctions;
import jdistlib.rng.RandomEngine;
/**
* Kendall tau distribution
*
*/
public class Kendall extends GenericDistribution {
static final long count(int k, int n, long w[][]) {
int i, u;
long sum;
u = (n * (n - 1) / 2);
if ((k < 0) || (k > u)) return(0);
if (w[n] == null) {
w[n] = new long[u+1]; // (double *) R_alloc(u + 1, sizeof(double));
//memset(w[n], '\0', sizeof(double) * (u+1));
for (i = 0; i <= u; i++)
w[n][i] = -1;
}
if (w[n][k] < 0) {
if (n == 1)
w[n][k] = (k == 0) ? 1 : 0;
else {
sum = 0;
for (i = 0; i < n; i++)
sum += count(k - i, n - 1, w);
w[n][k] = sum;
}
}
return(w[n][k]);
}
public static final double calculate_tau(double x, int n) {
return (4 * x - 2) / (n * (n - 1)) - 1;
}
public static final double calculate_count(double tau, int n) {
return 0.5 + (1.0 + tau) * n * (n - 1) / 4.0;
}
/**
* Density of Kendall distribution
* @param x This is count, not tau!
* @param n
* @return density
*/
public static final double density(double x, int n) {
long w[][] = new long[n+1][];
if (isNonInt(x) || x < 0 || x > (n * (n - 1) / 2)) return 0;
return count((int) x, n, w) / gammafn(n + 1);
}
/**
* Density of Kendall distribution
* @param tau This is tau, not count!
* @param n
* @return density
*/
public static final double density_tau(double tau, int n) {
return density(calculate_count(tau, n), n);
}
/**
* Cumulative density function of Kendall distribution.
* Kendall statistics: x = round((rho + 1) * n * (n-1) / 4);
*
Two-sided test: min(1, 2*((q > n*(n-1)/4) ? 1-cumulative(x-1,n) : cumulative(x,n)));
*
Greater test: 1-cumulative(x-1,n)
*
Less test: cumulative(x,n)
* @param x This is count, not tau!
* @param n
* @return cumulative
*/
public static final double cumulative(double x, int n) {
double p, q;
long w[][] = new long[n+1][];
q = floor(x + 1e-7);
if (q < 0)
return 0;
if (q > (n * (n - 1) / 2))
return 1;
p = 0;
for (int j = 0; j <= q; j++) {
p += count(j, n, w);
}
return exp(log(p) - lgammafn(n + 1));
}
/**
* Cumulative distribution of Kendall distribution
* @param tau This is tau, not count!
* @param n
* @return cumulative
*/
public static final double cumulative_tau(double tau, int n) {
return cumulative(calculate_count(tau, n), n);
}
/**
* Quantile search.
* @param p
* @param n
* @return count
*/
public static final double quantile(double p, int n) {
if (Double.isNaN(p) || MathFunctions.isInfinite(p)) return p;
if (p < 0 || p > 1 || n < 2) return Double.NaN;
double mu, sigma;
mu = n * (n-1)/4.0;
sigma = sqrt((n * (2.0 * n + 1) * (n + 1) / 6.0 - n) / 12.0);
long k = (long) (sigma * Normal.quantile(p, 0., 1., true, false) + mu + 0.5);
if (p <= cumulative(k, n)) {
do {
k--;
if (p > cumulative(k, n)) return k + 1.5;
} while (k > 0);
} else {
do {
k++;
if (p <= cumulative(k, n)) return k + 0.5;
} while (true);
}
return k + 0.5;
}
public static final double quantile_tau(double p, int n) {
return calculate_count(quantile(p, n), n);
}
/**
* Kendall RNG by inversion
* @param n
* @param random
* @return random variate
*/
public static final double random(int n, RandomEngine random) {
double u1 = random.nextDouble();
u1 = (int) (134217728 * u1) + random.nextDouble();
u1 = quantile(u1 / 134217728, n);
return u1;
}
public static final double[] random(int count, int n, RandomEngine random) {
double[] rand = new double[count];
for (int i = 0; i < count; i++)
rand[i] = random(n, random);
return rand;
}
protected int n;
public Kendall(int n) {
this.n = n;
}
@Override
public double density(double x, boolean log) {
return log ? log(density(x, n)) : density(x, n);
}
@Override
public double cumulative(double p, boolean lower_tail, boolean log_p) {
p = cumulative(p, n);
return log_p ? log(lower_tail ? p : 1-p) : (lower_tail ? p : 1-p);
}
@Override
public double quantile(double q, boolean lower_tail, boolean log_p) {
if (log_p) q = exp(q);
if (!lower_tail) q = 1 - q;
return quantile(q, n);
}
@Override
public double random() {
return random(n, random);
}
/*
public static final void main(String[] args) {
System.out.println(cumulative(26-1, 9));
System.out.println(cumulative_tau(0.36111111111111116045, 9));
System.out.println(quantile_tau(0.9402805335097011, 9));
System.out.println(density_tau(0, 10));
System.out.println(density_tau(1, 10));
System.out.println(cumulative_tau(0, 10));
System.out.println(cumulative_tau(0.42222222222222227650, 10));
System.out.println(cumulative_tau(0.26315789473684203514, 20));
System.out.println(quantile_tau(0.95, 10));
System.out.println(quantile_tau(0.95, 20));
}
//*/
}
Ads help maintain this website.