distriprob
Version:
A library for calculating the PDF, CDFs, and quantile function values of common probability distributions
152 lines (151 loc) • 4.59 kB
JavaScript
;
const gamma = require("./gamma");
const beta = require("./beta");
const rf = require("./rootFind");
const cfs = require("./continuedFractionSolver");
const pf = require("./primeFactors");
const async_1 = require("./async");
const random_1 = require("./random");
// 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 lnFactorial = gamma.lnFactorial;
const incompleteBeta = beta.incompleteBeta;
const discreteQuantileFind = rf.discreteQuantileFind;
const continuedFractionSolver = cfs.continuedFractionSolver;
const lnFactorialFractionEval = pf.lnFactorialFractionEval;
function lnBinomialCoefficient(n, chooseK) {
if (typeof n !== "number" || typeof chooseK !== "number") {
throw new Error(`The binomial coefficient function is only defined for numeric${""} arguments n and k.`);
}
if (n < chooseK) {
throw new Error(`The binomial coefficient function is only defined for n greater${""} than or equal to k.`);
}
if (!Number.isInteger(n) || !Number.isInteger(chooseK)) {
throw new Error(`The binomial coefficient function is defined for integer${""} arguments n and k.`);
}
if (chooseK === 0 || chooseK === n) {
return 0;
}
return lnFactorialFractionEval([n], [chooseK, n - chooseK]);
}
exports.lnBinomialCoefficient = lnBinomialCoefficient;
function pmfSync(k, trials, probSuccess) {
const p = probSuccess;
if (!Number.isInteger(k) || k < 0 || k > trials) {
return 0;
}
else {
return Math.exp(lnBinomialCoefficient(trials, k) + (k * Math.log(p)) +
((trials - k) * Math.log(1 - p)));
}
}
exports.pmfSync = pmfSync;
function pmf(k, trials, probSuccess) {
return async_1.asyncGen([
pf.primesLessThanOrEqualTo,
pf._factorialPrimes,
pf.factorialPrimes,
lnFactorialFractionEval,
lnBinomialCoefficient
], pmfSync, [k, trials, probSuccess]);
}
exports.pmf = pmf;
function cdfSync(k, trials, probSuccess, lowerTail = true) {
if (k < 0) {
if (lowerTail) {
return 0;
}
else {
return 1;
}
}
else if (k > trials) {
if (lowerTail) {
return 1;
}
else {
return 0;
}
}
else {
k = Math.floor(k);
if (lowerTail) {
return incompleteBeta(1 - probSuccess, trials - k, k + 1);
}
else {
return incompleteBeta(probSuccess, k + 1, trials - k);
}
}
}
exports.cdfSync = cdfSync;
function cdf(k, trials, probSuccess, lowerTail = true) {
return async_1.asyncGen([
beta.lnBeta,
gamma.lnGamma,
continuedFractionSolver,
beta.d,
beta.continuedFraction,
beta.lnIncompleteBeta,
beta.incompleteBeta
], cdfSync, [k, trials, probSuccess, lowerTail]);
}
exports.cdf = cdf;
function quantileSync(p, trials, probSuccess, lowerTail = true) {
function simplifiedCDF(val) {
return cdfSync(val, trials, probSuccess, lowerTail);
}
if (p === 0) {
if (lowerTail) {
return 0;
}
else {
return trials;
}
}
else if (p === 1) {
if (lowerTail) {
return trials;
}
else {
return 0;
}
}
else {
const mean = Math.floor(trials * p);
return discreteQuantileFind(simplifiedCDF, p, trials, 0, mean, lowerTail);
}
}
exports.quantileSync = quantileSync;
function quantile(p, trials, probSuccess, lowerTail = true) {
return async_1.asyncGen([
discreteQuantileFind,
beta.lnBeta,
gamma.lnGamma,
continuedFractionSolver,
beta.d,
beta.continuedFraction,
beta.lnIncompleteBeta,
beta.incompleteBeta,
cdfSync
], quantileSync, [p, trials, probSuccess, lowerTail]);
}
exports.quantile = quantile;
function randomSync(n, trials, probSuccess, seed, randoms) {
return random_1.randSync(n, quantileSync, [trials, probSuccess], seed, randoms);
}
exports.randomSync = randomSync;
function random(n, trials, probSuccess, seed) {
return random_1.rand(n, quantileSync, [trials, probSuccess], seed, [
discreteQuantileFind,
beta.lnBeta,
gamma.lnGamma,
continuedFractionSolver,
beta.d,
beta.continuedFraction,
beta.lnIncompleteBeta,
beta.incompleteBeta,
cdfSync
]);
}
exports.random = random;