distriprob
Version:
A library for calculating the PDF, CDFs, and quantile function values of common probability distributions
217 lines (216 loc) • 5.9 kB
JavaScript
;
const async_1 = require("./async");
const random_1 = require("./random");
const cfs = require("./continuedFractionSolver");
const gamma = require("./gamma");
const rf = require("./rootFind");
// This import and then renaming of imports is necessary to allow the async module to
// correctly generate web worker scripts.
const lnGamma = gamma.lnGamma;
const continuedFractionSolver = cfs.continuedFractionSolver;
const rootFind = rf.rootFind;
function lnBeta(x, y) {
return (lnGamma(x) + lnGamma(y)) - lnGamma(x + y);
}
exports.lnBeta = lnBeta;
/**
* a function to calculate the "d_i" values from
* http://www.stat.tamu.edu/~jnewton/604/chap3.pdf pp.15-16
* in the calculation of the IB(incomplete beta function)
*
* @param i - the index of the d_i values
* @param x - parameter from the IB function
* @param a - parameter from the IB function
* @param b - parameter from the IB function
* @returns {any} - the d_i value
*/
function d(i, x, a, b) {
var result;
var m;
if (i % 2 === 0) {
m = i / 2;
result = (m * (b - m) * x) / ((a + 2 * m - 1) * (a + 2 * m));
}
else if (i % 2 === 1) {
m = (i - 1) / 2;
result = -((a + m) * (a + b + m) * x) / ((a + 2 * m) * (a + 2 * m + 1));
}
return result;
}
exports.d = d;
function continuedFraction(x, a, b) {
function num(j) {
if (j === 1) {
return 1;
}
else {
return d(j - 1, x, a, b);
}
}
function denom(j) {
if (j === 0) {
return 0;
}
else {
return 1;
}
}
return continuedFractionSolver(num, denom);
}
exports.continuedFraction = continuedFraction;
function lnIncompleteBeta(x, a, b) {
const comparator = (a + 1) / (a + b + 1);
if (x >= comparator) {
return Math.log(1 - Math.exp(lnIncompleteBeta(1 - x, b, a)));
}
const alnx = a * Math.log(x);
const bln1MinusX = b * Math.log(1 - x);
const lna = Math.log(a);
const lnBetaAB = lnBeta(a, b);
const lnContinuedFraction = Math.log(continuedFraction(x, a, b));
return alnx + bln1MinusX - lna - lnBetaAB + lnContinuedFraction;
}
exports.lnIncompleteBeta = lnIncompleteBeta;
function incompleteBeta(x, a, b) {
return Math.exp(lnIncompleteBeta(x, a, b));
}
exports.incompleteBeta = incompleteBeta;
function inverseIncompleteBeta(p, a, b) {
const lnIncompBeta = function (x) {
return lnIncompleteBeta(x, a, b);
};
const derivativeLnIncompleteBeta = function (x) {
const lnBetaAB = lnBeta(a, b);
const lnIncBetaXAB = lnIncompleteBeta(x, a, b);
const bMinus1TimesLn1MinusX = (b - 1) * Math.log(1 - x);
const aMinus1TimesLnX = (a - 1) * Math.log(x);
return Math.exp(bMinus1TimesLn1MinusX + aMinus1TimesLnX - lnBetaAB - lnIncBetaXAB);
};
return rootFind(lnIncompBeta, derivativeLnIncompleteBeta, Math.log(p), 0.5, 1, 0);
}
exports.inverseIncompleteBeta = inverseIncompleteBeta;
function pdfSync(x, alpha, beta) {
if (x < 0 || x > 1) {
return 0;
}
else {
return Math.exp(((alpha - 1) * Math.log(x)) + ((beta - 1) * Math.log(1 - x))
- lnBeta(alpha, beta));
}
}
exports.pdfSync = pdfSync;
function pdf(x, alpha, beta) {
return async_1.asyncGen([lnGamma, lnBeta], pdfSync, [x, alpha, beta]);
}
exports.pdf = pdf;
function cdfSync(x, alpha, beta, lowerTail = true) {
if (x <= 0) {
if (lowerTail) {
return 0;
}
else {
return 1;
}
}
else if (x >= 1) {
if (lowerTail) {
return 1;
}
else {
return 0;
}
}
else {
if (lowerTail) {
return incompleteBeta(x, alpha, beta);
}
else {
return incompleteBeta(1 - x, beta, alpha);
}
}
}
exports.cdfSync = cdfSync;
function cdf(x, alpha, beta, lowerTail = true) {
return async_1.asyncGen([
lnBeta,
lnGamma,
continuedFractionSolver,
d,
continuedFraction,
lnIncompleteBeta,
incompleteBeta
], cdfSync, [x, alpha, beta, lowerTail]);
}
exports.cdf = cdf;
function quantileSync(p, alpha, beta, lowerTail = true) {
function f(val) {
return cdfSync(val, alpha, beta, lowerTail);
}
function fPrime(val) {
if (lowerTail) {
return pdfSync(val, alpha, beta);
}
else {
return -pdfSync(val, alpha, beta);
}
}
const mean = alpha / (alpha + beta);
if (p === 0) {
if (lowerTail) {
return 0;
}
else {
return 1;
}
}
else if (p === 1) {
if (lowerTail) {
return 1;
}
else {
return 0;
}
}
else {
return rootFind(f, fPrime, p, mean, 1, 0);
}
}
exports.quantileSync = quantileSync;
function quantile(x, alpha, beta, lowerTail = true) {
return async_1.asyncGen([
rf.newton,
rf.bisection,
rootFind,
lnBeta,
lnGamma,
continuedFractionSolver,
d,
continuedFraction,
lnIncompleteBeta,
incompleteBeta,
pdfSync,
cdfSync
], quantileSync, [x, alpha, beta, lowerTail]);
}
exports.quantile = quantile;
function randomSync(n, alpha, beta, seed, randoms) {
return random_1.randSync(n, quantileSync, [alpha, beta], seed, randoms);
}
exports.randomSync = randomSync;
function random(n, alpha, beta, seed) {
return random_1.rand(n, quantileSync, [alpha, beta], seed, [
rf.newton,
rf.bisection,
rootFind,
lnBeta,
lnGamma,
continuedFractionSolver,
d,
continuedFraction,
lnIncompleteBeta,
incompleteBeta,
pdfSync,
cdfSync
]);
}
exports.random = random;