UNPKG

distriprob

Version:

A library for calculating the PDF, CDFs, and quantile function values of common probability distributions

152 lines (151 loc) 4.59 kB
"use strict"; 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;